UART整体的仿真方法和testbench结构讲解

电子说

1.3w人已加入

描述

仿真框架

仿真部分结构和设计类似,同样有波特率、接收数据和发送数据模型。仿真的实现比较灵活,不用考虑可综合性。主要实现master功能,配置部分对DUT配置,发送模型发送数据到DUT,接收模型接收到数据后与发送数据进行对比,验证基本功能的正确性。

寄存器

仿真框架

伤真顶层产生时钟、复位,信号的初始化,测试用例的选择以及全局变量或参数的定义(如寄存器地址和某些多模块需要用到的变量)。

////////////////////////////////////////
`timescale 1ns/1ps
//`define tc01_00
//`define tc02_00
`define tc03_00

module    top();


reg            clk;                 // ARM clk
reg            clk26m;              // 26M function clk
reg            rst_;                // ARM clk's rst_
reg            rst26m_;             // function clk's rst_
reg            tx_data;             // send data line
wire           rx_data;             // receive data line
wire           uart_int;            // uart interrupt


// APB signals
reg  [3:0]     paddr;
reg  [31:0]    pwdata;
reg            psel;
reg            penable;
reg            pwrite;
wire [31:0]    prdata;

reg            baud_tclk;           // send data baud clk
reg            baud_rclk;           // receive data baud clk
reg            start;               // receive data baud enable signal
reg            rx_done;             // receive one data done
reg            w_state;             // write reg using signal
reg            r_state;             // read reg using signal
reg  [7:0]     tx_data_mem[0:999];  // send data memory
reg  [7:0]     rx_data_mem[0:999];  // receive data memory

reg  [31:0]    uart_tx;
reg  [31:0]    uart_rx;
reg  [31:0]    uart_baud;
reg  [31:0]    uart_conf;
reg  [31:0]    uart_rxtrig;
reg  [31:0]    uart_txtrig;
reg  [31:0]    uart_delay;
reg  [31:0]    uart_status;
reg  [31:0]    uart_rxfifo_stat;
reg  [31:0]    uart_txfifo_stat;

// when tx_model is runing a second time ,we don't want tx_cnt clean,
// so defind tx_cnt in top
integer        tx_cnt;

parameter      clk_period            = 10;
parameter      clk26m_period         = 38;
parameter      uart_tx_addr          = 4'h0;
parameter      uart_rx_addr          = 4'h1;
parameter      uart_baud_addr        = 4'h2;
parameter      uart_conf_addr        = 4'h3;
parameter      uart_rxtrig_addr      = 4'h4;
parameter      uart_txtrig_addr      = 4'h5;
parameter      uart_delay_addr       = 4'h6;
parameter      uart_status_addr      = 4'h7;
parameter      uart_rxfifo_stat_addr = 4'h8;
parameter      uart_txfifo_stat_addr = 4'h9;

`include "UART_baud.v"
`include "reg_op.v"
`include "check_int.v"
`include "uart_tx_model.v"
`include "uart_rx_model.v"
`include "tc01_00.v"
`include "tc02_00.v"
`include "tc03_00.v"

// cases of uart
UART_TOP    DUT(
        .clk(clk),
        .clk26m(clk26m),
        .rst_(rst_),
        .rst26m_(rst26m_),
        .paddr_i(paddr),
        .pwdata_i(pwdata),
        .psel_i(psel),
        .penable_i(penable),
        .pwrite_i(pwrite),
        .urxd_i(tx_data),
        .utxd_o(rx_data),
        .uart_int_o(uart_int),
        .prdata_o(prdata)
);

// always produce clk
always#(clk_period/2)    clk = ~clk;
always#(clk26m_period/2) clk26m = ~clk26m;


// signals initialize
initialbegin
    clk         = 1'b0;
    clk26m      = 1'b0;
    rst_        = 1'b1;
    rst26m_     = 1'b1;
    baud_tclk   = 1'b0;
    baud_rclk   = 1'b0;
    tx_data     = 1'b1;
    start       = 1'b0;
    rx_done     = 1'b0;
    w_state     = 1'b0;
    r_state     = 1'b0;
    uart_tx     = 32'h0;
    uart_baud   = 32'hf152;
    uart_conf   = 32'h34;
    uart_rxtrig = 32'h1;
    uart_txtrig = 32'h0;
    uart_delay  = 32'h2;
    uart_status = 32'h0;
    tx_cnt      = 0;
    #50;
    rst_      = 1'b0;
    rst26m_   = 1'b0;
    #100;
    rst_      = 1'b1;
    rst26m_   = 1'b1;

end


initialbegin
    @(posedge rst_) beginend
    fork
        UART_baud();
        check_int();
        uart_rx_model();
    join
end


initialbegin
    @(posedge rst_) beginend
    `ifdef tc01_00  tc01_00(10); `endif
    `ifdef tc02_00  tc02_00(); `endif
    `ifdef tc03_00  tc03_00(); `endif
end

endmodule

注意:每一个寄存器复位时都应该具有复位值,每一个输入在仿真时都应该具有初始值,确保功能的正确性以及仿真能顺利进行。

对于初学者或者常使用gui仿真的同学需要了解,在include task或者function等模型时,可以直接使用

`include "userfile.v"
或者
`include "D:/userdir/userfile.v"

两者不同之处在于前者需要指定一个include directory,这个目录包含需要inclue的文件;而后者使用绝对路径更加直接,但是在你的仿真环境需要移植或者include的文件比较多且分散时,使用第一种方式更为方便。

仿真顶层主要是将各个模型与DUT串接,形成串口的配置、收发数据通路。另外通过控制不同的仿真用例测试不同配置下的功能正确性。

testcase说明

所有的测试用例使用伪随机的方式进行,即数据和配置信息使用系统随机函数产生。

tc01_00: 对DUT接收部分的功能验证。随机配置波特率和串口功能设置,收发FIFO触发值为32'ha。控制发送数据模型发送数据到DUT,发送次数通过task input可控(10的倍数)。设计中达到RX FIFO触发值时,会触发中断,check int模块会一直工作检查处理中断,进行数据对比。

task  tc01_00;
inputinteger    run_num;

reg  [9:0]         baud;
reg  [2:0]         conf;
reg		[15:0]			 rdata;
integer            i;
integer            run_time;
integer            seed;

run_time = 0;
seed     = 0;
// memory initialize
for(i=0;i< 1000;i++) begin
    top.tx_data_mem[i] = {$random} % 255;    //$dist_uniform(seed,5,255);
end
repeat(run_num) begin
    baud = $dist_uniform(seed,13,676);
    conf = {$random} % 7;   //$dist_uniform(seed,0,7);
    @(posedge top.clk) beginend
    write_reg(top.uart_baud_addr,{20'hf,2'b0,baud});
    @(posedge top.clk) beginend
    write_reg(top.uart_txtrig_addr,32'ha);
    @(posedge top.clk) beginend
    write_reg(top.uart_rxtrig_addr,32'ha);
    @(posedge top.clk) beginend
    write_reg(top.uart_conf_addr,{26'h0,3'b111,conf});

      uart_tx_model(10);

    $display("------run -------%d ",run_time);
    run_time++;
    seed++;
end
$stop;
endtask

tc02_00: 对DUT发送部分的功能验证。随机配置波特率、功能、delay和收发FIFO触发值。寄存器配完后,配置串口发送寄存器,使DUT发送数据(重复1000次),将接收模型收到的数据与发送的数据对比,验证功能正确性。

task  tc02_00;

reg  [9:0]         baud;
reg  [2:0]         conf;
reg  [3:0]         delay;
reg  [3:0]         rxtrig;
reg  [3:0]         txtrig;

integer            i;
integer            j;
integer            seed;

seed     = 0;
j        = 0;
// memory initialize
for(i=0;i< 1000;i++) begin
    top.tx_data_mem[i] = $dist_uniform(seed,5,255);
end

begin
    baud  = $dist_uniform(seed,13,676);
    conf  = $dist_uniform(seed,0,7);
    delay = $dist_uniform(seed,0,15);
    rxtrig = $dist_uniform(seed,4,14);
    txtrig = $dist_uniform(seed,4,14);
    write_reg(top.uart_baud_addr,{20'hf,2'b0,baud});
    @(posedge top.clk) beginend
    write_reg(top.uart_txtrig_addr,{28'h0,txtrig});
    @(posedge top.clk) beginend
    write_reg(top.uart_rxtrig_addr,{28'h0,rxtrig});
    @(posedge top.clk) beginend
    write_reg(top.uart_conf_addr,{26'h0,3'b111,conf});
    @(posedge top.clk) beginend
    write_reg(top.uart_delay_addr,{28'h0,delay});
    repeat(16) begin
        @(posedge top.clk) beginend
        write_reg(top.uart_tx_addr,top.tx_data_mem[j]);
        j++;
        if(j > 999) begin
            j = 0;
        end
        $display("write %d data",j);
    end
    seed++;
end
endtask

tc03_00: DUT收发测试。随机配置波特率、功能、delay和收发FIFO触发值。寄存器完后,配置串口发送寄存器,使DUT发送数据(重复1000次);再使用发送数据模型发送数据1000次。

task  tc03_00;

reg  [9:0]         baud;
reg  [2:0]         conf;
reg  [3:0]         delay;
reg  [3:0]         rxtrig;
reg  [3:0]         txtrig;

integer            i;
integer            j;
integer            seed;


seed     = 0;
j        = 0;
// memory initialize
for(i=0;i< 1000;i++) begin
    top.tx_data_mem[i] = $dist_uniform(seed,1,255);
end

begin
    baud  = $dist_uniform(seed,13,676);
    conf  = $dist_uniform(seed,0,7);
    delay = $dist_uniform(seed,0,15);
    rxtrig = $dist_uniform(seed,4,14);
    txtrig = $dist_uniform(seed,4,14);
    write_reg(top.uart_baud_addr,{20'hf,2'b0,baud});
    @(posedge top.clk) beginend
    write_reg(top.uart_txtrig_addr,{28'h0,txtrig});
    @(posedge top.clk) beginend
    write_reg(top.uart_rxtrig_addr,{28'h0,rxtrig});
    @(posedge top.clk) beginend
    write_reg(top.uart_conf_addr,{26'h0,3'b111,conf});
    @(posedge top.clk) beginend
    write_reg(top.uart_delay_addr,{28'h0,delay});
    fork
    repeat(16) begin
        @(posedge top.clk) beginend
        write_reg(top.uart_tx_addr,top.tx_data_mem[j]);
        j++;
        if(j > 999) begin
            j = 0;
        end
        $display("write %d data",j);
    end
    uart_tx_model(1000);
    join
    seed++;
end
endtask

本设计只使用了三个测试用例,对模块的仿真验证并不完备,读者可以根据自己的使用情况增加不同功能的用例。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分