现在的位置: 首页 > 综合 > 正文

Verilog HDL in one day Part-IV

2013年02月06日 ⁄ 综合 ⁄ 共 4250字 ⁄ 字号 评论关闭
  ../images/main/bullet_green_ball.gif Test Benches //测试基准
   

Ok, we have code written according to the design document, now what?

好吧,我已经按照设计说明文档,编写了代码,现在做点什么呢?

   

space.gif

   

Well we need to test it to see if it works according to specs. Most of the time, it's the same we use to do in digital labs in college days: drive the inputs, match the outputs with expected values. Let's look at the
arbiter testbench.

我们需要测试一下它能否按照说明书的要求正常运行. 绝大部分时间,和我们大学时候过去在数字电路实验室中常做的一样:驱动输入,和预期的值比对输出。

让我们看看这个中仲裁器的测试基准程序。

   

space.gif

   

  1 module arbiter (
  2 clock, 
  3 reset, 
  4 req_0,
  5 req_1, 
  6 gnt_0,
  7 gnt_1
  8 );
  9 
 10 input clock, reset, req_0, req_1;
 11 output gnt_0, gnt_1;
 12 
 13 reg gnt_0, gnt_1;
 14 
 15 always @ (posedge clock or posedge reset)
 16 if (reset) begin
 17  gnt_0 <= 0;
 18  gnt_1 <= 0;
 19 end else if (req_0) begin
 20   gnt_0 <= 1;
 21   gnt_1 <= 0;
 22 end else if (req_1) begin
 23   gnt_0 <= 0;
 24   gnt_1 <= 1;
 25 end
 26 
 27 endmodule
 28 // Testbench Code Goes here
 29 module arbiter_tb;
 30 
 31 reg clock, reset, req0,req1;
 32 wire gnt0,gnt1;
 33 
 34 initial begin
 35   $monitor ("req0=%b,req1=%b,gnt0=%b,gnt1=%b", req0,req1,gnt0,gnt1);
 36   clock = 0;
 37   reset = 0;
 38   req0 = 0;
 39   req1 = 0;
 40    #5  reset = 1;
 41    #15  reset = 0;
 42    #10  req0 = 1;
 43    #10  req0 = 0;
 44    #10  req1 = 1;
 45    #10  req1 = 0;
 46    #10  {req0,req1} = 2'b11;
 47    #10  {req0,req1} = 2'b00;
 48    #10  $finish;
 49 end
 50 
 51 always begin
 52   #5  clock =  ! clock;
 53 end
 54 
 55 arbiter U0 (
 56 .clock (clock),
 57 .reset (reset),
 58 .req_0 (req0),
 59 .req_1 (req1),
 60 .gnt_0 (gnt0),
 61 .gnt_1 (gnt1)
 62 );
 63 
 64 endmodule

You could download file arbiter.v here

   

space.gif

   

It looks like we have declared all the arbiter inputs as reg and outputs as wire; well, that's true. We are doing this as test bench needs to drive inputs and needs to monitor outputs.

它看起来像是我们把所有的仲裁器的输入声明为reg类型,所有的输出声明为wire类型。没错,那是对的。我们这样做是因为测试程序需要驱动的输入和监视输出。

   

space.gif

   

After we have declared all needed variables, we initialize all the inputs to known state: we do that in the initial block. After initialization, we assert/de-assert reset, req0, req1 in the sequence we want to test the
arbiter. Clock is generated with an always block.

在我们声明完所有的变量后,我们初始化所有的输入为已知状态:我在initial-block中初始化输入。在初始输入后,我们一次确保能够测试仲裁器中的reset, req0, req1。时钟是通过always block 产生的。

   

space.gif

   

After we are done with the testing, we need to stop the simulator. Well, we use $finish to terminate simulation. $monitor is used to monitor the changes in the signal list and print them in the format we want.

在完成测试之后,我们需要停止simulator(仿真器)。我能够通过 $finish系统任务来终结simulation(仿真)。

$monitor系统任务用来监控信号列表的变化,并且可以按照我们需要的格式打印它们。

   

space.gif

   
 req0=0,req1=0,gnt0=x,gnt1=x
 req0=0,req1=0,gnt0=0,gnt1=0
 req0=1,req1=0,gnt0=0,gnt1=0
 req0=1,req1=0,gnt0=1,gnt1=0
 req0=0,req1=0,gnt0=1,gnt1=0
 req0=0,req1=1,gnt0=1,gnt1=0
 req0=0,req1=1,gnt0=0,gnt1=1
 req0=0,req1=0,gnt0=0,gnt1=1
 req0=1,req1=1,gnt0=0,gnt1=1
 req0=1,req1=1,gnt0=1,gnt1=0
 req0=0,req1=0,gnt0=1,gnt1=0
   

space.gif

   

I have used Icarus Verilog simulator to generate the above output.

这是我们使用Icarus verilog 仿真器产生的输出。

the original link:http://www.asic-world.com/verilog/verilog_one_day4.html

关于arbiter Verilog HDL code 的测试如下:这里介绍一下Icarus Verilog simulator使用方法, 开源的,很小,而且还能查看波形图。

1. arbiter module的代码如下:

//arbiter模块定义
module arbiter ( //模块的参数列表
    clock, //clock时钟信号
    reset, //reset复位信号
    req_0, //req_0, 请求授权0
    req_1, //req_1, 请求授权1
    gnt_0, //gnt_0, 授权0输出
    gnt_1); //gnt_1, 授权1输出

input clock, reset, req_0, req_1; // 模块输入,指明参数的方向
output gnt_0, gnt_1;              // 模块输出,指明参数的方向

reg gnt_0, gnt_1;                 //声明输出参数的类型,register类型

//使用@()触发表的always block 在 clock或reset的上升沿触发
always @ (posedge clock or posedge reset)
    if (reset) begin // 复位设置
        gnt_0 <= 0;
        gnt_1 <= 0;
    end else if (req_0) begin // 请求授权0
        gnt_0 <= 1;
        gnt_1 <= 0;
    end else if (req_1) begin  //请求授权1
        gnt_0 <= 0;
        gnt_1 <= 1;
    end
// 可见优先级:reset > req_0 > req_1;

endmodule // 模块的结束标志

2.对arbiter.v 测试的代码:

`include "arbiter.v" // 导入 arbiter模块

// Testbench Code Goes here
module arbiter_tb;

reg clock, reset, req0,req1; // the input, register类型, 输入驱动
wire gnt0,gnt1;             // the output, wire类型,连线型,输出

//仲裁器的实例
arbiter U0 (
    .clock (clock), //时钟信号的绑定
    .reset (reset), //复位信号的绑定
    .req_0 (req0),  //req_0 请求绑定
    .req_1 (req1),  //req_1 请求绑定

    .gnt_0 (gnt0), // gnt_0, grant0绑定
    .gnt_1 (gnt1)  // gnt_1 grant1 绑定
);

//初始化模块
initial begin
    //$monitor监视任务
   // $monitor ("req0=%b,req1=%b,gnt0=%b,gnt1=%b", req0,req1,gnt0,gnt1);

    //初始化状态
    // blocking = 
    #0
    clock = 0;
    reset = 0;
    req0 = 0;
    req1 = 0;

    //reset信号测试
    #5 reset = 1;
    #15 reset = 0;

    //req0信号测试
    #10 req0 = 1;
    #10 req0 = 0;

    //req1信号测试
    #10 req1 = 1;
    #10 req1 = 0;

    //优先级置位
    #10 {req0,req1} = 2'b11;

    //保持发呆
    #10 {req0,req1} = 2'b00;
    #10 $finish;
end

initial begin
    $display("time:\tclock\treset\treq0\treq1\tgnt0\tgnt1");
    $monitor("%2d:\t%b\t%b\t%b\t%b\t%b\t%b", $time, clock, reset, req0, req1, gnt0, gnt1);

    $dumpfile("arbiter.vcd");
    $dumpvars;
end



//带时延的always block
always begin
    #5 clock = !clock;   //每个时钟周期是5个单位,输入跳变的时延是时钟周期的整数倍
end

endmodule

3.测试 步骤, Icarus中有三个工具,编译器iverilog, 输出测试结果的vvp,输出波形的图的gtkwave工具。

                 1.编译 : iverilog arbiter_test.v

                 2.输出状态转换:vvp a.out

                3. 输出波形图:gtkwave arbiter.vcd

抱歉!评论已关闭.