Verilator简易使用教程——一个简单的测试案例

目标

  • 完成一个verilog文件的仿真。
  • 书写一个sim_main.cpp文件,能够对该verilog文件进行测试。

目标Verilog文件

  • 我们首先拿到一个目标verilog文件。
  • 这个verilog文件的test bench已经写好了,命名为tb。
  • 这个tb有两个input,这两个input由verilator的test bench控制,它们分别是clockreset
  • 因为有clock pulse才能进行仿真,所以我们需要书写一个sim_main.cpp(可以换名字)来对clock进行控制。
// Following code segment is generated from /home/ziyue/researchlib/Micro_Eletronic/STSearch/tests/b11/src/b11.v:1
module b11(x_in, stbi, clock, reset, x_out);
input [5:0] x_in;
input stbi;
input clock;
input reset;
output [5:0] x_out;

reg [5:0] cont = 6'b0;
reg signed [8:0] cont1 = 9'b0;
reg signed [8:0] cont1_inv = 9'b0;
reg [5:0] r_in = 6'b0;
reg [3:0] stato = 4'b0;
reg [5:0] x_out = 6'b0;

always @(*) begin
    cont1_inv = (9'sb000000000 - cont1); $display(";A 0");		//(= cont1_inv    (bv-sub 0b000000000 cont1 ))) ;0
end

// Following code segment is generated from /home/ziyue/researchlib/Micro_Eletronic/STSearch/tests/b11/src/b11.v:28
always @(posedge clock) begin
    if ((reset == 1'b1)) begin
        $display("target");
        stato = 4'b0000; $display(";A 3");		//(= stato    0b0000)) ;3
        r_in = 6'b000000; $display(";A 4");		//(= r_in    0b000000)) ;4
        cont = 6'b000000; $display(";A 5");		//(= cont    0b000000)) ;5
        cont1 = 9'b000000000; $display(";A 6");		//(= cont1    0b000000000)) ;6
        x_out <= 6'b000000; $display(";A 7");		//(= x_out    0b000000)) ;7
    end
    else begin
        case (stato)
            4'b0000 :
                begin
                    $display(";A 8");		//(= stato    0b0000)) ;8
                    cont = 6'b000000; $display(";A 9");		//(= cont    0b000000)) ;9
                    r_in = x_in; $display(";A 10");		//(= r_in    x_in )) ;10
                    x_out <= #1 6'b000000; $display(";A 11");		//(= x_out    0b000000)) ;11
                    stato = 4'b0001; $display(";A 12");		//(= stato    0b0001)) ;12
                end
            4'b0001 :
                begin
                    $display(";A 13");		//(= stato    0b0001)) ;13
                    r_in = x_in; $display(";A 14");		//(= r_in    x_in )) ;14
                    if ((stbi == 1'b1)) begin
                        $display(";A 15");		//(= (bv-comp stbi  0b1)   0b1)) ;15
                        stato = 4'b0001; $display(";A 17");		//(= stato    0b0001)) ;17
                    end
                    else begin
                        $display(";A 16");		//(= (bv-comp stbi  0b1)   0b0)) ;16
                        stato = 4'b0010; $display(";A 18");		//(= stato    0b0010)) ;18
                    end
                end
            4'b0010 :
                begin
                    $display(";A 19");		//(= stato    0b0010)) ;19
                    if (((r_in == 6'b000000) || (r_in == 6'b111111))) begin
                        $display(";A 20");		//(= (bv-or (bv-comp r_in  0b000000) (bv-comp r_in  0b111111))   0b1)) ;20
                        if ((cont < 6'b011001)) begin
                            $display(";A 22");		//(= (bool-to-bv (bv-lt cont  0b011001))   0b1)) ;22
                            cont = (cont + 6'b000001); $display(";A 24");		//(= cont    (bv-add cont  0b000001))) ;24
                        end
                        else begin
                            $display(";A 23");		//(= (bool-to-bv (bv-lt cont  0b011001))   0b0)) ;23
                            cont = 6'b000000; $display(";A 25");		//(= cont    0b000000)) ;25
                        end
                        cont1 = {3'b000, r_in}; $display(";A 26");		//(= cont1    (bv-concat 0b000 r_in ))) ;26
                        stato = 4'b1000; $display(";A 27");		//(= stato    0b1000)) ;27
                    end
                    else begin
                        $display(";A 21");		//(= (bv-or (bv-comp r_in  0b000000) (bv-comp r_in  0b111111))   0b0)) ;21
                        if ((r_in <= 6'b011010)) begin
                            $display(";A 28");		//(= (bool-to-bv (bv-le r_in  0b011010))   0b1)) ;28
                            stato = 4'b0011; $display(";A 30");		//(= stato    0b0011)) ;30
                        end
                        else begin
                            $display(";A 29");		//(= (bool-to-bv (bv-le r_in  0b011010))   0b0)) ;29
                            stato = 4'b0001; $display(";A 31");		//(= stato    0b0001)) ;31
                        end
                    end
                end
            4'b0011 :
                begin
                    $display(";A 32");		//(= stato    0b0011)) ;32
                    if ((r_in[0] == 1'b1)) begin
                        $display(";A 33");		//(= (bv-comp (bv-extract 0 0 r_in ) 0b1)   0b1)) ;33
                        cont1 = {2'b00, cont, 1'b0}; $display(";A 35");		//(= cont1    (bv-concat 0b00 cont  0b0))) ;35
                    end
                    else begin
                        $display(";A 34");		//(= (bv-comp (bv-extract 0 0 r_in ) 0b1)   0b0)) ;34
                        cont1 = {3'b000, cont}; $display(";A 36");		//(= cont1    (bv-concat 0b000 cont ))) ;36
                    end
                    stato = 4'b0100; $display(";A 37");		//(= stato    0b0100)) ;37
                end
            4'b0100 :
                begin
                    $display(";A 38");		//(= stato    0b0100)) ;38
                    if ((r_in[1] == 1'b1)) begin
                        $display(";A 39");		//(= (bv-comp (bv-extract 1 1 r_in ) 0b1)   0b1)) ;39
                        cont1 = ({3'b000, r_in} + cont1); $display(";A 41");		//(= cont1    (bv-add (bv-concat 0b000 r_in ) cont1 ))) ;41
                        stato = 4'b0101; $display(";A 42");		//(= stato    0b0101)) ;42
                    end
                    else begin
                        $display(";A 40");		//(= (bv-comp (bv-extract 1 1 r_in ) 0b1)   0b0)) ;40
                        cont1 = ({3'b000, r_in} - cont1); $display(";A 43");		//(= cont1    (bv-sub (bv-concat 0b000 r_in ) cont1 ))) ;43
                        stato = 4'b0110; $display(";A 44");		//(= stato    0b0110)) ;44
                    end
                end
            4'b0101 :
                begin
                    $display(";A 45");		//(= stato    0b0101)) ;45
                    if ((cont1 > 9'sb000011010)) begin
                        $display(";A 46");		//(= (bool-to-bv (bv-sgt cont1  0b000011010))   0b1)) ;46
                        cont1 = (cont1 - 9'b000011010); $display(";A 48");		//(= cont1    (bv-sub cont1  0b000011010))) ;48
                        stato = 4'b0101; $display(";A 49");		//(= stato    0b0101)) ;49
                    end
                    else begin
                        $display(";A 47");		//(= (bool-to-bv (bv-sgt cont1  0b000011010))   0b0)) ;47
                        stato = 4'b0111; $display(";A 50");		//(= stato    0b0111)) ;50
                    end
                end
            4'b0110 :
                begin
                    $display(";A 51");		//(= stato    0b0110)) ;51
                    if ((cont1 > 9'sb000111111)) begin
                        $display(";A 52");		//(= (bool-to-bv (bv-sgt cont1  0b000111111))   0b1)) ;52
                        cont1 = (cont1 + 9'b000011010); $display(";A 54");		//(= cont1    (bv-add cont1  0b000011010))) ;54
                        stato = 4'b0110; $display(";A 55");		//(= stato    0b0110)) ;55
                    end
                    else begin
                        $display(";A 53");		//(= (bool-to-bv (bv-sgt cont1  0b000111111))   0b0)) ;53
                        stato = 4'b0111; $display(";A 56");		//(= stato    0b0111)) ;56
                    end
                end
            4'b0111 :
                begin
                    $display(";A 57");		//(= stato    0b0111)) ;57
                    if ((r_in[3:2] == 2'b00)) begin
                        $display(";A 58");		//(= (bv-comp (bv-extract 3 2 r_in ) 0b00)   0b1)) ;58
                        cont1 = (cont1 - 9'b000010101); $display(";A 60");		//(= cont1    (bv-sub cont1  0b000010101))) ;60
                    end
                    else begin
                        $display(";A 59");		//(= (bv-comp (bv-extract 3 2 r_in ) 0b00)   0b0)) ;59
                        if ((r_in[3:2] == 2'b01)) begin
                            $display(";A 61");		//(= (bv-comp (bv-extract 3 2 r_in ) 0b01)   0b1)) ;61
                            cont1 = (cont1 - 9'b000101010); $display(";A 63");		//(= cont1    (bv-sub cont1  0b000101010))) ;63
                        end
                        else begin
                            $display(";A 62");		//(= (bv-comp (bv-extract 3 2 r_in ) 0b01)   0b0)) ;62
                            if ((r_in[3:2] == 2'b10)) begin
                                $display(";A 64");		//(= (bv-comp (bv-extract 3 2 r_in ) 0b10)   0b1)) ;64
                                cont1 = (cont1 + 9'b000000111); $display(";A 66");		//(= cont1    (bv-add cont1  0b000000111))) ;66
                            end
                            else begin
                                $display(";A 65");		//(= (bv-comp (bv-extract 3 2 r_in ) 0b10)   0b0)) ;65
                                cont1 = (cont1 + 9'b000011100); $display(";A 67");		//(= cont1    (bv-add cont1  0b000011100))) ;67
                            end
                        end
                    end
                    stato = 4'b1000; $display(";A 68");		//(= stato    0b1000)) ;68
                end
            4'b1000 :
                begin
                    $display(";A 69");		//(= stato    0b1000)) ;69
                    if ((cont1 < 9'sb000000000)) begin
                        $display(";A 70");		//(= (bool-to-bv (bv-slt cont1  0b000000000))   0b1)) ;70
                        x_out <= #1 cont1_inv[5:0]; $display(";A 72");		//(= x_out    (bv-extract 5 0 cont1_inv ))) ;72
                    end
                    else begin
                        $display(";A 71");		//(= (bool-to-bv (bv-slt cont1  0b000000000))   0b0)) ;71
                        x_out <= #1 cont1[5:0]; $display(";A 73");		//(= x_out    (bv-extract 5 0 cont1 ))) ;73
                    end
                    stato = 4'b0001; $display(";A 74");		//(= stato    0b0001)) ;74
                end
            default :
                begin
                    $display(";A 75");		//(= stato    0b0000)) ;75
                end
        endcase
    end
$display(";F cont = %b;cont1 = %b;cont1_inv = %b;r_in = %b;stato = %b;x_out = %b;clock = %b;reset = %b;stbi = %b;x_in = %b;",cont,cont1,cont1_inv,r_in,stato,x_out,clock,reset,stbi,x_in);
end

endmodule

module tb(input reset, input clock);

    // Generated top module signals
    reg  [5:0] x_in = 6'b0;
    reg  stbi = 1'b0;
    //reg  reset;
    wire [5:0] x_out;

    // Generated top module instance
    b11 _conc_top_inst(
            .x_in      ( x_in ),
            .stbi      ( stbi ),
            .clock     ( clock ),
            .reset     ( reset ),
            .x_out     ( x_out ));

    // Generated internal use signals
    reg  [31:0] _conc_pc;
    reg  [6:0] _conc_opcode;
    reg  [6:0] _conc_ram[0:3];


    // Generated program counter
    always @(posedge clock) begin
        _conc_opcode = _conc_ram[_conc_pc];
        stbi <= _conc_opcode[6];
        x_in <= _conc_opcode[5:0];
        _conc_pc = _conc_pc + 32'b1;
        $display(";_C %d", _conc_pc);
    end

    // Generated initial block
    initial begin
        //reset = 1'b0;
        _conc_pc = 32'b0;
        $readmemb("data.mem", _conc_ram);
        //reset = 1'b1;
    end
endmodule

  • 这个tb的含义是,打开data.mem文件,把里面的测试串传入进去。
  • _conc_ram[0:3]指的是我们会导入4个测试串。
  • 下面是data.mem的内容。
0101001
0000111
1101100
0101011

  • 注意底下这个回车是不可省略的!

1. 我们来查看一下文件夹结构

.
.
├── b11.v
├── data.mem
├── sim_main.cpp
└── src
    └── b11.v

1 directory, 4 files

2. 首先我们要对b11.v文件编译,把它变为cpp文件

  • 首先执行:
    verilator --cc b11.v --exe sim_main.cpp

  • 这个语句的含义是通过verilator把b11.v转化为cpp文件,并且指定test bench的名字为sim_main。

3. sim_main.cpp文件

  • 执行完过后我们生成了一个obj_dir文件,我们现在书写sim_main.cpp文件。
#include "Vb11.h"
#include "verilated.h"

vluint64_t sim_time = 0; // 用于计数时钟边沿
int main(int argc, char **argv, char **env) {
    Verilated::commandArgs(argc, argv);
    Vb11* top = new Vb11;
    
    while (sim_time <= 10)
    { 
        top->clock ^= 1;
        if(sim_time < 3){
            top->reset = 1;
        }else{
            top->reset = 0;
        }
        printf("clock = %d reset = %d sim_time = %d\n", top->clock,top->reset,sim_time);
        top->eval(); 
        sim_time++;
    }
    exit(0);
}

  • 我们要把这个文件拖进obj_dir中。
  • 现在的文件结构如下图所示:
.
├── b11.v
├── data.mem
├── obj_dir
│   ├── data.mem
│   ├── sim_main.cpp
│   ├── Vb11_classes.mk
│   ├── Vb11.cpp
│   ├── Vb11.h
│   ├── Vb11.mk
│   ├── Vb11__Syms.cpp
│   ├── Vb11__Syms.h
│   ├── Vb11__ver.d
│   └── Vb11__verFiles.dat
├── sim_main.cpp
└── src
    └── b11.v
  • 同理,我们也得把data.mem拖进去。

4. 我们编译出可执行文件

cd obj_dir
make -j8 -f Vb11.mk Vb11
  • make后面参数的含义可以自己查。
  • 最后我们进行仿真:
./Vb11 
clock = 1 reset = 1 sim_time = 0
;A 0
clock = 0 reset = 1 sim_time = 1
clock = 1 reset = 1 sim_time = 2
target
;A 3
;A 4
;A 5
;A 6
;A 7
;F cont = 000000;cont1 = 000000000;cont1_inv = 000000000;r_in = 000000;stato = 0000;x_out = 000000;clock = 1;reset = 1;stbi = 0;x_in = 000000;
;_C          1
clock = 0 reset = 0 sim_time = 3
clock = 1 reset = 0 sim_time = 4
;A 8
;A 9
;A 10
;A 11
;A 12
;F cont = 000000;cont1 = 000000000;cont1_inv = 000000000;r_in = 101001;stato = 0001;x_out = 000000;clock = 1;reset = 0;stbi = 0;x_in = 101001;
;_C          2
clock = 0 reset = 0 sim_time = 5
clock = 1 reset = 0 sim_time = 6
;A 13
;A 14
;A 16
;A 18
;F cont = 000000;cont1 = 000000000;cont1_inv = 000000000;r_in = 000111;stato = 0010;x_out = 000000;clock = 1;reset = 0;stbi = 0;x_in = 000111;
;_C          3
clock = 0 reset = 0 sim_time = 7
clock = 1 reset = 0 sim_time = 8
;A 19
;A 21
;A 28
;A 30
;F cont = 000000;cont1 = 000000000;cont1_inv = 000000000;r_in = 000111;stato = 0011;x_out = 000000;clock = 1;reset = 0;stbi = 1;x_in = 101100;
;_C          4
clock = 0 reset = 0 sim_time = 9
clock = 1 reset = 0 sim_time = 10
;A 32
;A 33
;A 35
;A 37
;F cont = 000000;cont1 = 000000000;cont1_inv = 000000000;r_in = 000111;stato = 0100;x_out = 000000;clock = 1;reset = 0;stbi = 0;x_in = 101011;
;_C          5
  • 我们观察到,只有处于上升沿的clock才能触发迭代,所以我们需要迭代(x+1)*2次,例如我们想迭代4个cycle,那么我们的while循环需要重复10次。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然,我可以为您提供关于Verilator的一些基本信息和教程。Verilator一个开源的Verilog仿真器,它可以将Verilog代码转换为C++代码,并生成可执行文件来模拟硬件行为。以下是一些学习Verilator的步骤和资源: 1. 安装Verilator:首先,您需要在您的系统上安装Verilator。您可以从官方网站(https://www.veripool.org/wiki/verilator)上下载并按照指南进行安装。 2. Verilator基础知识:了解Verilator的工作原理和基本概念是很重要的。您可以阅读官方文档中的入门指南,其中包含了一些基本示例和说明。 3. 编写Verilog代码:编写您想要仿真的Verilog模块。确保您的代码符合Verilog语法规范,并且您对所编写的硬件行为有清楚的理解。 4. 编译和运行:使用Verilator编译您的Verilog代码,并生成可执行文件。您可以使用Verilator提供的命令行选项来进行自定义设置和配置。运行可执行文件将启动硬件仿真。 5. 调试和验证:使用调试工具和仿真波形查看器来验证您的硬件仿真结果。这将帮助您识别和解决任何潜在的问题。 此外,还有一些在线资源可以帮助您深入了解Verilator的更多细节和用法,例如: - Verilator官方文档:官方网站提供了详细的文档,包括用户指南、参考手册和示例代码。 - Verilator GitHub仓库:您可以在GitHub上找到Verilator的源代码和一些示例项目。 - Verilator论坛:加入Verilator用户论坛,与其他用户交流经验和解决问题。 希望这些信息对您有所帮助!如果您有任何进一步的问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值