0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

冬至子 来源:两猿社 作者:IC猿 2023-06-05 16:08 次阅读

仿真框架

仿真部分结构和设计类似,同样有波特率、接收数据和发送数据模型。仿真的实现比较灵活,不用考虑可综合性。主要实现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

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

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

    关注

    31

    文章

    5343

    浏览量

    120347
  • 接收机
    +关注

    关注

    8

    文章

    1181

    浏览量

    53471
  • FIFO存储
    +关注

    关注

    0

    文章

    103

    浏览量

    5971
  • UART接口
    +关注

    关注

    0

    文章

    124

    浏览量

    15294
  • DUT
    DUT
    +关注

    关注

    0

    文章

    189

    浏览量

    12381
收藏 人收藏

    评论

    相关推荐

    谁有基于matlab仿真的TSC型动态无功补偿装置仿真整体结构

    基于DSP的TSC型动态无功补偿装置matlab仿真整体结构图啊,谢谢
    发表于 04-09 15:52

    用quartusii 9.1 生成的vht文件,testbench等问题

    1.quartusii 9.1 生成的testbench 后用VHDL 编写后续程序的格式, 方法2如何用modelsim 关联quartusii仿真3是不是testbench 没有问
    发表于 05-17 21:36

    testbench 的问题

    给位大神,想问一下testbench中是否只是写clk,reset等的变化?不是的话,里面究竟怎么写才能等到自己的仿真?能否附一例子讲解?谢谢
    发表于 04-11 16:03

    如何使用quartus ii 和modelsim -ae 快速进行Testbench功能仿真

    ,进行相关设置,如如图三.输入RTL级代码和Testbench文件RTL级代码和Testbench的相关语法,请参考其他书籍,这里不予讲述,主要讲解如何快速进行功能级仿真。3.1建立一
    发表于 11-29 21:35

    testbench设置的问题

    本帖最后由 平漂流 于 2017-5-21 11:09 编辑 如图,看Verilog仿真视频教程里面,在testbench设置时候,直接复制“blocking_vlg_tst”到top
    发表于 05-21 11:04

    关于VHDL的testbench仿真问题

    写了很多VHDL文件和testbench文件,在仿真时信号的值总是U,请问有谁遇到过这种问题么,怎样解决,谢谢各位大牛!
    发表于 09-29 17:20

    怎样用VHDL写TESTBENCH

    Testbench 不仅要产生激励也就是输入,还要验证响应也就是输出。当然也可以只产生激励,然后通过波形窗口通过人工的方法去验证波形,这种方法只能适用于小规模的设计。在 ISE 环境中,当前资源操作
    发表于 11-28 11:19

    testbench编写基本结构

    testbench编写基本结构
    发表于 09-28 17:43

    使用三种自动化testbench验证方法

    自我检查testbench设计:与前两种方法不同,该方法实时检查预期结果和实际结果,而不是仿真结束后才检查。在testbench中插入错误追
    的头像 发表于 11-20 11:26 3747次阅读

    在模块化设计过程中编写testbench仿真方法

    在开始设计前,根据设计划分好各功能模块(为了叙述方便,这里以对“FPGA数字信号处理(十三)锁相环位同步技术的实现”中设计的系统仿真为例)。编写好第一个子模块(本例中为双相时钟生成模块),在Vivado中添加仿真sim文件,编写test
    的头像 发表于 11-20 11:29 3935次阅读

    VHDL与Verilog硬件描述语言如何用TestBench来进行仿真

    TestBench来进行仿真是一个很不错的选择。 VHDL与Verilog语言的语法规则不同,它们的TestBench的具体写法也不同,但是应包含的基本结构大体相似,在VHDL的
    的头像 发表于 08-04 14:16 3824次阅读

    testbench是什么? testbench测试的机制是什么?

    废话不多说直接上干货,testbench就是对写的FPGA文件进行测试的文件,可以是verilog也可以是VHDL。
    的头像 发表于 06-28 16:44 4836次阅读
    <b class='flag-5'>testbench</b>是什么? <b class='flag-5'>testbench</b>测试的机制是什么?

    Testbench的基本组成和设计规则

      对于小型设计来说,最好的测试方式便是使用TestBench和HDL仿真器来验证其正确性。一般TestBench需要包含这些部分:实例化待测试设计、使用测试向量激励设计、将结果输出到终端或波形窗口便于可视化观察、比较实际结果和
    的头像 发表于 09-01 09:57 1271次阅读
    <b class='flag-5'>Testbench</b>的基本组成和设计规则

    VHDL与Verilog硬件描述语言TestBench的编写

    TestBench来进行仿真是一个很不错的选择。VHDL与Verilog语言的语法规则不同,它们的TestBench的具体写法也不同,但是应包含的基本结构大体相似,在VHDL的
    的头像 发表于 09-09 10:16 1741次阅读
    VHDL与Verilog硬件描述语言<b class='flag-5'>TestBench</b>的编写

    FPGA入门必备:Testbench仿真文件编写实例详解

    在编写完HDL代码后,往往需要通过仿真软件Modelsim或者Vivadao自带的仿真功能对HDL代码功能进行验证,此时我们需要编写Testbench文件对HDL功能进行测试验证。
    发表于 04-29 10:43 2051次阅读