現在我們已經移植好了OpenC906到xc7k325t,仿真器連接沒問題,程序加載運行也可以了,后面就可以進行各種開發測試了。 往往可能遇到問題這時就需要修改rtl代碼重新出bit文件,但是綜合,實現生成bit又比較漫長,所以我們就可以通過仿真來跑c code來先確認一下,再生成bit進行測試。
源碼中點擊sim_1目錄
添加仿真頂層文件






/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.Licensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.*/`define NC_SIM`define NOISA`timescale 1ns/100ps`define CLK_PERIOD 2`define TCLK_PERIOD 40`define MAX_RUN_TIME 700000000`define SOC_TOP tb.x_soc`define RTL_MEM tb.x_soc.x_axi_slave128.x_f_spsram_16384x128_L`define RTL_MEM2 tb.x_soc.x_axi_slave128.x_f_spsram_16384x128_H`define CPU_TOP tb.x_soc.x_cpu_sub_system_axi.x_c906_wrapper.x_cpu_top`define tb_retire0 `CPU_TOP.core0_pad_retire`define retire0_pc `CPU_TOP.core0_pad_retire_pc[39:0]`define CPU_CLK `CPU_TOP.pll_core_cpuclk`define CPU_RST `CPU_TOP.pad_cpu_rst_bmodule tb();reg clk;reg jclk;reg rst_b;reg jrst_b;reg jtap_en;wire jtg_tms;wire jtg_tdi;wire jtg_tdo;wire pad_yy_gate_clk_en_b;static integer FILE;wire uart0_sin;wire [7:0]b_pad_gpio_porta;assign pad_yy_gate_clk_en_b = 1'b1;initialbeginclk =0;forever begin#(`CLK_PERIOD/2) clk = ~clk;endendinitialbeginjclk = 0;forever begin#(`TCLK_PERIOD/2) jclk = ~jclk;endendinitialbeginrst_b = 1;#100;rst_b = 0;#100;rst_b = 1;endinitialbeginjrst_b = 1;#400;jrst_b = 0;#400;jrst_b = 1;endinteger i;bit [31:0] mem_inst_temp [65536];bit [31:0] mem_data_temp [65536];integer j;initialbegin$display("\t********* Init Program *********");$display("\t********* Wipe memory to 0 *********");for(i=0; i < 32'h16384; i=i+1)begin`RTL_MEM.ram0.mem[i][7:0] = 8'h0;`RTL_MEM.ram1.mem[i][7:0] = 8'h0;`RTL_MEM.ram2.mem[i][7:0] = 8'h0;`RTL_MEM.ram3.mem[i][7:0] = 8'h0;`RTL_MEM.ram4.mem[i][7:0] = 8'h0;`RTL_MEM.ram5.mem[i][7:0] = 8'h0;`RTL_MEM.ram6.mem[i][7:0] = 8'h0;`RTL_MEM.ram7.mem[i][7:0] = 8'h0;`RTL_MEM.ram8.mem[i][7:0] = 8'h0;`RTL_MEM.ram9.mem[i][7:0] = 8'h0;`RTL_MEM.ram10.mem[i][7:0] = 8'h0;`RTL_MEM.ram11.mem[i][7:0] = 8'h0;`RTL_MEM.ram12.mem[i][7:0] = 8'h0;`RTL_MEM.ram13.mem[i][7:0] = 8'h0;`RTL_MEM.ram14.mem[i][7:0] = 8'h0;`RTL_MEM.ram15.mem[i][7:0] = 8'h0;end$display("\t********* Read program *********");$readmemh("inst.pat", mem_inst_temp);$readmemh("data.pat", mem_data_temp);$display("\t********* Load program to memory *********");i=0;for(j=0;i<32'h2000;i=j/4)begin`RTL_MEM.ram0.mem[i][7:0] = mem_inst_temp[j][31:24];`RTL_MEM.ram1.mem[i][7:0] = mem_inst_temp[j][23:16];`RTL_MEM.ram2.mem[i][7:0] = mem_inst_temp[j][15: 8];`RTL_MEM.ram3.mem[i][7:0] = mem_inst_temp[j][ 7: 0];j = j+1;`RTL_MEM.ram4.mem[i][7:0] = mem_inst_temp[j][31:24];`RTL_MEM.ram5.mem[i][7:0] = mem_inst_temp[j][23:16];`RTL_MEM.ram6.mem[i][7:0] = mem_inst_temp[j][15: 8];`RTL_MEM.ram7.mem[i][7:0] = mem_inst_temp[j][ 7: 0];j = j+1;`RTL_MEM.ram8.mem[i][7:0] = mem_inst_temp[j][31:24];`RTL_MEM.ram9.mem[i][7:0] = mem_inst_temp[j][23:16];`RTL_MEM.ram10.mem[i][7:0] = mem_inst_temp[j][15: 8];`RTL_MEM.ram11.mem[i][7:0] = mem_inst_temp[j][ 7: 0];j = j+1;`RTL_MEM.ram12.mem[i][7:0] = mem_inst_temp[j][31:24];`RTL_MEM.ram13.mem[i][7:0] = mem_inst_temp[j][23:16];`RTL_MEM.ram14.mem[i][7:0] = mem_inst_temp[j][15: 8];`RTL_MEM.ram15.mem[i][7:0] = mem_inst_temp[j][ 7: 0];j = j+1;endi=0;for(j=0;i<32'h2000;i=j/4)begin`RTL_MEM.ram0.mem[i+32'h2000][7:0] = mem_data_temp[j][31:24];`RTL_MEM.ram1.mem[i+32'h2000][7:0] = mem_data_temp[j][23:16];`RTL_MEM.ram2.mem[i+32'h2000][7:0] = mem_data_temp[j][15: 8];`RTL_MEM.ram3.mem[i+32'h2000][7:0] = mem_data_temp[j][ 7: 0];j = j+1;`RTL_MEM.ram4.mem[i+32'h2000][7:0] = mem_data_temp[j][31:24];`RTL_MEM.ram5.mem[i+32'h2000][7:0] = mem_data_temp[j][23:16];`RTL_MEM.ram6.mem[i+32'h2000][7:0] = mem_data_temp[j][15: 8];`RTL_MEM.ram7.mem[i+32'h2000][7:0] = mem_data_temp[j][ 7: 0];j = j+1;`RTL_MEM.ram8.mem[i+32'h2000][7:0] = mem_data_temp[j][31:24];`RTL_MEM.ram9.mem[i+32'h2000][7:0] = mem_data_temp[j][23:16];`RTL_MEM.ram10.mem[i+32'h2000][7:0] = mem_data_temp[j][15: 8];`RTL_MEM.ram11.mem[i+32'h2000][7:0] = mem_data_temp[j][ 7: 0];j = j+1;`RTL_MEM.ram12.mem[i+32'h2000][7:0] = mem_data_temp[j][31:24];`RTL_MEM.ram13.mem[i+32'h2000][7:0] = mem_data_temp[j][23:16];`RTL_MEM.ram14.mem[i+32'h2000][7:0] = mem_data_temp[j][15: 8];`RTL_MEM.ram15.mem[i+32'h2000][7:0] = mem_data_temp[j][ 7: 0];j = j+1;endendinitialbegin#`MAX_RUN_TIME;$display("**********************************************");$display("* meeting max simulation time, stop! *");$display("**********************************************");FILE = $fopen("run_case.report","a");$fwrite(FILE,"TEST FAIL");$finish;endreg [31:0] retire_inst_in_period;reg [31:0] cycle_count;`define LAST_CYCLE 50000always @(posedge clk or negedge rst_b)beginif(!rst_b)cycle_count[31:0] <= 32'b1;elsecycle_count[31:0] <= cycle_count[31:0] + 1'b1;endalways @(posedge clk or negedge rst_b)beginif(!rst_b) //reset to zeroretire_inst_in_period[31:0] <= 32'b0;else if( (cycle_count[31:0] % `LAST_CYCLE) == 0)//check and reset retire_inst_in_period every 50000 cyclesbeginif(retire_inst_in_period[31:0] == 0)begin$display("*************************************************************");$display("* Error: There is no instructions retired in the last %d cycles! *", `LAST_CYCLE);$display("* Simulation Fail and Finished! *");$display("*************************************************************");#10;FILE = $fopen("run_case.report","a");$fwrite(FILE,"TEST FAIL");$finish;endretire_inst_in_period[31:0] <= 32'b0;endelse if(`tb_retire0)retire_inst_in_period[31:0] <= retire_inst_in_period[31:0] + 1'b1;endreg [39:0] cpu_awaddr;reg [3:0] cpu_awlen;reg [15:0] cpu_wstrb;reg cpu_wvalid;reg [63:0] value0;reg [63:0] value1;always @(posedge clk)begincpu_awlen[3:0] <= `SOC_TOP.biu_pad_awlen[3:0];cpu_awaddr[31:0] <= `SOC_TOP.biu_pad_awaddr[31:0];cpu_wvalid <= `SOC_TOP.biu_pad_wvalid;cpu_wstrb <= `SOC_TOP.biu_pad_wstrb;value0 <= `CPU_TOP.x_aq_top_0.x_aq_core.x_aq_rtu_top.x_aq_rtu_wb.wb_wb0_data[63:0];value1 <= `CPU_TOP.x_aq_top_0.x_aq_core.x_aq_rtu_top.x_aq_rtu_wb.wb_wb1_data[63:0];endalways @(posedge clk)beginif((value0 == 64'h444333222) || (value1 == 64'h444333222))begin$display("\n**********************************************");$display("* simulation finished successfully *");$display("**********************************************");#10;FILE = $fopen("run_case.report","a");$fwrite(FILE,"TEST PASS");$fclose(FILE);$finish;endelse if ((value0 == 64'h2382348720) || (value1 == 64'h2382348720))begin$display("**********************************************");$display("* simulation finished with error *");$display("**********************************************");#10;FILE = $fopen("run_case.report","a");$fwrite(FILE,"TEST FAIL");$fclose(FILE);$finish;endelse if((cpu_awlen[3:0] == 4'b0) &&(cpu_awaddr[31:0] == 32'h10015000) &&cpu_wvalid)beginFILE = $fopen("run_case.report","a");if(cpu_wstrb[15:0] == 16'hf) begin$write("%c", `SOC_TOP.biu_pad_wdata[7:0]);$fwrite(FILE,"%c",`SOC_TOP.biu_pad_wdata[7:0]);$fclose(FILE);endelse if(cpu_wstrb[15:0] == 16'hf0) begin$write("%c", `SOC_TOP.biu_pad_wdata[39:32]);$fwrite(FILE,"%c",`SOC_TOP.biu_pad_wdata[39:32]);$fclose(FILE);endelse if(cpu_wstrb[15:0] == 16'hf00) begin$write("%c", `SOC_TOP.biu_pad_wdata[71:64]);$fwrite(FILE,"%c",`SOC_TOP.biu_pad_wdata[71:64]);$fclose(FILE);endelse if(cpu_wstrb[15:0] == 16'hf000) begin$write("%c", `SOC_TOP.biu_pad_wdata[103:96]);$fwrite(FILE,"%c",`SOC_TOP.biu_pad_wdata[103:96]);$fclose(FILE);endendend`ifndef NO_DUMPinitialbegin`ifdef NC_SIM$dumpfile("test.vcd");$dumpvars;`else`ifdef IVERILOG_SIM$dumpfile("test.vcd");$dumpvars;`else$display("######time:%d, Dump start######",$time);$fsdbDumpvars();`endif`endifend`endifassign jtg_tdi = 1'b0;assign jtg_tms = 1'b0;assign uart0_sin = 1'b1;soc x_soc(.i_pad_clk ( clk ),.b_pad_gpio_porta ( b_pad_gpio_porta ),.i_pad_jtg_trst_b ( jrst_b ),.i_pad_jtg_nrst_b ( rst_b ),.i_pad_jtg_tclk ( jclk ),.i_pad_jtg_tdi ( jtg_tdi ),.i_pad_jtg_tms ( jtg_tms ),.i_pad_uart0_sin ( uart0_sin ),.o_pad_jtg_tdo ( jtg_tdo ),.o_pad_uart0_sout ( uart0_sout ),.i_pad_rst_b ( rst_b ));endmodule
因為用到了sv的語法,tb.v要修改屬性為sv

將上一篇編譯代碼時生成的
data.pat,inst.pat,case,pat三個文件復制到
放到C906_325T_2017.sim\sim_1\behav\xsim下
Tb.v會加載data.pat和inst.pat到RAM運行。
Settings下按照如下設置仿真的頂層模塊位tb和我們的tb.v中的模塊對應

開始仿真

跑完之后顯示scope,objects,waveform窗口

如果沒有則可以window菜單下選上

此時就可以看對應信號的波形,默認是頂層文件的信號都會抓出

如果要看對應信號,可以scope中選模塊,objects下右鍵點擊某個具體信號Add to Wave Window

Tcl命令對應add_wave {{/tb/x_soc/x_apb/x_uart/x_uart_baud_gen/trans_clk_en}}
如果是要抓該信號則是Log to ave Database
tcl命令對應
log_wave {{/tb/x_soc/x_apb/x_uart/x_uart_baud_gen/trans_clk_en}}
此時wcfg文件會被修改,然后ctrl+s保存,提示wcfg是否添加到工程時選是
然后再跑一次仿真則該信號會被抓取可以顯示波形。
默認仿真時長位100ns可能太短,可以直接tcl啟動仿真時設置仿真時長
run 1000000 ns
加速仿真
設置多核處理
set_param general.maxThreads 8
降低精度
`timescale 1ns / 100ps
smart_run\logical\uart\uart_apb_reg.v中
assign uart_reg_haddr[5:0] = apb_uart_paddr[7:2];
串口地址為0x10010030 且一個WORD對應一個8位寄存器

以上分享了vivado中進行仿真的過程,可以通過仿真模擬程序的運行,查看各種信號,仿真確認沒問題之后再生成bit文件,fpga上真實運行bit測試,這樣可以提高效率。