`timescale 1 ns / 1 ps `define ENABLE_REG_RW1_TEST "generated/log/reg_rw1_tc.log" module ShinTopSpiTb( ); reg clock; reg reset; reg [15:0] multiCLK; reg clock2; reg [15:0] multiCLK2; `include "dev_predef.vh" `ifdef DEFINE_SLAVE_DEVICE `define DEV_NUM 4 //slave num `define ALL_DEV_NUM (`DEV_NUM + 1) // slave + master `define SPI_CSN_NUM (`ALL_DEV_NUM * 3) `define HW_SERIAL 0 //48'h31303050584c //(48'h4c5850303031) `define IQSPI_PINS(N) (`N*4+3):(`N*4) `define EQSPI_PINS(N) ((`N + `ALL_DEV_NUM)*4+3):((`N + `ALL_DEV_NUM)*4) `define IQSPI_MISO(N) qspi_miso[`IQSPI_PINS(`N)] `define EQSPI_MISO(N) qspi_miso[`EQSPI_PINS(`N)] `define IQSPI_CSN_NUM(id) (`id) `define ESPI_CSN_NUM(id) ((`id)+(`ALL_DEV_NUM)) `define EQSPI_CSN_NUM(id) ((`id)+(`ALL_DEV_NUM)*2) `define IQSPI_CSN(id) spi_csn[`IQSPI_CSN_NUM(`id)] `define ESPI_CSN(id) spi_csn[`ESPI_CSN_NUM(`id)] `define EQSPI_CSN(id) spi_csn[`EQSPI_CSN_NUM(`id)] `define QSPI_MUX_MISO_INIT \ (`IQSPI_MISO(0) & ~{4{`IQSPI_CSN(0)}}) |\ (`IQSPI_MISO(1) & ~{4{`IQSPI_CSN(1)}}) |\ (`IQSPI_MISO(2) & ~{4{`IQSPI_CSN(2)}}) |\ (`IQSPI_MISO(3) & ~{4{`IQSPI_CSN(3)}}) |\ (`IQSPI_MISO(4) & ~{4{`IQSPI_CSN(4)}}) |\ (`EQSPI_MISO(0) & ~{4{`EQSPI_CSN(0)}}) |\ (`EQSPI_MISO(1) & ~{4{`EQSPI_CSN(1)}}) |\ (`EQSPI_MISO(2) & ~{4{`EQSPI_CSN(2)}}) |\ (`EQSPI_MISO(3) & ~{4{`EQSPI_CSN(3)}}) |\ (`EQSPI_MISO(4) & ~{4{`EQSPI_CSN(4)}}) `define SPI_MUX_MISO_INIT \ ( spi_miso[0] & ~`ESPI_CSN(0)) |\ ( spi_miso[1] & ~`ESPI_CSN(1)) |\ ( spi_miso[2] & ~`ESPI_CSN(2)) |\ ( spi_miso[3] & ~`ESPI_CSN(3)) |\ ( spi_miso[4] & ~`ESPI_CSN(4)) `endif wire [(`DEV_NUM - 1):0] dDat_w; wire [(`DEV_NUM - 1):0] uDat_w; wire spi_sck; wire spi_mosi; wire [(`ALL_DEV_NUM - 1):0] spi_miso; reg [(`SPI_CSN_NUM - 1):0] spi_csn; wire qspi_sck; wire [3:0] qspi_mosi; //wire [40-1:0] qspi_miso; wire [(`ALL_DEV_NUM * 4 * 2 - 1):0] qspi_miso; integer spidata_file; integer c_line; integer _pos; integer _len; integer _t_start; integer _t_end; reg [63:0] _temp_time; reg _reset_deactive; wire [(`ALL_DEV_NUM - 1):0] isSoftReset; reg [(`ALL_DEV_NUM - 1):0] isSoftReset_reg; generate for( genvar i = 0; i < `ALL_DEV_NUM; i = i + 1 ) begin always @(posedge clock or posedge reset) begin if(reset) isSoftReset_reg[i] <= 1'b0; else isSoftReset_reg[i] <= isSoftReset[i]; end end endgenerate wire [`DEV_NUM:0] io_int_sig; reg latch0; reg latch1; ShinTop s_ShinTop_Mst( .clock(clock), .reset(reset | isSoftReset_reg[0]), .io_multiCLK_0(multiCLK[0]), .io_multiCLK_1(multiCLK[1]), .io_multiCLK_2(multiCLK[2]), .io_multiCLK_3(multiCLK[3]), .io_multiCLK_4(multiCLK[4]), .io_multiCLK_5(multiCLK[5]), .io_multiCLK_6(multiCLK[6]), .io_multiCLK_7(multiCLK[7]), .io_multiCLK_8(multiCLK[8]), .io_multiCLK_9(multiCLK[9]), .io_multiCLK_10(multiCLK[10]), .io_multiCLK_11(multiCLK[11]), .io_multiCLK_12(multiCLK[12]), .io_multiCLK_13(multiCLK[13]), .io_multiCLK_14(multiCLK[14]), .io_multiCLK_15(multiCLK[15]), .io_dDatIn(1'b0), .io_dDatOut(dDat_w[0]), .io_uDatIn(uDat_w[0]), .io_uDatOut(), .io_iqspi_sck(qspi_sck), .io_iqspi_mosi(qspi_mosi), .io_iqspi_miso(`IQSPI_MISO(0)), .io_iqspi_isDirIn(), .io_iqspi_csn(`IQSPI_CSN(0)), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[0]), .io_ospi_csn (`ESPI_CSN(0)), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(`EQSPI_MISO(0)), .io_oqspi_isDirIn(), .io_oqspi_csn(`EQSPI_CSN(0)), .io_isSoftReset(isSoftReset[0]), .io_interrupt(io_int_sig[0]), .io_latchPin_0(latch0), .io_latchPin_1(latch1), .io_hwSerial(`HW_SERIAL), .io_uniCode(0) ); `include "slave_dev_def.vh" `ifdef DEFINE_SLAVE_DEVICE ShinTop s_ShinTop_slv0( .clock(clock), .reset(reset | isSoftReset_reg[1]), .io_multiCLK_0(multiCLK[0]), .io_multiCLK_1(multiCLK[1]), .io_multiCLK_2(multiCLK[2]), .io_multiCLK_3(multiCLK[3]), .io_multiCLK_4(multiCLK[4]), .io_multiCLK_5(multiCLK[5]), .io_multiCLK_6(multiCLK[6]), .io_multiCLK_7(multiCLK[7]), .io_multiCLK_8(multiCLK[8]), .io_multiCLK_9(multiCLK[9]), .io_multiCLK_10(multiCLK[10]), .io_multiCLK_11(multiCLK[11]), .io_multiCLK_12(multiCLK[12]), .io_multiCLK_13(multiCLK[13]), .io_multiCLK_14(multiCLK[14]), .io_multiCLK_15(multiCLK[15]), .io_dDatIn(dDat_w[0]), .io_dDatOut(dDat_w[1]), .io_uDatIn(uDat_w[1]), .io_uDatOut(uDat_w[0]), .io_iqspi_sck(qspi_sck), .io_iqspi_mosi(qspi_mosi), .io_iqspi_miso(`IQSPI_MISO(1)), .io_iqspi_isDirIn(), .io_iqspi_csn(`IQSPI_CSN(1)), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[1]), .io_ospi_csn (`ESPI_CSN(1)), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(`EQSPI_MISO(1)), .io_oqspi_isDirIn(), .io_oqspi_csn(`EQSPI_CSN(1)), .io_isSoftReset(isSoftReset[1]), .io_interrupt(io_int_sig[1]), .io_latchPin_0(latch0), .io_latchPin_1(latch1), .io_hwSerial(`HW_SERIAL), .io_uniCode(0) ); ShinTop s_ShinTop_slv1( .clock(clock), .reset(reset | isSoftReset_reg[2]), .io_multiCLK_0(multiCLK[0]), .io_multiCLK_1(multiCLK[1]), .io_multiCLK_2(multiCLK[2]), .io_multiCLK_3(multiCLK[3]), .io_multiCLK_4(multiCLK[4]), .io_multiCLK_5(multiCLK[5]), .io_multiCLK_6(multiCLK[6]), .io_multiCLK_7(multiCLK[7]), .io_multiCLK_8(multiCLK[8]), .io_multiCLK_9(multiCLK[9]), .io_multiCLK_10(multiCLK[10]), .io_multiCLK_11(multiCLK[11]), .io_multiCLK_12(multiCLK[12]), .io_multiCLK_13(multiCLK[13]), .io_multiCLK_14(multiCLK[14]), .io_multiCLK_15(multiCLK[15]), .io_dDatIn(dDat_w[1]), .io_dDatOut(dDat_w[2]), .io_uDatIn(uDat_w[2]), .io_uDatOut(uDat_w[1]), .io_iqspi_sck(qspi_sck), .io_iqspi_mosi(qspi_mosi), .io_iqspi_miso(`IQSPI_MISO(2)), .io_iqspi_isDirIn(), .io_iqspi_csn(`IQSPI_CSN(2)), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[2]), .io_ospi_csn (`ESPI_CSN(2)), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(`EQSPI_MISO(2)), .io_oqspi_isDirIn(), .io_oqspi_csn(`EQSPI_CSN(2)), .io_isSoftReset(isSoftReset[2]), .io_interrupt(io_int_sig[2]), .io_latchPin_0(latch0), .io_latchPin_1(latch1), .io_hwSerial(`HW_SERIAL), .io_uniCode(0) ); ShinTop s_ShinTop_slv2( .clock(clock), .reset(reset | isSoftReset_reg[3]), .io_multiCLK_0(multiCLK[0]), .io_multiCLK_1(multiCLK[1]), .io_multiCLK_2(multiCLK[2]), .io_multiCLK_3(multiCLK[3]), .io_multiCLK_4(multiCLK[4]), .io_multiCLK_5(multiCLK[5]), .io_multiCLK_6(multiCLK[6]), .io_multiCLK_7(multiCLK[7]), .io_multiCLK_8(multiCLK[8]), .io_multiCLK_9(multiCLK[9]), .io_multiCLK_10(multiCLK[10]), .io_multiCLK_11(multiCLK[11]), .io_multiCLK_12(multiCLK[12]), .io_multiCLK_13(multiCLK[13]), .io_multiCLK_14(multiCLK[14]), .io_multiCLK_15(multiCLK[15]), .io_dDatIn(dDat_w[2]), .io_dDatOut(dDat_w[3]), .io_uDatIn(uDat_w[3]), .io_uDatOut(uDat_w[2]), .io_iqspi_sck(qspi_sck), .io_iqspi_mosi(qspi_mosi), .io_iqspi_miso(`IQSPI_MISO(3)), .io_iqspi_isDirIn(), .io_iqspi_csn(`IQSPI_CSN(3)), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[3]), .io_ospi_csn (`ESPI_CSN(3)), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(`EQSPI_MISO(3)), .io_oqspi_isDirIn(), .io_oqspi_csn(`EQSPI_CSN(3)), .io_isSoftReset(isSoftReset[3]), .io_interrupt(io_int_sig[3]), .io_latchPin_0(latch0), .io_latchPin_1(latch1), .io_hwSerial(`HW_SERIAL), .io_uniCode(0) ); ShinTop s_ShinTop_slv3( .clock(clock), .reset(reset | isSoftReset_reg[4]), .io_multiCLK_0(multiCLK[0]), .io_multiCLK_1(multiCLK[1]), .io_multiCLK_2(multiCLK[2]), .io_multiCLK_3(multiCLK[3]), .io_multiCLK_4(multiCLK[4]), .io_multiCLK_5(multiCLK[5]), .io_multiCLK_6(multiCLK[6]), .io_multiCLK_7(multiCLK[7]), .io_multiCLK_8(multiCLK[8]), .io_multiCLK_9(multiCLK[9]), .io_multiCLK_10(multiCLK[10]), .io_multiCLK_11(multiCLK[11]), .io_multiCLK_12(multiCLK[12]), .io_multiCLK_13(multiCLK[13]), .io_multiCLK_14(multiCLK[14]), .io_multiCLK_15(multiCLK[15]), .io_dDatIn(dDat_w[3]), .io_dDatOut(), .io_uDatIn(1'b0), .io_uDatOut(uDat_w[3]), .io_iqspi_sck(qspi_sck), .io_iqspi_mosi(qspi_mosi), .io_iqspi_miso(`IQSPI_MISO(4)), .io_iqspi_isDirIn(), .io_iqspi_csn(`IQSPI_CSN(4)), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[4]), .io_ospi_csn (`ESPI_CSN(4)), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(`EQSPI_MISO(4)), .io_oqspi_isDirIn(), .io_oqspi_csn(`EQSPI_CSN(4)), .io_isSoftReset(isSoftReset[4]), .io_interrupt(io_int_sig[4]), .io_latchPin_0(latch0), .io_latchPin_1(latch1), .io_hwSerial(`HW_SERIAL), .io_uniCode(0) ); `endif initial begin clock = 0; clock2 = 0; reset = 1; latch0 = 0; latch1 = 0; _reset_deactive = 1'b0; $timeformat(-9, 2, " ns", 8); spi_csn = {`SPI_CSN_NUM{1'b1}}; //~15'b0; #10000000 reset <= 1; #24000000 reset <= 0; #8000000000000 #8000000000000 #8000000000000 $display("Time Out !!!"); $fclose(spidata_file); //$stop; $finish; end initial begin forever begin #8000000 clock <= ~clock; end end generate for( genvar i = 0; i < 16; i = i + 1 ) begin initial begin multiCLK[i] = 0; for( integer j = 0; j < i; j = j + 1 ) begin #1000000 ; end forever begin #8000000 multiCLK[i] <= ~multiCLK[i]; end end end endgenerate //如果频率差到 80ppm,参数是: 8000640/1000080/8000640 [pass] //如果频率差到120ppm,参数是: 8000960/1000120/8000960 [pass] //如果频率差到160ppm,参数是: 8001280/1000160/8001280 [pass] //如果频率差到168ppm,参数是: 8001344/1000168/8001344 [pass] //如果频率差到176ppm,参数是: 8001408/1000176/8001408 [pass] //如果频率差到-176ppm,参数是: 7998592/ 999824/7998592 [pass] //如果频率差到180ppm,参数是: 8001440/1000180/8001440 [pass] //如果频率差到-180ppm,参数是: 7998560/ 999820/7998560 [pass] //如果频率差到181ppm,参数是: 8001448/1000181/8001448 [failed] //tc29, tc30联合测试,tc30最后几个字节不过, 单测能过 //如果频率差到-181ppm,参数是: 7998552/ 999819/7998552 [failed] //同上 //如果频率差到182ppm,参数是: 8001456/1000182/8001456 [failed] //如果频率差到-182ppm,参数是: 7998544/ 999818/7998544 [failed] //单测, tc30下行是对的,上行发生错误 //如果频率差到184ppm,参数是: 8001472/1000184/8001472 [failed] //差得字节数不多,大概在180ppm上下 //如果频率差到-184ppm,参数是: 7998528/ 999816/7998528 [failed] initial begin forever begin #7998560 clock2 <= ~clock2; end end generate for( genvar i = 0; i < 16; i = i + 1 ) begin initial begin //相位信息 #250000 multiCLK2[i] = 0; for( integer j = 0; j < i; j = j + 1 ) begin #999820 ; end forever begin #7998560 multiCLK2[i] <= ~multiCLK2[i]; end end end endgenerate initial begin spidata_file = $fopen("spi_trans_data.txt", "w"); if (!spidata_file) $display("文件打开失败"); `ifdef VCS_COMPILE $dumpfile("./generated/wave.vcd"); //生成的vcd文件名称 $dumpvars(0, ShinTopSpiTb);//tb模块名称 `endif `ifdef IVERILOG_COMPILE $dumpfile("./generated/wave.fst"); //生成的fst文件名称 $dumpvars(0, ShinTopSpiTb);//tb模块名称 `endif end always @(posedge reset) begin _reset_deactive <= 1'b0; end always @(negedge reset) begin _reset_deactive <= 1'b1; end `define SCKFRE #64000000 reg sck = 0; initial begin forever begin `SCKFRE sck <= ~sck; end end assign spi_sck = sck; assign qspi_sck = sck; reg [7:0] txBuf[0:2047]; reg [7:0] rxBuf[0:2047]; reg [7:0] exChangeRego; reg [7:0] exChangeRegi; assign spi_mosi = exChangeRego[7]; assign qspi_mosi = exChangeRego[7:4]; wire [3:0] qspi_mux_miso = `QSPI_MUX_MISO_INIT; //( qspi_miso[4*0+3:4*0] & ~{4{spi_csn[ 0]}}) | //( qspi_miso[4*1+3:4*1] & ~{4{spi_csn[ 1]}}) | //( qspi_miso[4*2+3:4*2] & ~{4{spi_csn[ 2]}}) | //( qspi_miso[4*3+3:4*3] & ~{4{spi_csn[ 3]}}) | //( qspi_miso[4*4+3:4*4] & ~{4{spi_csn[ 4]}}) | //( qspi_miso[4*5+3:4*5] & ~{4{spi_csn[10]}}) | //( qspi_miso[4*6+3:4*6] & ~{4{spi_csn[11]}}) | //( qspi_miso[4*7+3:4*7] & ~{4{spi_csn[12]}}) | //( qspi_miso[4*8+3:4*8] & ~{4{spi_csn[13]}}) | //( qspi_miso[4*9+3:4*9] & ~{4{spi_csn[14]}}); /* (`IQSPI_MISO(0) & ~{4{`IQSPI_CSN(0)}}) | (`IQSPI_MISO(1) & ~{4{`IQSPI_CSN(1)}}) | (`IQSPI_MISO(2) & ~{4{`IQSPI_CSN(2)}}) | (`IQSPI_MISO(3) & ~{4{`IQSPI_CSN(3)}}) | (`IQSPI_MISO(4) & ~{4{`IQSPI_CSN(4)}}) | (`EQSPI_MISO(0) & ~{4{`EQSPI_CSN(0)}}) | (`EQSPI_MISO(1) & ~{4{`EQSPI_CSN(1)}}) | (`EQSPI_MISO(2) & ~{4{`EQSPI_CSN(2)}}) | (`EQSPI_MISO(3) & ~{4{`EQSPI_CSN(3)}}) | (`EQSPI_MISO(4) & ~{4{`EQSPI_CSN(4)}}); */ wire spi_mux_miso = `SPI_MUX_MISO_INIT; //( spi_miso[0] & ~spi_csn[5] ) | //( spi_miso[1] & ~spi_csn[6] ) | //( spi_miso[2] & ~spi_csn[7] ) | //( spi_miso[3] & ~spi_csn[8] ) | //( spi_miso[4] & ~spi_csn[9] ); /* ( spi_miso[0] & ~`ESPI_CSN(0)) | ( spi_miso[1] & ~`ESPI_CSN(1)) | ( spi_miso[2] & ~`ESPI_CSN(2)) | ( spi_miso[3] & ~`ESPI_CSN(3)) | ( spi_miso[4] & ~`ESPI_CSN(4)); */ reg isReq = 0; reg isBusy = 0; reg [11:0] length; reg [7:0] idx; reg [11:0] transCnt; reg [11:0] byteCnt; reg [2:0] bitCnt; always @(posedge clock) begin if( isReq & sck == 0 ) begin isBusy <= #500000 1'b1; transCnt <= #500000 0; byteCnt <= #500000 ~12'b0; bitCnt <= #500000 ~3'b0; spi_csn[idx] <= #500000 1'b0; exChangeRego <= txBuf[0]; end end //DEV_NUM //ALL_DEV_NUM wire isQspi = (idx >= 0 && idx <= (`ALL_DEV_NUM - 1)) || idx >= (`ALL_DEV_NUM * 2); wire [11:0] nextByteCnt = byteCnt + 1; //输出 always @(negedge sck) begin if( isBusy ) begin if( &bitCnt ) begin exChangeRego <= txBuf[nextByteCnt]; end else begin exChangeRego <= isQspi ? exChangeRego << 4 : exChangeRego << 1; end end end //输入 always @(posedge sck) begin if( isBusy ) begin if( transCnt <= length ) begin if( isQspi ) begin bitCnt <= ~bitCnt; end else begin bitCnt <= bitCnt + 1; end if( &bitCnt ) begin byteCnt <= byteCnt +1; transCnt <= transCnt + 1; if( txBuf[2] === 1 & nextByteCnt >= 4) begin rxBuf[byteCnt] <= exChangeRegi; //$display("spi read out %x", exChangeRegi); end if( txBuf[2] === 1 & nextByteCnt >= 3) begin exChangeRegi <= isQspi ? {exChangeRegi[3:0], qspi_mux_miso} : {exChangeRegi[6:0], spi_mux_miso}; end else begin exChangeRegi <= 0; end end else begin exChangeRegi <= isQspi ? {exChangeRegi[3:0], qspi_mux_miso} : {exChangeRegi[6:0], spi_mux_miso}; end end else begin isBusy <= #500000 1'b0; spi_csn[idx] <= #500000 1'b1; end end end //mst slv0~slv3的 内部qspi调用即设置 //sidx为0~4;外部spi为5~9,外部qspi为10~15 task spi_trans( input [15:0] saddress, input [7:0] scmd, input [12:0] slength,input [7:0] sidx ); begin txBuf[0] <= saddress[15:8]; txBuf[1] <= saddress[7:0]; txBuf[2] <= scmd; length <= slength + 3; idx <= sidx; #500000 @(negedge sck) isReq <= 1; @(posedge sck) #500000 isReq <= 0; @( negedge isBusy) #100000000 begin //$fwrite(spidata_file, "------------%5t------------\n", $realtime); $fwrite(spidata_file, "T:%t \tdev:%4d, addr:0x%02h%02h, %s, len:%4d\n", $realtime, ((sidx >= `ALL_DEV_NUM)? ((sidx >= (`ALL_DEV_NUM * 2))? (sidx - (`ALL_DEV_NUM * 2)):(sidx - `ALL_DEV_NUM)):sidx), txBuf[0], txBuf[1], ((txBuf[2] == 0)? "Write":" Read"), slength); if ( ((saddress == 16'h0800) || (saddress == 16'h1000) || (saddress == 16'h1800) || (saddress == 16'h2000) || (saddress == 16'h2800) || (saddress == 16'h3000) || (saddress == 16'h3800) || (saddress == 16'h4000)) && ((sidx == 0) || (sidx == `ALL_DEV_NUM) || (sidx == (`ALL_DEV_NUM * 2)))) begin _pos = 3; for (integer _k = 0; _k < 4; _k++) begin if (scmd == 0) begin $fwrite(spidata_file, "%02h ", txBuf[_k + _pos]); end else begin $fwrite(spidata_file, "%02h ", rxBuf[_k + _pos]); end end $fwrite(spidata_file, "\n"); _pos = 4 + _pos; for (; _pos < slength; ) begin for (integer _k = 0; _k < 6; _k++) begin if (scmd == 0) begin $fwrite(spidata_file, "%02h ", txBuf[_k + _pos]); _len = txBuf[_pos + 5] + (txBuf[_pos + 4] & 8'h0f) * 256; end else begin $fwrite(spidata_file, "%02h ", rxBuf[_k + _pos]); _len = rxBuf[_pos + 5] + (rxBuf[_pos + 4] & 8'h0f) * 256; end end begin:PRINT_PKT_COMMENT integer dev; integer addr_type; integer addr; integer cmd; integer len; if (scmd == 0) begin addr_type = txBuf[_pos + 1] & 8'h3; dev = (txBuf[_pos] >> 2) * 256 + ((txBuf[_pos + 1] >> 2) & 8'hff); addr = txBuf[_pos + 2] * 256 + (txBuf[_pos + 3] & 8'hff); cmd = (txBuf[_pos + 4] >> 4) & 8'h0f; len = (txBuf[_pos + 4] & 8'h0f) * 256 + (txBuf[_pos + 5] & 8'hff); end else begin addr_type = rxBuf[_pos + 1] & 8'h3; dev = (rxBuf[_pos] >> 2) * 256 + ((rxBuf[_pos + 1] >> 2) & 8'hff); addr = rxBuf[_pos + 2] * 256 + (rxBuf[_pos + 3] & 8'hff); cmd = (rxBuf[_pos + 4] >> 4) & 8'h0f; len = (rxBuf[_pos + 4] & 8'h0f) * 256 + (rxBuf[_pos + 5] & 8'hff); end if (addr_type == 0) $fwrite(spidata_file, "// type:%3d dev:%3d addr:0x%04x cmd:0x%1x len:%3d", addr_type, dev, addr[15:0], cmd[3:0], len); else begin addr = dev * 65536 + addr; $fwrite(spidata_file, "// type:%3d addr:0x%08x cmd:0x%1x len:%3d", addr_type, addr, cmd[3:0], len); end end $fwrite(spidata_file, "\n{{ "); _pos = _pos + 6; for (integer _k = 0; _k < _len; _k++) begin if (scmd == 0) begin $fwrite(spidata_file, "%02h ", txBuf[_k + _pos]); end else begin $fwrite(spidata_file, "%02h ", rxBuf[_k + _pos]); end c_line = 0; if ((_k + 2)%16 == 0) begin $fwrite(spidata_file, "\n"); c_line = 1; end end $fwrite(spidata_file, "}}\n"); _pos = _pos + _len; for (integer _k = 0; _k < 2; _k++) begin if (scmd == 0) begin $fwrite(spidata_file, "%02h ", txBuf[_k + _pos]); end else begin $fwrite(spidata_file, "%02h ", rxBuf[_k + _pos]); end end _pos = _pos + 2; $fwrite(spidata_file, "\n"); end end else begin for (integer i=0; i= 500000000000.0) begin $display("comm timeout."); is_run = 0; end end end endtask initial begin #50000000 `ifdef ENABLE_REG_RW1_TEST /*--------------------------------------------------------------------------------------------------------- 测试用例 1. 从IP中读取寄存器,上电后的寄存器期望值为0 ---------------------------------------------------------------------------------------------------------*/ begin:READ_REG_TESTCASE `BEGIN_TESTCASE(`ENABLE_REG_RW1_TEST); _t_start = $realtime; $fdisplay(spidata_file, "测试用例:从IP中读取寄存器,上电后的寄存器期望值为0"); `SPI_TRANS( (16'h00), (`SPI_READ), (64), (`IF_OSPI(0)) ); `SPI_TRANS( (16'h00), (`SPI_READ), (64), (`IF_OSPI(1)) ); `SPI_TRANS( (16'h00), (`SPI_READ), (64), (`IF_OSPI(2)) ); `SPI_TRANS( (16'h00), (`SPI_READ), (64), (`IF_OSPI(3)) ); `SPI_TRANS( (16'h00), (`SPI_READ), (64), (`IF_OSPI(4)) ); _t_end = $realtime; $fdisplay(spidata_file, "该测试用例运行时间:%t\n", _t_end - _t_start); `END_TESTCASE(`ENABLE_REG_RW1_TEST); end `endif begin:SETTING_INTERFACE if ((`INTERFACE_IDX) == `ALL_DEV_NUM) begin $fdisplay(spidata_file, "\n\n从内部QSPI配置使用外部的SPI接口访问EasyBus"); txBuf[0+3] = 8'h01; spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(0)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(1)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(2)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(3)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(4)) ); end else if ((`INTERFACE_IDX) == (`ALL_DEV_NUM * 2)) begin $fdisplay(spidata_file, "\n\n从内部QSPI配置使用外部的QSPI接口访问EasyBus"); txBuf[0+3] = 8'h02; spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(0)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(1)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(2)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(3)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(4)) ); end else begin $fdisplay(spidata_file, "\n\n从内部QSPI接口访问EasyBus"); txBuf[0+3] = 8'h00; spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(0)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(1)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(2)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(3)) ); spi_trans( (16'h09), (`SPI_WRITE), (1), (`IF_OSPI(4)) ); end end `ifdef ENABLE_INT_INIT_TEST begin:CHECK_INTERRUPT_SIG $fdisplay(spidata_file, "\n\n测试用例:检查设备的INTERRUPT信号"); @(posedge clock) begin if (io_int_sig[0]) $fdisplay(spidata_file, "**MST Interrupt."); if (io_int_sig[1]) $fdisplay(spidata_file, "**SLV0 Interrupt."); if (io_int_sig[2]) $fdisplay(spidata_file, "**SLV1 Interrupt."); if (io_int_sig[3]) $fdisplay(spidata_file, "**SLV2 Interrupt."); if (io_int_sig[4]) $fdisplay(spidata_file, "**SLV3 Interrupt."); end $fdisplay(spidata_file, "-检查中断"); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(0)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(1)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(2)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(3)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(4)) ); $fdisplay(spidata_file, "-清中断"); txBuf[0+3] = 8'h00; txBuf[1+3] = 8'h00; txBuf[2+3] = 8'h00; txBuf[3+3] = 8'h80; spi_trans( (16'h78), (`SPI_WRITE), (4), (`IF_IDX(0)) ); spi_trans( (16'h78), (`SPI_WRITE), (4), (`IF_IDX(1)) ); spi_trans( (16'h78), (`SPI_WRITE), (4), (`IF_IDX(2)) ); spi_trans( (16'h78), (`SPI_WRITE), (4), (`IF_IDX(3)) ); spi_trans( (16'h78), (`SPI_WRITE), (4), (`IF_IDX(4)) ); $fdisplay(spidata_file, "-检查中断"); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(0)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(1)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(2)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(3)) ); spi_trans( (16'h70), (`SPI_READ), (14), (`IF_IDX(4)) ); end begin:CHECK_INTERRUPT_CFG_REG $fdisplay(spidata_file, "\n\n测试用例:检查设备的INTERRUPT信号设置寄存器"); $fdisplay(spidata_file, "-检查中断"); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(0)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(1)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(2)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(3)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(4)) ); $fdisplay(spidata_file, "-设置中断"); txBuf[0+3] = 8'h00; txBuf[1+3] = 8'h00; txBuf[2+3] = 8'h00; txBuf[3+3] = 8'h00; spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(0)) ); spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(1)) ); spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(2)) ); spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(3)) ); spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(4)) ); $fdisplay(spidata_file, "-检查中断"); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(0)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(1)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(2)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(3)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(4)) ); $fdisplay(spidata_file, "-设置中断"); txBuf[0+3] = 8'h0F; txBuf[1+3] = 8'h00; txBuf[2+3] = 8'h00; txBuf[3+3] = 8'h00; spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(0)) ); txBuf[0+3] = 8'h00; txBuf[1+3] = 8'hFF; txBuf[2+3] = 8'h00; txBuf[3+3] = 8'h00; spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(1)) ); spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(2)) ); spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(3)) ); spi_trans( (16'h70), (`SPI_WRITE), (4), (`IF_IDX(4)) ); $fdisplay(spidata_file, "-检查中断"); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(0)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(1)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(2)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(3)) ); spi_trans( (16'h70), (`SPI_READ), (4), (`IF_IDX(4)) ); $fdisplay(spidata_file, "-中断改为脉冲模式"); txBuf[3] = 8'h10; txBuf[4] = 8'h8A; spi_trans( (16'h7c), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (16'h7c), (`SPI_WRITE), (2), (`IF_IDX(1)) ); spi_trans( (16'h7c), (`SPI_WRITE), (2), (`IF_IDX(2)) ); spi_trans( (16'h7c), (`SPI_WRITE), (2), (`IF_IDX(3)) ); spi_trans( (16'h7c), (`SPI_WRITE), (2), (`IF_IDX(4)) ); end `endif `include "tc_runlist.vh" #100000000000 $display("Testcase Finished! Time Out !!!"); $fclose(spidata_file); //$stop; $finish; end endmodule