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

Maverick_

Модераторы
  • Постов

    3 841
  • Зарегистрирован

Репутация

15 Хороший

Информация о Maverick_

  • Звание
    я только учусь...
    Гуру
  • День рождения 12.01.1979

Контакты

  • Сайт
    Array
  • ICQ
    Array

Посетители профиля

26 891 просмотр профиля
  1. тогда работа с описаниями по ссилкам https://github.com/tirfil/VhdI2CSlave https://github.com/murattcan/FPGA-I2C-Slave можно поискать еще и включить в поиск модули на verilog кроме vhdl - уверен их много, просто я потратил на поиск 2 мин PS возможна дополнительная работа напильником
  2. Возьмите плату на stm32 и организуйте обмен для отладки
  3. https://ru.scribd.com/document/78090253/Carrier-Recovery-and-Automatic-Gain-Control-on-FPGA-s-based-platform-IEEE-802-15-3c-mm-Wave-PHY-Application
  4. можете просто скомпилировать и посмотреть тактовую частоту для конвеерного счетчика - просто любопытство в описании модуля для создания паузы - проблема ж частоты именно в "большой" разрядности счетчика например 64 бита и/или 32 бита и/или 24 бита менять разрядность в строке width_g: natural := 64; -- Must be divisible by parts_g. в некоторых памятях например в DDR есть так называемый burst режим -когда данные пишутся в память непрерывно по 16/32/64 слова/байта вот можно использовать например если тактовая отличается в разы - в DDR3/4 используется также при работе с трансиверами например 10G - 64 bit данные
  5. в IP core есть модуль DMA или VDMA (для видео) если есть может стоит попробовать его? пакетная передача в видео - ставиться фифо на размер строки видео и таким образом формируется так называемый пакет как avalon или axi stream интерфейсе таким образом можно считать пакеты - формировать кадры использование стандарных интерфейсов увеличивает читабельность описания - avalon или axi stream
  6. не пробовали pipelineCounter для повышения частоты для задания паузы?
  7. variable mem : mem_type := (others => (others => '0')); у меня строка используется для инициализации памяти - после того как плис будет запрограммипрвана, что должно быть в памяти и все ... с коркой MIPI я бы работал через двухклоковое фифо 1 частота работы модуля чаще она будет высокой 2 частота MIPI И смотрел (на логике) за сигналами фифо full/empty - для старта можно вывел их на светодиоды/лог анализатор - убедиться что нет потерь данных возможно лучше сделал бы пакетное фифо - мое на форуме как пример
  8. что значит "Когда они готовы генерит сигнал 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 - т.е. дает разрешения работы или запрещает модуля или процесса
  9. 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
  10. если хотите увеличить частоту можно применить конвеерний счетчик - вместо встроенного в модуль 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 бита
  11. например 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;
  12. https://nandland.com/variables-vs-signals/ variable не будут видны в другом процессе если нужен фифо опишите его отдельно - разбейте Вашу логику на более простые и понятные модули Двухклоковый фифо я выкладывал... Посмотрите как переходите через клоковые домены - правильно? sdc or xdc для логики написаны которая отвечает за коректный переход между клоковыми доменами
×
×
  • Создать...