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 is
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 camPix;
 
architecture Behavioral of camPix is
 
signal cam_da_in_dly  : std_logic_vector(7 downto 0);
signal cam_da_out_dly : std_logic_vector(3 downto 0);
 
begin
 
process(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 is
end test_top;
 
architecture Behavioral of test_top is
 
 
COMPONENT 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;
--Inputs
signal 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 : camPix
port 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_period5就相同于cam_da_i在(clk_period5 -Δt)的时候产生的,所以在下一个clk触发的时候,cam_da_i_dly就被赋予了cam_da_i的值了,即在仿真波形图中看到两个信号同时发生变化。

  有时候这样的时序问题不会产生什么影响,但也有不少情况下,这一个时序的错误就会导致仿真与实际情况不同,那如何解决这个问题呢。解决办法很简单,既然是因为testBench中的信号不是通过process(clk)产生而导致的,那我们就在输入到component之前先将信号延时一个clk即可。

    延时一个clk之后的波形仿真图:
仿真图
  可以看到,现在的时序跟我们想象中的一样了。

  文件操作也是TestBench里一个非常重要的部分,很多时候,我们需要通过文件来读取或者记录仿真数据,下一次更新,笔者将简单介绍一下TestBench中的文件读写操作。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于VHDL FIR滤波器的testbench,可以参考以下步骤进行设计和仿真。 首先,根据设计文件中的顶层模块和子模块的连接关系,创建一个顶层实体(entity)。在该实体中,实例化FIR模块和DDS模块,并连接它们的输入和输出信号。 接下来,为FIR模块和DDS模块创建相应的仿真模型。根据引用\[1\]中的描述,FIR模块的系数应该是从coeffs_registers中读取的。因此,在FIR模块的仿真模型中,可以使用一个过程(process)来模拟从coeffs_registers中读取系数的行为。 在DDS模块的仿真模型中,可以生成100KHz和1MHz的正弦波,并将其作为滤波器的输入信号。 在顶层实体的仿真模型中,可以为FIR模块和DDS模块的输入和输出信号创建信号(signal)。然后,根据引用\[2\]中的描述,可以使用一个过程(process)来模拟ast_sink_valid信号的行为,即在脉冲为高时将滤波器的数据取出。 最后,编写一个testbench主体,将顶层实体和仿真模型中的信号连接起来,并在仿真过程中对输入信号进行激励,观察输出信号的变化。 需要注意的是,根据引用\[3\]中的描述,可以使用Quartus II中的MegaWizard Plug-In Manager来生成FIR Compiler II IP核。在设计和仿真过程中,可以使用该IP核的配置参数。 这样,你就可以根据以上步骤设计和仿真VHDL FIR滤波器的testbench了。 #### 引用[.reference_title] - *1* [matlab工具生成可编程FIR滤波器的HDL代码](https://blog.csdn.net/sinat_33705291/article/details/103481689)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [FIR滤波器仿真--基于Quartus II的FIR Compiler II IP核的脚本仿真](https://blog.csdn.net/heshiliqiu/article/details/75816555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值