lyzifer 0 28 ноября, 2017 Опубликовано 28 ноября, 2017 · Жалоба Есть у меня описание работы синтезатора,состоящего из 3-x модулей. RTL-анализ проходит успешно,а вот тестбенч не выдаёт ничего путного. А я в свою очередь не могу понять,в чём проблема, то ли просто тестбенч косячно написал,то ли в описании устройства ошибся. Вот его описание на VHDL: 1)ОСНОВНОЙ МОДУЛЬ library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity TOP is Port ( clk : in STD_LOGIC; reset: in STD_LOGIC; DATAuWire : out STD_LOGIC; CLKuWire : out STD_LOGIC; LEuWire : out STD_LOGIC ); end TOP; architecture Behavioral of TOP is component spi_interface Generic(CLK_DIV: integer := 2); Port ( clk_20: in STD_LOGIC; -- System clk = 20 MHz reset_n : in STD_LOGIC; -- Reset signal start_interface : in STD_LOGIC; -- Send data via SPI interface data_2write : in STD_LOGIC_VECTOR(31 downto 0); -- CDCE62005 register content get_data : inout STD_LOGIC; -- Transmit complete, get a new data to interface DATAuWire : out STD_LOGIC; -- Serial Clock CLKuWire : out STD_LOGIC; -- SPI master output signal --spi_miso : in STD_LOGIC; -- SPI input signal LEuWire : out STD_LOGIC); -- Latch enable end component; component programming_sequence Port ( clk_20 : in STD_LOGIC; -- System clk = 20 MHz reset_n : in STD_LOGIC; -- Reset signal get_data : in STD_LOGIC; -- Change register content start_interface : out STD_LOGIC; -- Send data via SPI interface data_2write : out STD_LOGIC_VECTOR (31 downto 0); -- CDCE62005 register content sync : out STD_LOGIC; -- CDCE62005 SYNC# power_down : out STD_LOGIC); -- CDCE62005 Power Down# end component; signal si : std_logic; signal dw : STD_LOGIC_VECTOR(31 downto 0); signal gd : std_logic; begin dd1:component programming_sequence port map (clk_20=>clk,reset_n=>reset,get_data=>gd,start_interface=>si,data_2write=>dw); dd2:component spi_interface port map (clk_20=>clk,reset_n=>reset,start_interface=>si,data_2write=>dw,get_data=>gd,CLKuWire=>CLKuWire,LEuWire=>LEuWire,DATAuWire=>DATAuWire); end Behavioral; 2)programming_sequence (МОДУЛЬ УПРАВЛЕНИЯ И ПАМЯТИ) library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity programming_sequence is Port ( clk_20 : in STD_LOGIC; -- System clk = 20 MHz reset_n : in STD_LOGIC; -- Reset signal get_data : in STD_LOGIC; -- Change register content start_interface : out STD_LOGIC; -- Send data via SPI interface data_2write : out STD_LOGIC_VECTOR (31 downto 0); -- CDCE62005 register content sync : out STD_LOGIC; -- CDCE62005 SYNC# power_down : out STD_LOGIC); -- CDCE62005 Power Down# end programming_sequence; architecture Behavioral of programming_sequence is type statetype is (START, R0, R1, R2, R3, R4, R5, R6, R7, R8, FINISH); signal state, nextstate: statetype; signal change_state_d, change_state_q: std_logic; -- Change state trigger begin power_down <= '1'; --State register process (clk_20, reset_n) begin if reset_n = '1' then state <= START; change_state_q <= '0'; elsif rising_edge(clk_20) then state <= nextstate; change_state_q <= change_state_d; end if; end process; start_interface <= '0' when state = START else ((change_state_d xor change_state_q) and '1'); -- Next state logic process (state, get_data) begin case state is when START => -- Idle state nextstate <= R0; when R0 => -- Write Register 0 if get_data = '1' then nextstate <= R1; else nextstate <= R0; end if; when R1 => -- Write Register 1 if get_data = '1' then nextstate <= R2; else nextstate <= R1; end if; when R2 => -- Write Register 2 if get_data = '1' then nextstate <= R3; else nextstate <= R2; end if; when R3 => -- Write Register 3 if get_data = '1' then nextstate <= R4; else nextstate <= R3; end if; when R4 => -- Write Register 4 if get_data = '1' then nextstate <= R5; else nextstate <= R4; end if; when R5 => -- Write Register 5 if get_data = '1' then nextstate <= R6; else nextstate <= R5; end if; when R6 => -- Write Register 6 if get_data = '1' then nextstate <= R7; else nextstate <= R6; end if; when R7 => -- Write Register 7 if get_data = '1' then nextstate <= R8; else nextstate <= R7; end if; when R8 => -- Write Register 8 if get_data = '1' then nextstate <= FINISH; else nextstate <= R8; end if; when FINISH => -- End config nextstate <= FINISH; when others => nextstate <= START; end case; end process; -- Registered output logic process (clk_20, state) begin sync <= '0'; change_state_d <= '0'; case state is when START => data_2write <= "11111100000000000000000000000010"; change_state_d <= '0'; when R0 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '1'; when R1 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '0'; when R2 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '1'; when R3 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '0'; when R4 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '1'; when R5 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '0'; when R6 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '1'; when R7 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '0'; when R8 => data_2write <= "00000000000000000000000000000000"; change_state_d <= '1'; when FINISH => data_2write <= "00000000000000000000000000000000"; --change_state_d <= '1'; sync <= '1'; when others => data_2write <= "00000000000000000000000000000000"; change_state_d <= '0'; end case; end process; end Behavioral; 3)spi_interface (ПЕРЕДАЮЩИЙ МОДУЛЬ) library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity spi_interface is Generic(CLK_DIV: integer := 2); Port ( clk_20: in STD_LOGIC; -- System clk = 20 MHz reset_n : in STD_LOGIC; -- Reset signal start_interface : in STD_LOGIC; -- Send data via SPI interface data_2write : in STD_LOGIC_VECTOR(31 downto 0); -- CDCE62005 register content get_data : out STD_LOGIC; -- Transmit complete, get a new data to interface DATAuWire : out STD_LOGIC; -- Serial Clock CLKuWire : out STD_LOGIC; -- SPI master output signal --spi_miso : in STD_LOGIC; -- SPI input signal LEuWire : out STD_LOGIC); -- Latch enable end spi_interface; architecture Behavioral of spi_interface is type statetype is (IDLE, WAIT_HALF, TRANSFER); signal state_d, state_q: statetype; signal data_d, data_q: STD_LOGIC_VECTOR(31 downto 0); -- Input data register signal CLKuWire_d, CLKuWire_q: STD_LOGIC_VECTOR(CLK_DIV - 1 downto 0); signal DATAuWire_d, DATAuWire_q: STD_LOGIC; -- Shift Out SPI data signal ctr_d, ctr_q: STD_LOGIC_VECTOR(4 downto 0); -- Bit Counter signal get_data_d, get_data_q: STD_LOGIC; -- Transmit complete begin -- Output signal assigment DATAuWire <= DATAuWire_q; LEuWire <= '1' when state_q = IDLE else '0'; get_data <= get_data_q; -- State register, and memory system process(clk_20, reset_n) begin if reset_n = '1' then state_q <= IDLE; data_q <= "11111100000000000000000000000010"; CLKuWire_q <= "00"; DATAuWire_q <= '0'; ctr_q <= "00000"; get_data_q <= '0'; elsif rising_edge(clk_20) then state_q <= state_d; data_q <= data_d; CLKuWire_q <= CLKuWire_d; DATAuWire_q <= DATAuWire_d; ctr_q <= ctr_d; get_data_q <= get_data_d; end if; end process; --Next state logic process(state_q, start_interface, CLKuWire_q, ctr_q) begin state_d <= state_q; data_d <= data_q; CLKuWire_d <= CLKuWire_q; DATAuWire_d <= DATAuWire_q; ctr_d <= ctr_q; get_data_d <= get_data_q; case state_q is when IDLE => CLKuWire_d <= "00"; -- Reset Clock counter ctr_d <= "00000"; -- Reset Bit counter if start_interface = '1' then -- If Start signal is active data_d <= data_2write; -- Load data to register state_d <= WAIT_HALF; -- Change state on next else state_d <= IDLE; -- Else stay in current state end if; when WAIT_HALF => CLKuWire_d <= CLKuWire_q + 1; -- Increment clock counter if (CLKuWire_q = "01") then -- If clock counter if half_full (about to fall) CLKuWire_d <= "00"; -- Reset to 0 state_d <= TRANSFER; -- Change state else state_d <= WAIT_HALF; -- Else stay in current state end if; when TRANSFER => CLKuWire_d <= CLKuWire_q + 1; -- Increment clock counter if (CLKuWire_q = "00") then -- If Clock counter is o DATAuWire_d <= data_q(31); -- Shift out MSB data elsif (CLKuWire_q = "01") then -- Else if it's half full(about to fall) data_d <= (data_q(30 downto 0) & '0'); -- Shift in zero elsif (CLKuWire_q = "11") then -- Else if it's full(about to rise) ctr_d <= ctr_q + 1; -- Increment bit counter if (ctr_q = "11111") then -- If we are on the last bit state_d <= IDLE; get_data_d <= '1'; else state_d <= TRANSFER; -- Else stay in current state end if; end if; when others => state_d <= IDLE; end case; end process; process (clk_20) begin if rising_edge(clk_20) then case state_q is when others => CLKuWire <= '0'; end case; end if; end process; end Behavioral; RTL ВОТ ТАКИЕ СИГНАЛЫ Я ДОЛЖЕН ПОЛУЧИТЬ А ВОТ И МОЙ ТЕСТБЕНЧ library IEEE; use IEEE.Std_logic_1164.all; use IEEE.Numeric_Std.all; entity TOP_tb is end; architecture bench of TOP_tb is component TOP Port ( clk : in STD_LOGIC; reset: in STD_LOGIC; DATAuWire : out STD_LOGIC; CLKuWire : out STD_LOGIC; LEuWire : out STD_LOGIC ); end component; signal clk: STD_LOGIC; signal reset: STD_LOGIC; signal DATAuWire: STD_LOGIC; signal CLKuWire: STD_LOGIC; signal LEuWire: STD_LOGIC; constant PERIOD : TIME := 100 ns; constant DUTY_CYCLE : real := 0.5; constant OFFSET : time := 1 ns; begin uut: TOP port map ( clk => clk, reset => reset, DATAuWire => DATAuWire, CLKuWire => CLKuWire, LEuWire => LEuWire ); clk_gen: PROCESS BEGIN WAIT for OFFSET; CLOCK_LOOP : LOOP CLK <= '0'; WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE)); CLK <= '1'; WAIT FOR (PERIOD * DUTY_CYCLE); END LOOP CLOCK_LOOP; END PROCESS; reset<='0'; -- rst_gen: PROCESS -- BEGIN -- WAIT for OFFSET; -- reset <='1'; -- wait for period * DUTY_CYCLE *2; -- reset <='0'; -- wait; -- END PROCESS; end; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 28 ноября, 2017 Опубликовано 28 ноября, 2017 (изменено) · Жалоба В Entitiy spi_interface так и должно быть ? CLKuWire : out STD_LOGIC; -- SPI master output signal process (clk_20) begin if rising_edge(clk_20) then case state_q is when others => CLKuWire <= '0'; end case; end if; end process; Так-же в VHDL совсем не обязательно описывать компонент в области декларации архитектуры. Можно писать вот так: dd1: entity work.programming_sequence port map ( clk_20 => clk, reset_n => reset, get_data => gd, start_interface => si, data_2write => dw ); Ну и старайтесь избегать записи в port map в одну строчку. Это делает проект абсолютно не читаемым. Изменено 28 ноября, 2017 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lyzifer 0 28 ноября, 2017 Опубликовано 28 ноября, 2017 · Жалоба ну по началу было так: process (clk_20) begin if rising_edge(clk_20) then case state_q is when TRANSFER => spi_clk <= (spi_clk_q(CLK_DIV - 1)); end case; end if; end process; но Вивада ругается на такое представление... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 28 ноября, 2017 Опубликовано 28 ноября, 2017 (изменено) · Жалоба ну по началу было так: process (clk_20) begin if rising_edge(clk_20) then case state_q is when TRANSFER => spi_clk <= (spi_clk_q(CLK_DIV - 1)); end case; end if; end process; но Вивада ругается на такое представление... Добавили бы тогда строчку: when others => null; Так-же присутствуют ошибки неполного списка чувствительности: Warning (10492): VHDL Process Statement warning at spi_interface.vhd(67): signal "data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list Warning (10492): VHDL Process Statement warning at spi_interface.vhd(69): signal "DATAuWire_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list Warning (10492): VHDL Process Statement warning at spi_interface.vhd(71): signal "get_data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list Warning (10492): VHDL Process Statement warning at spi_interface.vhd(77): signal "data_2write" is read inside the Process Statement but isn't in the Process Statement's sensitivity list Warning (10492): VHDL Process Statement warning at spi_interface.vhd(93): signal "data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list Warning (10492): VHDL Process Statement warning at spi_interface.vhd(95): signal "data_q" is read inside the Process Statement but isn't in the Process Statement's sensitivity list Изменено 28 ноября, 2017 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lyzifer 0 29 ноября, 2017 Опубликовано 29 ноября, 2017 (изменено) · Жалоба ооо,вот тут помогло: process (clk_20) begin if rising_edge(clk_20) then case state_q is when TRANSFER => CLKuWire <= (CLKuWire_q(CLK_DIV - 1)); when others => null; end case; end if; end process; в тестбенче CLKuWire теперь выдаёт результаты. а вот список чувствительности в принципе ничего не дал process(state_q, start_interface, CLKuWire_q, ctr_q, data_q, DATAuWire_q, get_data_q, data_2write) begin только как мне теперь добиться,чтобы на DATAuWire выдавались данные со всех регистров, а не только с 2х ? Изменено 29 ноября, 2017 пользователем lyzifer Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 30 ноября, 2017 Опубликовано 30 ноября, 2017 · Жалоба только как мне теперь добиться,чтобы на DATAuWire выдавались данные со всех регистров, а не только с 2х ? Со всех это с каких ? Вообще данные выдаются только с одного регистра: DATAuWire <= DATAuWire_q; Я бы посоветовал сначала: 1. Разобраться с сигналом reset_n. Назван он будто имеет логический уровень "0", о чем говорит общепринятый постфикс _n, а работает по лог. "1". Запутаете себя таким образом. 2. Нужен ли асинхронный reset вообще ? 3. Чем обусловлено применение библиотек: IEEE.STD_LOGIC_ARITH.ALL; IEEE.STD_LOGIC_UNSIGNED.ALL; 4. Если у Вас достаточно мощная система для моделирования, можно смело писать список чувствительности вот так: process(all), тогда будет с ним меньше мороки. Но в любом варианте надо разобраться с ним. 5. Переписать автомат на что-то более понятное. Я так и не понял, как он должен работать. 6. Применять понятные обозначения регистров. Ибо среди объявленных сигналов регистр только один: signal get_data_d : STD_LOGIC := '0'; -- Transmit complete signal get_data_q : STD_LOGIC := '0'; -- Transmit complete А именно: signal get_data_q : STD_LOGIC := '0'; -- Transmit complete Так и объявляли бы его как : signal get_data_reg : STD_LOGIC := '0'; -- Transmit complete Тогда, читающим Ваш код было бы существенно проще разобраться с ним. Либо где-то пишите соглашение об именах, чтобы было понятно что сигналы с постфиксом _q - это регистры. Хотя я считаю, что лучше давать "говорящие" имена, где само название переменной говорит за себя и практически не нуждается в пояснении. Так-же и сигналы автомата. Не проще их назвать как-нибудь типа press_state и next_state. Уж очень тяжко понимать такие вот названия state_d, state_q: statetype; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться