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

仿真框架仿真部分结构和设计类似,同样有波特率、接收数据和发送数据模型。仿真的实现比较灵活,不用考虑可综合性。主要实现master功能,配置部分对dut配置,发送模型发送数据到dut,接收模型接收到数据后与发送数据进行对比,验证基本功能的正确性。
仿真框架
伤真顶层产生时钟、复位,信号的初始化,测试用例的选择以及全局变量或参数的定义(如寄存器地址和某些多模块需要用到的变量)。
////////////////////////////////////////`timescale 1ns/1ps//`define tc01_00//`define tc02_00`define tc03_00module top();reg clk; // arm clkreg clk26m; // 26m function clkreg rst_; // arm clk's rst_reg rst26m_; // function clk's rst_reg tx_data; // send data linewire rx_data; // receive data linewire uart_int; // uart interrupt// apb signalsreg [3:0] paddr;reg [31:0] pwdata;reg psel;reg penable;reg pwrite;wire [31:0] prdata;reg baud_tclk; // send data baud clkreg baud_rclk; // receive data baud clkreg start; // receive data baud enable signalreg rx_done; // receive one data donereg w_state; // write reg using signalreg r_state; // read reg using signalreg [7:0] tx_data_mem[0:999]; // send data memoryreg [7:0] rx_data_mem[0:999]; // receive data memoryreg [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 topinteger 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 uartuart_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 clkalways#(clk_period/2) clk = ~clk;always#(clk26m_period/2) clk26m = ~clk26m;// signals initializeinitialbegin 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;endinitialbegin @(posedge rst_) beginend fork uart_baud(); check_int(); uart_rx_model(); joinendinitialbegin @(posedge rst_) beginend `ifdef tc01_00 tc01_00(10); `endif `ifdef tc02_00 tc02_00(); `endif `ifdef tc03_00 tc03_00(); `endifendendmodule注意:每一个寄存器复位时都应该具有复位值,每一个输入在仿真时都应该具有初始值,确保功能的正确性以及仿真能顺利进行。
对于初学者或者常使用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 initializefor(i=0;i< 1000;i++) begin top.tx_data_mem[i] = {$random} % 255; //$dist_uniform(seed,5,255);endrepeat(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;endtasktc02_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 initializefor(i=0;i 999) begin j = 0; end $display(write %d data,j); end seed++;endendtasktc03_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 initializefor(i=0;i 999) begin j = 0; end $display(write %d data,j); end uart_tx_model(1000); join seed++;endendtask本设计只使用了三个测试用例,对模块的仿真验证并不完备,读者可以根据自己的使用情况增加不同功能的用例。

中芯国际截至2011年9月30日止3个月业绩公布
尼康D7200相机拥有2416万的有效像素,能瞬间捕捉被摄物体留住感动瞬间
质量流量计检定装置的研制与应用
如何实现S7-1200和三菱Q系列PLC的开放式以太网通信?
新版tplink路由器修改密码的方法
UART整体的仿真方法和testbench结构讲解
FM2822型可调光电子镇流器控制器及其应用
现代计算机的基石——英特尔8086处理器
盘点未来物联网新能源——纸基电池
什么是宏内核、微内核?
物联网如何增强智能停车技术?
芯片设计进阶之路—从CMOS到建立时间和保持时间
天津联通联合华为,对基础通信网络进行升级使网络智能化
ST多核微控制器SPC56EL70符合最严格的汽车安全标准
过孔——PCB设计信号失真的原因,不容小觑
比特币对于人们的日常用处是什么
北斗智联再添两项国家级认证
半导体支出逐渐集中化 Intel、三星和台积电占比近六成
《炬丰科技-半导体工艺》硅片清洗技术的演变
Intel酷睿i5-9400F怎么样 值不值得买