VHDL testbench для устройства, которое использует два ранее определенных и протестированных объекта - PullRequest
0 голосов
/ 04 июля 2018

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

Я только начинаю изучать 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 ]

0 голосов
/ 04 июля 2018

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

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

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

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

С комментариями я понимаю, что вы используете внутренний генератор от 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);
0 голосов
/ 04 июля 2018

В вашей сущности 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
    );
...