Перейти к содержанию
    

Как убрать варнинги

В 29.02.2024 в 15:38, _4afc_ сказал:

Вот так выглядит написанное Вами текстовое описания аппаратуры.

Покажите пожалуйста хороший вариант?

У меня в архитектуре несколько процессов которые заведуют разными вещами. То есть логичнее каждый процесс вытащить в отдельный entity/module так чтоли?? 

Тогда на диаграмме будут модули блоками показаны или это не принципиально?

В 29.02.2024 в 15:38, _4afc_ сказал:

//исходные LUT8+LUT8+LUT8+R = 1.627+1.627+1.627+0.380=5.261nS - 1 такт 190МГц

always @( posedge C ) if( CE & A[3:0] & B[1:0] & Z[13:0]) Q<=X;

А почему тут именно LUT8??

Как я понимаю:

CE & A[3:0] = на вход подаем CE и  A[3:0] то есть 5 сигналов. значит используем LUT5??

& B[1:0] = один выход с первого условия и 2 сигнала отсюда = LUT4

& Z[13:0] = один с предыдущего и 14 тут = LUT8*2 

Q<=X; = R

 

тогда LUT5 + LUT4 + ( LUT8*2 ) + R.

Правильно или нет?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 2/29/2024 at 3:50 PM, Worldmaster said:

CE & A[3:0] = на вход подаем CE и  A[3:0] то есть 5 сигналов. значит используем LUT5??

& B[1:0] = один выход с первого условия и 2 сигнала отсюда = LUT4

А можно и по-другому

CE & A[3:0]& B[1:0]  в один LUT, например...
Ну и  - я не в курсе, как там ресурсы распределены физически в кристалле, синтезатор сам должен оптимизировать исходя из заданных условий оптимизации (скорость или размер, к примеру).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Worldmaster said:

 

Что значит умирают?

 

https://nandland.com/variables-vs-signals/

variable не будут видны в другом процессе

если нужен фифо опишите его отдельно - разбейте Вашу логику на более простые и понятные модули

Двухклоковый фифо я выкладывал... 

Посмотрите как переходите через клоковые домены - правильно? sdc or xdc для логики написаны которая отвечает за коректный переход между клоковыми доменами

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Worldmaster said:

У меня в архитектуре несколько процессов которые заведуют разными вещами. То есть логичнее каждый процесс вытащить в отдельный entity/module так чтоли?? 

Если будет отдельный модуль, а его выходы будут внутри подключены к регистрам - вы начнёте понимать как писать на ПЛИС.

 

1 hour ago, Worldmaster said:

Покажите пожалуйста хороший вариант?

Например модуль останавливающий работу FSM на 600/3600/36000/900000 тактов

займёт 36 регистров, 44 LUT, с максимальной частотой 306МГц и 2 уровнями логики для GW2A GW5A_ES и будет выглядеть так:

Spoiler

PauseMSv4.thumb.png.ae0260751b30cfdc2ccd55cf650babac.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 minutes ago, _4afc_ said:

Если будет отдельный модуль, а его выходы будут внутри подключены к регистрам - вы начнёте понимать как писать на ПЛИС.

Например модуль останавливающий работу FSM на 600/3600/36000/900000 тактов

например

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity PauseCounter is
    generic (
        COUNT_WIDTH : integer := 16
    );
    port (
        clk         : in  std_logic;
        rst         : in  std_logic;
        load        : in  std_logic;
        pause_value : in  unsigned(COUNT_WIDTH - 1 downto 0);
        done        : out std_logic
    );
end entity PauseCounter;

architecture Behavioral of PauseCounter is
    signal count : unsigned(COUNT_WIDTH - 1 downto 0) := (others => '0');
    signal counting : std_logic;
    signal shift_counting : std_logic;
    signal reg_strob : std_logic;
    signal reg_ready : std_logic;
    
begin
    process (clk, rst)
    begin
        if rst = '1' then
            count <= (others => '0');
            counting <= '0';
            reg_ready <= '0';
            shift_counting <= '0';
        elsif rising_edge(clk) then
            shift_counting <= counting;
            if load = '1' then
                count <= pause_value;
                counting <= '1';
                reg_ready <= '0';
            elsif counting = '1' then
                if count = 0 then
                    counting <= '0';
                    reg_ready <= '1';
                    count <= count;
                else
                    count <= count - 1;
                    reg_ready <= '0';
                    counting <= '1';
                end if;
            end if;
        end if;
    end process;
    
    reg_strob <= shift_counting and not(counting);
    
    --done <= reg_ready;
    done <= reg_strob;
    
    

end Behavioral;

 

пример использования

 library ieee;
 use ieee.std_logic_1164.all;
 use ieee.numeric_std.all;
 
 entity spi_config is
 generic(
	N                     : integer := 24;      -- number of bit to serialize
	CLK_DIV               : integer := 1 );  -- input clock divider to generate output serial clock; o_sclk frequency = i_clk/(2*CLK_DIV)
  port (
	clk                   : in  std_logic;
	rst                   : in  std_logic;
	
	start            	  : in  std_logic;  
	ready              	  : out std_logic;
	
	busy_spi              : out std_logic;
	
	-- spi
	o_sclk                : out std_logic;
	o_ss                  : out std_logic;
	o_mosi                : out std_logic;
	i_miso                : in  std_logic
 );	
	
 end spi_config;
 
 architecture rtl of spi_config is
 
 COMPONENT power_on_start is
	Port ( 
		clk  : in  std_logic;   
		rst  : in std_logic;
		start_up : out std_logic
	); 
 end COMPONENT;
 
 COMPONENT spi_controller is
 generic(
	N                     : integer := 24;      -- number of bit to serialize
	CLK_DIV               : integer := 1 );  -- input clock divider to generate output serial clock; o_sclk frequency = i_clk/(2*CLK_DIV)
  port (
	i_clk                 : in  std_logic;
	i_rstb                : in  std_logic;
	i_tx_start            : in  std_logic;  -- start TX on serial line
	o_tx_end              : out std_logic;  -- TX data completed; o_data_parallel available
	i_data_parallel       : in  std_logic_vector(N-1 downto 0);  -- data to sent
	o_data_parallel       : out std_logic_vector(N-1 downto 0);  -- received data
	o_sclk                : out std_logic;
	o_ss                  : out std_logic;
	o_mosi                : out std_logic;
	i_miso                : in  std_logic);
 end COMPONENT;
 
 COMPONENT PauseCounter is
    generic (
        COUNT_WIDTH : integer := 16
    );
    port (
        clk         : in  std_logic;
        rst         : in  std_logic;
        load        : in  std_logic;
        pause_value : in  unsigned(COUNT_WIDTH - 1 downto 0);
        done        : out std_logic
    );
 end COMPONENT;
 
 type state_type is (
                          idle_st   ,
						  pause_st	,
						  send_config_data   ,
						  pause2_st,
                          send_config_data2     );
						  
 -- Declare current and next state signals
 SIGNAL current_state, nxt_state : state_type;
						  
 signal reg_tx_start    		: std_logic;
 signal reg_tx_end      		: std_logic;
 signal reg_indata_parallel 	: std_logic_vector(N-1 downto 0);
 signal reg_outndata_parallel 	: std_logic_vector(N-1 downto 0);
 
 signal reg_start_pause			: std_logic;
 signal reg_end_pause			: std_logic;
 signal reg_value_pause			: unsigned(15 downto 0);
 signal reg_busy                : std_logic;
 signal reg_start_up            : std_logic;
 signal reg_start               : std_logic;
 				  
 begin
 
 busy_spi <= reg_busy;
 reg_start <= reg_start_up or start;
 
  start_up_inst : power_on_start 
	Port map( 
		clk  => clk, 
		rst  => rst,
		start_up => reg_start_up
	); 

 spi_controller_inst:  spi_controller 
 generic map(
	N                     => N,      	-- number of bit to serialize
	CLK_DIV               => CLK_DIV 	-- input clock divider to generate output serial clock; o_sclk frequency = i_clk/(2*CLK_DIV)
	)
  port map(
	i_clk                 => clk,
	i_rstb                => not(rst),
	
	i_tx_start            => reg_tx_start,  -- start TX on serial line
	o_tx_end              => reg_tx_end,  -- TX data completed; o_data_parallel available
	
	i_data_parallel       => reg_indata_parallel,  -- data to sent
	o_data_parallel       => reg_outndata_parallel,  -- received data
	
	o_sclk                => o_sclk,
	o_ss                  => o_ss,
	o_mosi                => o_mosi,
	i_miso                => o_mosi --i_miso	
 );
 
  PauseCounter_inst: PauseCounter 
    generic map(
        COUNT_WIDTH => 16
    )
    port map(
        clk         => clk,
        rst         => rst,
        load        => reg_start_pause,
        pause_value => reg_value_pause,
        done        => reg_end_pause
    );

 --------------------------------------------------------------------------
 clocked_proc : PROCESS (all)
 --------------------------------------------------------------------------
 BEGIN
 IF (rst = '1') THEN
	current_state <= idle_st;
 -- Default Reset Values
	reg_tx_start <= '0';
	reg_indata_parallel <= (others => '0');
	ready <= '0';
	reg_start_pause <= '0';
	reg_value_pause <= (others => '0');
	reg_busy <= '0';
		
 ELSIF (clk'EVENT AND clk = '1') THEN
 current_state <= nxt_state;
 
 -- Combined Actions
 CASE current_state IS
 WHEN idle_st =>
    ready <= '0';
	if reg_start = '1' THEN
		reg_start_pause <= '1';
		reg_value_pause <= to_unsigned(CLK_DIV*2, reg_value_pause'length);
	else
		reg_start_pause <= '0';
		--reg_indata_parallel <= (others => '0');
	end if;
	
 WHEN pause_st =>
    reg_start_pause <= '0';
	if reg_end_pause = '1' THEN
		reg_tx_start <= '1';
		reg_busy <= '1';
		reg_indata_parallel <= '0' & "10" & "0000000010100" & "00000010";  -- R_W & W1_W0 & A12-A0 & D7-D0  -- Data can be sent in either MSB-first mode  --std_logic_vector(to_unsigned(170, reg_indata_parallel'length));
	else
		reg_tx_start <= '0';
		reg_indata_parallel <= std_logic_vector(to_unsigned(0, reg_indata_parallel'length));
	end if;
		
	
 WHEN send_config_data =>
    reg_tx_start <= '0';
	if reg_tx_end = '1' THEN
		reg_start_pause <= '1';
		reg_value_pause <= to_unsigned(CLK_DIV*2, reg_value_pause'length);
		reg_indata_parallel <= std_logic_vector(to_unsigned(0, reg_indata_parallel'length));
	else
		reg_start_pause <= '0';
		
	end if;	
	
  WHEN pause2_st =>
    reg_start_pause <= '0';
	if reg_end_pause = '1' THEN
		reg_tx_start <= '1';
		reg_indata_parallel <= '0' & "10" & "1111111111111" & "00000001"; -- R_W & W1_W0 & A12-A0 & D7-D0  -- Data can be sent in either MSB-first mode  --std_logic_vector(to_unsigned(85, reg_indata_parallel'length));
	else
		reg_tx_start <= '0';
		--reg_indata_parallel <= std_logic_vector(to_unsigned(0, reg_indata_parallel'length));
	end if;
 
 WHEN send_config_data2 =>
    reg_tx_start <= '0';
	if reg_tx_end = '1' THEN
		ready <= '1';
		reg_busy <= '0';
		reg_indata_parallel <= std_logic_vector(to_unsigned(0, reg_indata_parallel'length));
	else
		ready <= '0';
		--reg_indata_parallel <= (others => '0');
	end if;
	
 WHEN OTHERS => NULL;
 END CASE;
 END IF;

 END PROCESS clocked_proc; 
 
 --------------------------------------------------------------------------
 nextstate_proc : PROCESS ( all )
 --------------------------------------------------------------------------
 BEGIN
 CASE current_state IS
 
 WHEN idle_st => 
	IF (reg_start = '1') THEN
		nxt_state <= pause_st;
	ELSE
		nxt_state <= idle_st;
	END IF;
	
 WHEN pause_st =>
 	if reg_end_pause = '1' THEN
 	  nxt_state <= send_config_data;
 	else
 	  nxt_state <= pause_st;  
    end if;
	
 WHEN send_config_data =>
	if reg_tx_end = '1' THEN
		nxt_state <= pause2_st;
	else
		nxt_state <= send_config_data;
	end if;	
	
  WHEN pause2_st =>
 	if reg_end_pause = '1' THEN
 	  nxt_state <= send_config_data2;
 	else
 	  nxt_state <= pause2_st;  
    end if;

 WHEN send_config_data2 =>	
    if reg_tx_end = '1' THEN
		nxt_state <= idle_st;
	else
		nxt_state <= send_config_data2;
	end if;
	
 WHEN OTHERS => nxt_state <= idle_st;
 END CASE;

 END PROCESS nextstate_proc; 
 
 end rtl;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

32 minutes ago, Maverick_ said:

например

COUNT_WIDTH : integer := 16

Для 900000 вероятно 24 бита.

Как ваш пример:

  • выглядит в схематике любого IDE?
  • сколько занимает Reg/LUT?
  • сколько слоёв логики?
  • на какой максимальной частоте может работать?

В приведённом мной примере для решения задачи достаточно было 4 фиксированных варианта паузы, поэтому они задаются 2 битами, ваш более общий на любую величину.

 

PS: Посмотрел ваш вариант, получилось: займёт 26 регистров, 54 LUT, с максимальной частотой 146МГц и 5 уровнями логики для GW5A_ES и будет выглядеть так:

PauseCounter.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если хотите увеличить частоту можно применить конвеерний счетчик - вместо встроенного в модуль PauseCounter сигнала count

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity PipelinedCounter is
    generic (
        width_g: natural := 64; -- Must be divisible by parts_g.
        parts_g: natural := 4
    );
    
    port (
        clk:            in std_logic;
        rst:          in std_logic;
        
        clear:          in std_logic;
        enable:         in std_logic;
        
        count:          out std_logic_vector(width_g - 1 downto 0);
        tick:           out std_logic
    );
end entity;

architecture rtl of PipelinedCounter is
    constant part_width_c:      natural := width_g / parts_g;
    signal almost_tick_r:       std_logic_vector(parts_g - 1 downto 0);
    signal count_r:             std_logic_vector(width_g - 1 downto 0);
begin
    count <= count_r;

    process (all)
        variable part_v:        unsigned(part_width_c - 1 downto 0);
        variable tick_v:        std_logic;
    begin
        if rst = '1' then
            count_r <= (others => '0');
            almost_tick_r <= (others => '0');
            tick <= '0';
        elsif rising_edge(clk) then
            
            tick_v := enable;
            for i in 0 to parts_g - 1 loop
                part_v := unsigned(count_r((i + 1) * part_width_c - 1 downto i * part_width_c));
                
                if tick_v = '1' then
                    -- Value is max - 1?
                    if part_v = to_unsigned(2**part_width_c - 2, part_width_c) then
                        almost_tick_r(i) <= '1';
                    else
                        almost_tick_r(i) <= '0';
                    end if;
                
                    part_v := part_v + 1;
                end if;
                
                count_r((i + 1) * part_width_c - 1 downto i * part_width_c) <=
                    std_logic_vector(part_v);
                
                tick_v := tick_v and almost_tick_r(i);
            end loop;
            tick <= tick_v;
            
            if clear = '1' then
                count_r <= (others => '0');
                almost_tick_r <= (others => '0');
                tick <= '0';
            end if;
        end if;
    end process;
end architecture;

он разбит по 4 бита

1 hour ago, _4afc_ said:

Для 900000 вероятно 24 бита.

Как ваш пример:

  • выглядит в схематике любого IDE?

 

image.thumb.png.6a4e6e4c0088237072585e1bdc59b055.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 29.02.2024 в 16:41, Maverick_ сказал:

variable не будут видны в другом процессе

А зачем мне видеть их в других процессах. Это локальные переменные можно сказать и используются только внутри одного процесса.

 

В 29.02.2024 в 16:41, Maverick_ сказал:

если нужен фифо опишите его отдельно

Так и сделано. Есть модуль FIFO, SDRAM, i2c.

Но в основной архитектуре добавились процессы которые координируют потоки данных между ними. Нужно и с камер снимать данные укладывая их в оперативу и если прилетел запрос с FIFO то отрабатывать его и одновременно выкидывать в него данные из оперативы, а еще не забыть i2c и с периферии снимать показания.

Просто я так понял что вы склоняете к тому что все управляющие процессы вынести тоже в отдельные компоненты, тогда видимо и диаграмма будет более понятная. А потом просто связать сигналы всех этих блоков в топовой архитектуре. Так ведь?

 

В 29.02.2024 в 16:41, Maverick_ сказал:

Двухклоковый фифо я выкладывал... 

Я смотрел ваш пример но так и не нашел варианта как его встроить к себе. А возможно что у себя я и сделал нечто такое же. У меня есть процесс который закладывает данные в RAM по нужному адресу но когда приходит запрос с FIFO он производит передачу блоков из RAM в буфер отправки FIFO. Пока освобождается один буфер, процесс закидывает данные из камер в RAM, потом если буфер пуст то производит чтения из рамы. 

 

В 29.02.2024 в 16:55, _4afc_ сказал:

Например модуль останавливающий работу FSM на 600/3600/36000/900000 тактов

Линий маловато. А есть чтонибудь большое большое. Камеры например какие нибудь или что нибудь из периферии .. Мне кажется что тоже будет такая же каша на диаграмме как и у меня. 

ну либо с самого маленького кирпича собирать блоки, блоки объединять опять в блоки пока не получится один суперблок который в архитектуре будет просто соединять сигналы с железки и передавать их внутрь.

Изменено пользователем Worldmaster

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну и все равно не понятно что делать с коркой MIPI.

component mipi_rx
	port (
		reset_n: in std_logic;
		HS_CLK_P: in std_logic;
		HS_CLK_N: in std_logic;
		clk_byte_out: out std_logic;
		HS_DATA1_P: in std_logic;
		HS_DATA1_N: in std_logic;
		data_out1: out std_logic_vector(7 downto 0);
		HS_DATA0_P: in std_logic;
		HS_DATA0_N: in std_logic;
		data_out0: out std_logic_vector(7 downto 0);
		hs_en: in std_logic;
		clk_term_en: in std_logic;
		data_term_en: in std_logic;
		ready: out std_logic
	);
end component;



	MyMIPI1: mipi_rx
		port map (
			reset_n => Mipi_Rst_N,
	
			HS_CLK_P => CAM1_CLK_P,
			HS_CLK_N => CAM1_CLK_N,
	
			HS_DATA1_P => CAM1_DATA_P,
			HS_DATA1_N => CAM1_DATA_N,
			
			HS_DATA0_P => CAM1_DATA_2_P,
			HS_DATA0_N => CAM1_DATA_2_N,
			
			ready => Cam1_Mipi_Ready,
			clk_byte_out => Cam1_Mipi_Data_Read_Clk,		
			data_out1 => CAM1_MIPI_DATA_OUT1,
			data_out0 => CAM1_MIPI_DATA_OUT0,
			
			hs_en => Mipi_EN_N,
			clk_term_en => '1',
			data_term_en => '1'	
		);  


 

А процесс примитивный до нельзя.

	function rMod(value: integer;   maxSize: integer) return integer is
	begin
		if value >= maxSize then
			return value - maxSize;
		else 
			return value;
		end if;    
	end function;


Cam1_Read_Process: process (buffer_pointers_reset, Cam1_Mipi_Data_Read_Clk)
begin
if buffer_pointers_reset = '0' then
	cam1_write_ptr <= 0; 
elsif rising_edge(Cam1_Mipi_Data_Read_Clk) then 			 
	cam1_data_buffer(cam1_write_ptr) <= Cam1_Mipi_Data_Out0 & Cam1_Mipi_Data_Out1; 					
	cam1_write_ptr <= rMod(cam1_write_ptr + 1, MAX_BUF_CNT);
end if;
end process Cam1_Read_Process;

И все равно он показывает недобор частоты по CAM1_CLK.

С этим то что делать? Почему корка такая медленная?

image.thumb.png.04a69500430e6f5b0c322460906a3183.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

cam1_data_buffer - организация памяти какая - блочная память или регистровая или srl?

как синтезатор реализовал?

расскажите что физически процесс делает:

Cam1_Read_Process: process (buffer_pointers_reset, Cam1_Mipi_Data_Read_Clk)
begin
if buffer_pointers_reset = '0' then
	cam1_write_ptr <= 0; 
elsif rising_edge(Cam1_Mipi_Data_Read_Clk) then 			 
	cam1_data_buffer(cam1_write_ptr) <= Cam1_Mipi_Data_Out0 & Cam1_Mipi_Data_Out1; 					
	cam1_write_ptr <= rMod(cam1_write_ptr + 1, MAX_BUF_CNT);
end if;
end process Cam1_Read_Process;

то что пишет и читает вижу, точно нужно одновременность?

почему Вы не хотите написать подмодули с такторовой частатой clk и ресетом rst

в топ модуле соеденить все модули подав нужные частоты от PLL

не хотите сделать память отдельным модулем:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;


entity bram_tdp is
generic (
    DATA    : integer := 32;
    ADDR    : integer := 12
);
port (
    -- Port A
    a_clk   : in  std_logic;
    --ena     : in  std_logic;
	 a_wr    : in  std_logic;
    a_addr  : in  std_logic_vector(ADDR-1 downto 0);
    a_din   : in  std_logic_vector(DATA-1 downto 0);
    a_dout  : out std_logic_vector(DATA-1 downto 0);

    -- Port B
    b_clk   : in  std_logic;
	 --enb     : in  std_logic;
    b_wr    : in  std_logic;
    b_addr  : in  std_logic_vector(ADDR-1 downto 0);
    b_din   : in  std_logic_vector(DATA-1 downto 0);
    b_dout  : out std_logic_vector(DATA-1 downto 0)
);
end bram_tdp;

architecture rtl of bram_tdp is
    -- Shared memory
    type mem_type is array ( (2**ADDR)-1 downto 0 ) of std_logic_vector(DATA-1 downto 0);
    
    FUNCTION initialize_ram  return mem_type is variable result : mem_type;
    BEGIN
		FOR i IN ((2**ADDR)-1) DOWNTO 0 LOOP
			result(i) := std_logic_vector( to_unsigned(natural(i), natural'((DATA))));
		END LOOP;
    RETURN result;
    END initialize_ram;
    
--	 shared variable mem : mem_type := initialize_ram;
    shared variable mem : mem_type := (others => (others => '0')); -- := initialize_ram;
begin

-- Port A
process(a_clk)
begin
    if(a_clk'event and a_clk='1') then
--       if ena = '1' then
		 if(a_wr='1') then
            mem(conv_integer(a_addr)) := a_din;
        end if;
        a_dout <= mem(conv_integer(a_addr));
--    end if;
	 end if;
end process;

-- Port B
process(b_clk)
begin
   if(b_clk'event and b_clk='1') then
---		  if enb = '1' then	
        if(b_wr='1') then
            mem(conv_integer(b_addr)) := b_din;
        end if;
        b_dout <= mem(conv_integer(b_addr));
--    end if;
	 end if;
end process;

end rtl;

каждый подмодуль проверить на максимальную частоту (отдельный проект) - надо бы такое сделать  и за одно посмотреть как синтезатор Вас понимает - блочная память, DSP - схемотехника по RTL просматровщику 

написать тестбенч - промоделировать - с коркой и без например MIPI 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 01.03.2024 в 10:23, Maverick_ сказал:

как синтезатор реализовал?

Если я правильно понял что вот так: 

constant MAX_BUF_CNT : integer :=128;

type MEMBuffer is array (0 to MAX_BUF_CNT-1) of std_logic_vector(15 downto 0); 

signal cam1_data_buffer: MEMBuffer := (others=>(others=>'0')); 

Если надо по другому то покажите пожалуйста как.

 

В 01.03.2024 в 10:23, Maverick_ сказал:

расскажите что физически процесс делает:

Камера подключена к линиям mipi_rx. Корка получает данные и преобразует их в байты. 

Когда они готовы генерит сигнал Cam1_Mipi_Data_Read_Clk и процесс объединяет два байта в один блок и пишет в буфер.

В 01.03.2024 в 10:23, Maverick_ сказал:

то что пишет и читает вижу, точно нужно одновременность?

В чем одновременность? 

 

В 01.03.2024 в 10:23, Maverick_ сказал:

почему Вы не хотите написать подмодули с такторовой частатой clk и ресетом rst

в топ модуле соеденить все модули подав нужные частоты от PLL

Ну в данном случае для сбора данных нужен был всего один процесс. Поэтому и не стал городить надстройку. 

Вы хотите сказать что если сделать отдельный модуль MIPI_CTRL и туда перенести этот процесс то это радикально изменит ситуацию?

Для MIPI передачу данных определяет сама камера же. ЗАчем этому модулю еще какое то тактирование?

Изменено пользователем Worldmaster

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

что значит "Когда они готовы генерит сигнал Cam1_Mipi_Data_Read_Clk " ?

счетчики 

cam1_data_buffer(cam1_write_ptr) <= Cam1_Mipi_Data_Out0 & Cam1_Mipi_Data_Out1; 					
	cam1_write_ptr <= rMod(cam1_write_ptr + 1, MAX_BUF_CNT);

работают паралельно т.е. одновременно - пишиут и читают из одной ячейки памяти, судя по Вашему процессу

Тактовая частота на модулях должна быть постоянно - работает модуль в данный момент времени или нет определяет сигнал разрешения 

valid для данных или enable для модуля - например

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity modulo_cnt is
  port (
    clk     : in  std_logic;
    rst     : in  std_logic;

    -- inputs
    max_cnt : in  std_logic_vector;
    en      : in  std_logic;

    -- outputs
    zero    : out std_logic
  );
end modulo_cnt;
architecture rtl of modulo_cnt is
  -- normalize the unconstrained input
  alias max_cnt_norm : std_logic_vector(max_cnt'length - 1 downto 0) is max_cnt; -- normalized unconstrained input
  signal cnt : unsigned(max_cnt_norm'left downto 0);

begin
  counter_pr : process (clk)
  begin
    if (rising_edge(clk)) then
      if (rst = '1') then
        cnt <= unsigned(max_cnt_norm) - 1;
        zero <= '0';
      elsif (en = '1') then -- is counting enabled?
        if (cnt = 1) then -- use pipeline to assert zero
          zero <= '1'; -- together with cnt=0
        else
          zero <= '0';
        end if;
        if (zero = '1') then -- check if counter reached zero
          cnt <= unsigned(max_cnt_norm) - 1; -- reload with modulo_value-1
        else
          cnt <= cnt - 1; -- decrement counter
        end if;
      end if;
    end if;
  end process counter_pr;

end rtl;

попробуйте промоделировать - разберитесь с  enable для модуля

valid/ready для данных  модуль принимает данные по valid выдает модуль обработанные данные по сигналу ready

Для следующего модуля ready превращается в сигнал valid 

промоделируйте двухклоковое фифо ...

чаще всего FSM работает с сигналами valid/ready - т.е. дает разрешения работы или запрещает модуля или процесса

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Worldmaster said:

Линий маловато. А есть чтонибудь большое большое. Камеры например какие нибудь или что нибудь из периферии .. Мне кажется что тоже будет такая же каша на диаграмме как и у меня. 

ну либо с самого маленького кирпича собирать блоки, блоки объединять опять в блоки пока не получится один суперблок который в архитектуре будет просто соединять сигналы с железки и передавать их внутрь.

Да. Мне так удобнее. Написать универсальный (лучше параметризируемый) модуль с "always" внутри. Отсимулировать его во всех режимах.

И далее использовать уже эту абстракцию в своих модулях. Практически мои проекты состоят из модулей состоящих из модулей которые состоят из модулей...

Все модули содержат комментарий описывающий их назначение. Только самый нижний уровень, в моём идеале, содержит "always".

 

Дело в том, что описание ПЛИС на Verilog отличается от программы на C++ под CPU.

И основное отличие от CPU в том, что нельзя создать "глобальную переменную", которая будет менять своё значение от 5 разных подпрограмм.

В ПЛИС все переменные (REG) каждый такт меняются одновременно в зависимости от локальных условий (LUT).

 

Кратко:

  • на заводе с менеджментом CPU - рабочему (АЛУ) постоянно поступают приказы от любого количества руководителей, причём устно, по громкой связи, на личный телефон, по мылу, телеге, видеосвязи... меняют приоритеты и прерывают работу новыми заданиями, на стол кто-то притаскивает болванки, ставит станки, забирает детали...
  • на заводе с менеджментом ПЛИС - рабочий (REG) каждый такт смотрит в отрывной календарь (LUT), выполняет заданное там действие, передаёт результат далее по конвейеру в календари (LUT) других работников и свой на завтра, текущий лист отрывает и выбрасывает.

 

Соответственно архитектурно просится описывать алгоритм как изменение конкретного REG от условий LUT находящегося в неком ограниченном по функционалу модуле (CLB).

 

1 hour ago, Worldmaster said:

И все равно он показывает недобор частоты по CAM1_CLK. С этим то что делать?

Если проект разбит на модули - вы можите посмотреть Fmax на любое кол-во конкретных подмодулей сразу в отчёте, добавив это требование в sdc файл мышкой или редактором.

38 minutes ago, Maverick_ said:

каждый подмодуль проверить на максимальную частоту (отдельный проект) -

необязательно, в GoWin можно посмотреть Fmax любого модуля и его детей и найти паршивую овцу портящую семью.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 01.03.2024 в 10:48, Maverick_ сказал:

что значит "Когда они готовы генерит сигнал Cam1_Mipi_Data_Read_Clk " ?

Gowin MIPI D-PHY RX TX Advance.pdf

Вот документ на корку.

 

В 01.03.2024 в 10:48, Maverick_ сказал:

работают паралельно т.е. одновременно - пишиут и читают из одной ячейки памяти, судя по Вашему процессу

Это плохо?? Выше вроде по советам сделал что используется значение прошлой переменной а потом изменяется на новое.

Так как правильно то?? 

То что вы привели модуль памяти по сути ведь тоже самое. Также использован logic_vector

variable mem : mem_type := (others => (others => '0')); 

Просто дополнительно добавлена надстройка в виде модуля. Какое преимущество в этом? Вместо простого присвоения счетчика вы добавляете еще больше LUT и логики. Разве это должно работать быстрее?

Но я тут проверил и даже если в Cam1_Read_Process будет только мигание светодиодом все равно частота выше 30 не поднимается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

variable mem : mem_type := (others => (others => '0')); 

у меня строка используется для инициализации памяти - после того как плис будет запрограммипрвана, что должно быть в памяти

и все ...

с коркой MIPI я бы работал через двухклоковое фифо 

1 частота работы модуля  чаще она будет высокой

2 частота MIPI

И смотрел (на логике) за сигналами фифо full/empty - для старта можно вывел их на светодиоды/лог анализатор - убедиться что нет потерь данных

возможно лучше сделал бы пакетное фифо - мое на форуме как пример

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...