FPGA学习笔记:面向验证和仿真的行为描述语句(3)

仿真激励的产生
1、变量初始化
基本原则:可综合代码中完成内部变量的初始化,Testbench中完成可综合代码所需要的各类接口信号的初始化。初始化的方法有两种:
(1)initial初始化:
initial语句只执行一次,即在设计被开始模拟执行时开始,专门用于对输入信号进行初始化和产生特定的信号波形。一个Testbench可以包含多个initial语块,且同时执行,initial语块中的所有变量必须是reg型。
(2)定义变量时初始化:
直接用“=”在变量右端赋初值。例如:

 reg [7:0] cnt=8'00000000;//将8比特的寄存器变量cnt初始化为全0比特   

或者:

reg [3:0] temp=0;

2、时钟信号的产生
(1)普通时钟信号
指的是占空比为50%的时钟信号,可通过initial或者always语句产生,其方法如下:
基于initial语句:

parameter clk_period=10;
reg clk;
initial
   begin
      clk=0;
      forever #(clk_preiod/2) clk=~clk;
   end

基于always语句:

parameter clk_period=10;
reg clk;
initial
   clk=0;
   always #(clk_period/2) clk=~clk;

注:initial语句用于带clk初始化。
(2)自定义占空比的时钟信号
可通过Always模块快速实现,例如:

parameter High_time=5,Low_time=20;
reg clk;
always
   begin
      clk=1;
      #High_time;
      clk=0;
      #Low_time;
   end

由于对clk直接赋值,所以不需要用initial语句初始化clk信号。
(3)相位偏移的时钟信号
相位偏移是两个时钟信号之间的相对概念。其代码为:

parameter High_time=5,Low_time=5,pshift_time=2;
reg clk_a;
wire clk_b;
always
   begin
      clk_a=1;
      #High_time;
      clk_b=0;
      #Low_time;
   end
assign #pshife_time clk_b=clk_a;

(4)固定数目的时钟信号
repeat语句来产生固定数目的时钟脉冲,其代码如下:

parameter clk_cnt=5,clk_period=2;
reg clk;
initial
   begin
      clk=1;
      repeat (clk_cnt) #clk_period/2 clk=~clk;
   end

3、复位信号的产生
复位信号不是周期信号,通常通过initial语句产生的值序列来描述。
(1)异步复位信号

paramter rst_repiod=100;
reg rst_n;
initial
   begin
      rst_n=0;
      #rst_period;
      rst_n=1;
   end

上述代码将产生低有效的复位信号rst_n,其复位时间为100个仿真代码。
(2)同步复位信号

parameter rst_repiod=100;
reg rst_n;
initial
   begin
      rst_n=1;
      @(posedge clk);
      rst_n=0;
      #rst_repiod;
      @(posedge clk)
      rst_n=1;
   end

上述代码首先将复位信号rst_n初始化为1,然后等待时钟信号clk的上升沿,将复位信号拉低,进入有效复位状态,然后进过100个仿真周期,等待下一个时钟信号上升沿的到来,将复位信号置1。
当需要复位时间为时钟周期的整数倍时,可以将rst_repiod修改为时钟周期的整数倍俩实现,也可以通过下面代码:

parameter rst_num=100;
initial
   begin
      rst_n;
      @(posedge clk);
      rst_n=0;
      repeat(rst_num) @(posedge clk);
      rst_n=1;
   end

上述代码在clk的第一个上升沿开始复位,然后经过5个时钟上升沿后,在第五个时钟上升沿撤销复位信号,进入有效工作状态。
4、数据信号的产生
数据信号的产生主要有两种形式:一种是初始化和产生都在单个initial中完成;另一种是初始化在initial中完成,而产生却在always语句块中完成。前者适合不规则数据数列,并且长度较短;后者适合具有一定规律的数据数列,长度不限。
例一:产生位宽为4的质数序列{1,2,3,5,7,11,13},并且重复两次,其中样值采样间隔为4个仿真时间单位:

'timescale 1ns/ 1ps
module tb_shuju1;
reg [3:0] q_out;
parameter sample_period=4;
parameter queue_num=2;
initial
   begin
      q_out=0;
      repeat(queue_num)
         begin
            # sample_period q_out=1;
            # sample_period q_out=2;
            # sample_period q_out=3;
            # sample_period q_out=5;
            # sample_period q_out=7;
            # sample_period q_out=11;
            # sample_period q_out=13;
         end
   end
endmodule

例二:产生位宽为4的偶数序列,并重复多次。由于该序列规律明显,利用always语句最为方便:

module tb_shuju2;
reg [3:0] q_out;
parameter sample_period=4;
initial
   q_out=0;
   always #sample_period q_out=q_out+2;
endmodule

6、测试向量的产生
如果有方法产生期望的结果,可以用Verilog或其他工具自动地比较期望值和实际值。如果没有简易的方法产生期望的结果,那么测试向量时可以简化仿真结果的。例如16位复数乘法器的代码仿真验证。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值