VHDL testbench для устройства, которое использует два ранее определенных и проверенных объекта

Предупреждение: это будет долго. Извините, если это слишком многословно.

Я только начинаю изучать FPGA и VHDL, используя Quartus Prime. За последние несколько дней я научил себя:

  • Как написать VHDL
  • Как сделать компонент
  • Как написать тестовый стенд
  • Как использовать ранее созданные и протестированные компоненты - связанные вместе - для создания нового компонента

Однако я не могу понять, как создать тестовый стенд, который тестирует новый компонент, использующий два существующих компонента, когда некоторые сигналы, содержащиеся в этом новом компоненте, являются только внутренними сигналами.

Итак, вот два сверхпростых компонента, которые я успешно написал и протестировал на испытательных стендах. Между прочим, я понимаю, что это не настоящий мир, я просто пытаюсь сделать маленькие шаги.

1. Четырехбитный регистр

library ieee;
use ieee.std_logic_1164.all;

entity four_bit_reg is
port
    (
    bcd_in: in std_logic_vector(3 downto 0);
    clk: in std_logic;
    clr: in std_logic;
    bcd_out: out std_logic_vector(3 downto 0)
    );

end four_bit_reg;

architecture behaviour of four_bit_reg is
begin
    process (clk,clr)
        begin
        if (clr = '1') then
            bcd_out <= "0000";
        elsif rising_edge(clk) then
            bcd_out <= bcd_in;
        end if;
    end process;

end behaviour;

2. Преобразователь BCD в семь сегментов

library ieee;
use ieee.std_logic_1164.all;

entity sev_seg is
    port
        (
        bcd_value : in std_logic_vector(3 downto 0);
        sev_seg_value : out std_logic_vector(6 downto 0)                                        
        );

end sev_seg;

architecture behaviour of sev_seg is
begin   
    sev_seg_process : process (bcd_value)
        begin
        case bcd_value is
            when "0000" => sev_seg_value <="0111111"; -- 0
            when "0001" => sev_seg_value <="0000110"; -- 1
            when "0010" => sev_seg_value <="0111011"; -- 2
            when "0011" => sev_seg_value <="1001111"; -- 3
            when "0100" => sev_seg_value <="1100110"; -- 4
            when "0101" => sev_seg_value <="1101101"; -- 5
            when "0110" => sev_seg_value <="1111101"; -- 6
            when "0111" => sev_seg_value <="0000111"; -- 7
            when "1000" => sev_seg_value <="1111111"; -- 8
            when "1001" => sev_seg_value <="1101111"; -- 9
            when others => sev_seg_value <= "0000000"; -- A to F should show blank      
        end case;
    end process sev_seg_process;
end behaviour;

Первый вопрос: что вы называете двумя вещами выше? Компоненты? Модули? Сущности? Что-то другое?

Затем я использую эти два в другом новом компоненте / объекте / модуле (в зависимости от обстоятельств), как показано ниже:

library ieee;
use ieee.std_logic_1164.all;

entity two_modules is
    port
        (
        bcd_pins : in std_logic_vector(3 downto 0);
        sev_seg_pins : out std_logic_vector(6 downto 0)                     
        );

end two_modules;


architecture behaviour of two_modules is
-- Internal signals
signal int_clk: std_logic;
signal int_bus: std_logic_vector(3 downto 0); 

-- List any components used in the design
    component four_bit_reg is
        port
            (
            bcd_in: in std_logic_vector(3 downto 0);
            clk: in std_logic;
            clr: in std_logic;
            bcd_out: out std_logic_vector(3 downto 0)
            );
    end component;

    component sev_seg is
        port
            (
            bcd_value : in std_logic_vector(3 downto 0);
            sev_seg_value : out std_logic_vector(6 downto 0)                                        
            );

    end component;

begin -- start the instances
    fbr: four_bit_reg port map
        (
        clk => int_clk,
        bcd_in => bcd_pins,
        clr => '0',
        bcd_out => int_bus
        );
    sseg: sev_seg port map
        (
        bcd_value => int_bus,
        sev_seg_value => sev_seg_pins

        );

end behaviour;      

Итак, для этой вещи, которую я назвал two_modules, структура для тестового стенда, созданная Quartus, выглядит следующим образом:

LIBRARY ieee;                                               
USE ieee.std_logic_1164.all;                                

ENTITY two_modules_vhd_tst IS
END two_modules_vhd_tst;
ARCHITECTURE two_modules_arch OF two_modules_vhd_tst IS
-- constants       

-- signals                                                   
SIGNAL bcd_pins : STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL sev_seg_pins : STD_LOGIC_VECTOR(6 DOWNTO 0);
signal internal_clock : std_logic := '0';
COMPONENT two_modules
    PORT (
    bcd_pins : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
    sev_seg_pins : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
    );
END COMPONENT;
BEGIN
    i1 : two_modules
    PORT MAP (
-- list connections between master ports and signals
    bcd_pins => bcd_pins,
    sev_seg_pins => sev_seg_pins
    );

internal_clock <= not internal_clock after 500 us;

init : PROCESS                                               
-- variable declarations                                     
BEGIN                                                        
        -- code that executes only once                      
WAIT;                                                       
END PROCESS init;                                           
always : PROCESS                                              
-- optional sensitivity list                                  
-- (        )                                                 
-- variable declarations                                      
BEGIN                                                         
        -- code executes for every event on sensitivity list  
WAIT;                                                        
END PROCESS always;                                          
END two_modules_arch;

Как вы можете видеть, я создал внутренние часы, и я хотел бы, просто для того, чтобы научиться делать подобные вещи, подчеркиваю, я понимаю, что это не полный дизайн, присоединяйтесь к internal_clock (который я вижу, работает и представляет собой сигнал в редакторе сигналов модели Sim), чтобы кликнуть в four_bit_reg.

Я думаю и надеюсь, что когда я знаю, как это сделать, я смогу вспахать и получить настоящий сложный испытательный стенд. Однако после долгих поисков я не могу найти ссылки на то, как связать воедино сигналы от подкомпонентов. Это может быть потому, что я использую совершенно неправильную терминологию и где-то там может быть идеальное руководство.

Так:

  1. Как я могу просто для начала подключить мой internal_clock к подкомпоненту, входу clk four_bit_reg?
  2. Какова правильная терминология, когда вы используете и соединяете такие вещи, как four_bit_reg и sev_seg? Подкомпоненты? Что-то другое?

Большое спасибо, если вы получили это далеко!

3 ответа

С комментариями я понимаю, что вы используете внутренний генератор от Altera в вашем CPLD.

Я предлагаю добавить третий модуль с именем "internal_oscillator", который можно описать следующим образом:

library ieee;
  use ieee.std_logic_1164.all;

entity internal_oscillator is
port (
  CLK  : out std_logic
);
end entity;

architecture for_simulation_only of internal_oscillator is
  constant C_HALF_PERIOD : time      := 5 ns; -- 100MHz
  signal   clk_internal  : std_logic := '0';
begin

  clk_internal <= not clk_internal after C_HALF_PERIOD;
  CLK <= clk_internal;

end architecture;

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

osc_inst : entity work.internal_oscillator 
port map (CLK => int_clk);

В большинстве случаев часы являются входом для модуля. Часто сопровождается сбросом.

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

Есть два основных исключения:

  1. Испытательные стенды генерируют искусственные часы внутри, чтобы управлять проверяемым устройством.
  2. Модули, которые имитируют реальную тактовую генерацию, например, кварцевый генератор.

В вашем two_models объект, добавьте новый порт для тактового сигнала:

entity two_modules is
    port
        (
        clk : in std_logic;
        bcd_pins : in std_logic_vector(3 downto 0);
        sev_seg_pins : out std_logic_vector(6 downto 0)                     
        );

end two_modules;

Удалить int_clk сигнал в two_models архитектура. Замените его ранее определенным входным сигналом, когда вы подключаете подмодули:

fbr: four_bit_reg port map
    (
    clk => clk_in,
    bcd_in => bcd_pins,
    clr => '0',
    bcd_out => int_bus
    );

В вашем тестовом стенде подключите внутренний тактовый сигнал internal_clock в этот порт two_modules:

    PORT MAP (
-- list connections between master ports and signals
    clk_in => internal_clock,
    bcd_pins => bcd_pins,
    sev_seg_pins => sev_seg_pins
    );
Другие вопросы по тегам