VHDL TestBench数据产生方式

来源:互联网 发布:大疆无人机 知乎 编辑:程序博客网 时间:2024/04/24 22:16

VHDL TestBench数据产生方式
    TestBench是FPGA代码编写中最重要的一个测试方式,一般情况下,只有在TestBench上测试通过了,我们才会将代码烧写到FPGA中去。TestBench的代码不像需要烧写到FPGA中的代码那么严谨,会使用一些比如wait for之类的语言。这样的代码不合乎时序规范,就会导致仿真的时候也出现一些时序问题,我们就通过一个例子来看一下。
    首先这是我们要进行仿真的代码:

library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity camPix isport(  rst_n    :  IN  std_logic;  clk      :  IN  std_logic;  cam_da_i :  IN  std_logic_vector(7 downto 0);  cam_da_o : OUT  std_logic_vector(3 downto 0)  );end camPix;architecture Behavioral of camPix issignal cam_da_in_dly  : std_logic_vector(7 downto 0);signal cam_da_out_dly : std_logic_vector(3 downto 0);beginprocess(rst_n,clk)begin  if(rst_n = '0') then    cam_da_in_dly <= (others => '0');  elsif(rising_edge(clk)) then    cam_da_in_dly <= cam_da_i;  end if;end process;process(rst_n,clk)begin  if(rst_n = '0') then    cam_da_out_dly <= (others => '0');  elsif(rising_edge(clk)) then    cam_da_out_dly <= cam_da_in_dly(5 downto 2);  end if;end process;process(rst_n,clk)begin  if(rst_n = '0') then    cam_da_o <= (others => '0');  elsif(rising_edge(clk)) then    cam_da_o <= cam_da_out_dly;  end if;end process;end Behavioral;

    接下来是我们的TestBench代码

library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;use STD.TEXTIO.all;use ieee.std_logic_textio.all;entity test_top isend test_top;architecture Behavioral of test_top isCOMPONENT camPix  Port(    rst_n   : in std_logic;    clk     : in std_logic;             cam_da_i    : in std_logic_vector(7 downto 0);    cam_da_o    :out std_logic_vector(3 downto 0)  );END COMPONENT;--------------------------------------------------------------------constant clk_period : time := 2 ns;--Inputssignal rst_n    : std_logic := '0';signal cam_clk  : std_logic := '0';signal cam_da_i : std_logic_vector(7 downto 0);signal cam_da_o : std_logic_vector(3 downto 0);begin-- Clock process definitions  cam_clk_process :process  begin    cam_clk <= not cam_clk;    wait for clk_period/2;  end process;-- Reset process definitions  rst_process :process  begin    rst_n <= '0';    wait for clk_period*5;    rst_n <= '1';    wait;  end process;-- Stimulus process  sti_process : process  begin    cam_da_i <= x"67";    wait for clk_period*5;    cam_da_i <= x"45";    wait for clk_period*3;    cam_da_i <= x"AB";    wait for clk_period*4;  end process;CAMPIXEL : camPixport map(  rst_n    => rst_n,  clk      => cam_clk,  cam_da_i => cam_da_i,  cam_da_o => cam_da_o  );end Behavioral;

    然后我们来看一下仿真的波形图
仿真图
    可以发现这个时序与我们想象中的有点不一样,在代码中,我们的cam_da_in_dly这个信号是比cam_da_i这个信号延时一个clk的,但是在仿真波形图中可以看到cam_da_in_dly和cam_da_i这两个信号同时变化,也就是说和我们代码中描述的不一样。
    究其原因,是因为连接到campixel这个component里的cam_da_i是通过时间延时产生的,即通过wait for这种形式产生的,而并不是在process(clk)中产生的。可以这样理解,如果是在process(clk)里面产生的,那么可以认为信号与clk之间存在着因果关系,而如果是通过wait for这样的形式产生的,虽然看上去信号也像是在某个时钟上升沿产生的,但其实两者之间并不存在任何联系,或者可以理解成,wait for clk_period*5就相同于cam_da_i在(clk_period*5 -Δt)的时候产生的,所以在下一个clk触发的时候,cam_da_i_dly就被赋予了cam_da_i的值了,即在仿真波形图中看到两个信号同时发生变化。
    有时候这样的时序问题不会产生什么影响,但也有不少情况下,这一个时序的错误就会导致仿真与实际情况不同,那如何解决这个问题呢。解决办法很简单,既然是因为testBench中的信号不是通过process(clk)产生而导致的,那我们就在输入到component之前先将信号延时一个clk即可。
    延时一个clk之后的波形仿真图:
仿真图
    可以看到,现在的时序跟我们想象中的一样了。
    文件操作也是TestBench里一个非常重要的部分,很多时候,我们需要通过文件来读取或者记录仿真数据,下一次更新,笔者将简单介绍一下TestBench中的文件读写操作。

0 0