在实际开发中,在写完一个module之后,很少会直接下板测试,更多是选择先进行仿真,在仿真之前,就要先构建仿真环境。
本小节就来构建O_board的全系统仿真环境,并通过一个简单的例子来进行验证。
1,RTL的修改
我们之前曾加构建过基于ML501的仿真环境,对于O_board来说,大体步骤是相似的。
所以在这之前,请先参考:http://blog.csdn.net/rill_zhen/article/details/16880801
对于O_board,在对仿真工程综合过程中,主要有两类问题:
a,提示模块接口数量与例化时不匹配。
解决方法:仔细对比模块端口,将多余的信号去掉。
b,提示某些信号重复定义,或者在本区域内已经定义。原因是在定义信号的前面,已经有使用本信号的代码。
解决方法:将信号定义提前,或者将信号定义去掉(modelsim会自动定义)。建议采用第一种方式。
需要注意的是SDRAM的例化,需要修改clk,cke,cs_n,三个信号。
由于是全系统仿真,除了要综合出design以及testbench之外,我们还需要编写用于仿真时运行的软件。步骤如下:
a,创建软件仿真目录和文件
cd ~/soc-design/orpsocv2/boards/altera/ordb2a-ep4ce22/sw/tests mkdir uart cd uart mkdir sim cd sim touch uart.c cp ../../usbhostslave/sim/Makefile .
b,编写仿真软件程序
编辑uart.c,如下所示:
/* * file name : uart.c * function : uart controller test * date : 2014-03-13 * author : Rill */ #include "cpu-utils.h" #include "board.h" #include "int.h" #include "uart.h" #include "printf.h" void delay(volatile unsigned int delay) { while(delay--) { ;//do nothing } return; } int main (void) { uart_init(0); printf("uart_init done!\n"); while(1) { delay(1); printf("loop...\n"); } return 0; }
在准备好RTL和测试程序之后,我们就可以进行仿真了。步骤如下:
a,进入仿真执行目录
cd ~/soc-design/orpsocv2/boards/altera/ordb2a-ep4ce22/sim/run
b,执行仿真
make rtl-test TEST=uart PRELOAD_RAM=1
除了TEST,PRELOAD_RAM这两个参数之外,还有其他的参数,可以辅助我们更方便的debug。
比如:
VCD,使能波形导出。
VCD_DELAY,可以指定开始导出波形的时间(ps)。
VCD_DELAY_INSNS,可以指定从第几条指令开始导出波形。
VCD_DEPTH,可以指定导出哪些模块的波形。
VPI,可以对JTAG和debug_if模块进行仿真。
END_TIME,可以指定仿真结束时间。
其他参数可参考orpsoc.pdf和orpsoc_testbench.v获得。
下面是orpsoc_testbench.v中的相关代码:
`ifdef JTAG_DEBUG `ifdef VPI_DEBUG // Debugging interface vpi_debug_module vpi_dbg ( .tms(tms_pad_i), .tck(tck_pad_i), .tdi(tdi_pad_i), .tdo(tdo_pad_o) ); `else // If no VPI debugging, tie off JTAG inputs assign tdi_pad_i = 1; assign tck_pad_i = 0; assign tms_pad_i = 1; `endif // !`ifdef VPI_DEBUG_ENABLE `endif // `ifdef JTAG_DEBUG `ifdef VCD reg vcd_go = 0; always @(vcd_go) begin `ifdef VCD_DELAY #(`VCD_DELAY); `endif // Delay by x insns `ifdef VCD_DELAY_INSNS #10; // Delay until after the value becomes valid while (monitor.insns < `VCD_DELAY_INSNS) @(posedge clk); `endif `ifdef SIMULATOR_MODELSIM // Modelsim can GZip VCDs on the fly if given in the suffix `define VCD_SUFFIX ".vcd.gz" `else `define VCD_SUFFIX ".vcd" `endif `ifndef SIM_QUIET $display("* VCD in %s\n", {"../out/",`TEST_NAME_STRING,`VCD_SUFFIX}); `endif $dumpfile({"../out/",`TEST_NAME_STRING,`VCD_SUFFIX}); `ifndef VCD_DEPTH `define VCD_DEPTH 0 `endif $dumpvars(`VCD_DEPTH); end `endif // `ifdef VCD initial begin `ifndef SIM_QUIET $display("\n* Starting simulation of design RTL.\n* Test: %s\n", `TEST_NAME_STRING ); `endif `ifdef VCD vcd_go = 1; `endif end // initial begin `ifdef END_TIME initial begin #(`END_TIME); `ifndef SIM_QUIET $display("* Finish simulation due to END_TIME being set at %t", $time); `endif $finish; end `endif `ifdef END_INSNS initial begin #10 while (monitor.insns < `END_INSNS) @(posedge clk); `ifndef SIM_QUIET $display("* Finish simulation due to END_INSNS count (%d) reached at %t", `END_INSNS, $time); `endif $finish; end `endif
执行:make rtl-test TEST=uart PRELOAD_RAM=1
采用这种方式,仿真速度最快,可以大体判断程序执行过程。
执行:make rtl-test TEST=uart PRELOAD_RAM=1 VCD=1
通过VCD=1,我们可以得到软件执行时,所有模块的波形。
执行:make rtl-test VPI=1
在一般仿真时,我们无法对jtag和debug_if模块进行仿真,因为一般仿真时,这两个模块是不工作的(软件是直接加载到内存的),如果想对这两个模块进行仿真,我们可以通过VPI=1来实现。采用VPI=1,可以建立RSP server(端口号:50002),用来与gdb相连,具体工作原理,我们之前介绍过,如有疑问,请参考:(http://blog.csdn.net/rill_zhen/article/details/14167515)。
一旦建立的RSP server,我们就可以使用or32-elf-gdb来与之连接,并向SDRAM 的仿真模型里下载软件程序了。这样,我们就可以得到JTAG和debug_if两个模块的工作波形了。
本实验所需的所有内容,我已上传:
O_board-4-仿真环境的构建与验证,布布扣,bubuko.com
原文:http://blog.csdn.net/rill_zhen/article/details/21190757