`timescale 1 ns / 1 ps //`define ENABLE_REG_RW_TEST `define ENABLE_DET_TEST `define ENABLE_SET_ADDR_TEST //`define ENABLE_SM1_SEND_TEST `define ENABLE_EXCHG_DATA_SEQ_TEST //`define ENABLE_EXCHG_DATA_SEQ0_TEST //`define ENABLE_EXCHG_DATA_SEQ1_TEST //`define ENABLE_EXCHG_DATA_SEQ2_TEST `define ENABLE_EXCHG_DATA_BC_TEST //`define ENABLE_SYNC_TEST module ShinTopSpiTb( ); reg clock; reg reset; reg clk8x; wire [3:0] dDat_w; wire [3:0] uDat_w; wire spi_sck; wire spi_mosi; wire [4:0] spi_miso; reg [14:0] spi_csn; wire qspi_sck; wire [3:0] qspi_mosi; wire [40-1:0] qspi_miso; wire isResp; integer spidata_file; integer c_line; integer _pos; integer _len; wire [4:0] isSoftReset; ShinTop s_ShinTop_Mst( .clock(clock), .reset(reset | isSoftReset[0]), .io_clk8x(clk8x), .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(qspi_miso[3:0]), .io_iqspi_isDirIn(), .io_iqspi_csn(spi_csn[0]), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[0]), .io_ospi_csn (spi_csn[5]), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(qspi_miso[4*5+3:4*5]), .io_oqspi_isDirIn(), .io_oqspi_csn(spi_csn[10]), .io_rsp_valid(isResp), .io_rsp_bits_isError(), .io_isSoftReset(isSoftReset[0]), .io_interrupt() ); ShinTop s_ShinTop_slv0( .clock(clock), .reset(reset | isSoftReset[1]), .io_clk8x(clk8x), .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(qspi_miso[4*1+3:4*1]), .io_iqspi_isDirIn(), .io_iqspi_csn(spi_csn[1]), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[1]), .io_ospi_csn (spi_csn[6]), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(qspi_miso[4*6+3:4*6]), .io_oqspi_isDirIn(), .io_oqspi_csn(spi_csn[11]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_isSoftReset(isSoftReset[1]), .io_interrupt() ); ShinTop s_ShinTop_slv1( .clock(clock), .reset(reset | isSoftReset[2]), .io_clk8x(clk8x), .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(qspi_miso[4*2+3:4*2]), .io_iqspi_isDirIn(), .io_iqspi_csn(spi_csn[2]), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[2]), .io_ospi_csn (spi_csn[7]), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(qspi_miso[4*7+3:4*7]), .io_oqspi_isDirIn(), .io_oqspi_csn(spi_csn[12]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_isSoftReset(isSoftReset[2]), .io_interrupt() ); ShinTop s_ShinTop_slv2( .clock(clock), .reset(reset | isSoftReset[3]), .io_clk8x(clk8x), .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(qspi_miso[4*3+3:4*3]), .io_iqspi_isDirIn(), .io_iqspi_csn(spi_csn[3]), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[3]), .io_ospi_csn (spi_csn[8]), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(qspi_miso[4*8+3:4*8]), .io_oqspi_isDirIn(), .io_oqspi_csn(spi_csn[13]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_isSoftReset(isSoftReset[3]), .io_interrupt() ); ShinTop s_ShinTop_slv3( .clock(clock), .reset(reset | isSoftReset[4]), .io_clk8x(clk8x), .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(qspi_miso[4*4+3:4*4]), .io_iqspi_isDirIn(), .io_iqspi_csn(spi_csn[4]), .io_ospi_sck (spi_sck), .io_ospi_mosi(spi_mosi), .io_ospi_miso(spi_miso[4]), .io_ospi_csn (spi_csn[9]), .io_oqspi_sck(qspi_sck), .io_oqspi_mosi(qspi_mosi), .io_oqspi_miso(qspi_miso[4*9+3:4*9]), .io_oqspi_isDirIn(), .io_oqspi_csn(spi_csn[14]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_isSoftReset(isSoftReset[4]), .io_interrupt() ); initial begin clock = 0; clk8x = 0; reset = 0; spi_csn = ~15'b0; #100 reset <= 1; #240 reset <= 0; `ifdef ENABLE_REG_RW_TEST `endif `ifdef ENABLE_DET_TEST `endif `ifdef ENABLE_SET_ADDR_TEST `endif `ifdef ENABLE_SM1_SEND_TEST `endif `ifdef ENABLE_EXCHG_DATA_SEQ_TEST `ifdef ENABLE_EXCHG_DATA_SEQ0_TEST `endif `ifdef ENABLE_EXCHG_DATA_SEQ1_TEST `endif `ifdef ENABLE_EXCHG_DATA_SEQ2_TEST `endif `ifdef ENABLE_EXCHG_DATA_BC_TEST `endif `endif `ifdef ENABLE_SYNC_TEST `endif //#20000000 #5000000 $display("Time Out !!!"); $fclose(spidata_file); $stop; end initial begin forever begin #20 clk8x <= ~clk8x; end end initial begin forever begin #80 clock <= ~clock; end end initial begin spidata_file = $fopen("spi_trans_data.txt", "w"); if (!spidata_file) $display("文件打开失败"); $dumpfile("./tb/build/wave.vcd"); //生成的vcd文件名称 $dumpvars(0, ShinTopSpiTb);//tb模块名称 end `define SCKFRE #640 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_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]}}); wire spi_mux_miso = ( 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] ); 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 <= #5 1'b1; transCnt <= #5 0; byteCnt <= #5 ~12'b0; bitCnt <= #5 ~3'b0; spi_csn[idx] <= #5 1'b0; exChangeRego <= txBuf[0]; end end wire isQspi = (idx >= 0 && idx <= 4) || idx >= 10; 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 <= #5 1'b0; spi_csn[idx] <= #5 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[7:0]; txBuf[1] <= saddress[15:8]; txBuf[2] <= scmd; length <= slength + 3; idx <= sidx; #5 @(negedge sck) isReq <= 1; @(posedge sck) #5 isReq <= 0; @( negedge isBusy) #1000 begin //$fwrite(spidata_file, "------------%5t------------\n", $time); $fwrite(spidata_file, "T:%2tns \tdev:%4d, addr:0x%02h%02h, %s, len:%4d\n", $time/1000, ((sidx >= 5)? ((sidx >= 10)? (sidx - 10):(sidx - 5)):sidx), txBuf[1], txBuf[0], ((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 == 5) || (sidx == 10))) 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 < 8; _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 $fwrite(spidata_file, "\n{{ "); _pos = _pos + 8; 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; end end else begin for (integer i=0; i>>设置完毕,检查接口寄存器"); spi_trans( (16'h00), (`SPI_READ), (1), (`IF_IDX(0)) ); spi_trans( (16'h00), (`SPI_READ), (1), (`IF_IDX(1)) ); spi_trans( (16'h00), (`SPI_READ), (1), (`IF_IDX(2)) ); spi_trans( (16'h00), (`SPI_READ), (1), (`IF_IDX(3)) ); spi_trans( (16'h00), (`SPI_READ), (1), (`IF_IDX(4)) ); `ifdef ENABLE_DET_TEST /*--------------------------------------------------------------------------------------------------------- 测试用例3 ---------------------------------------------------------------------------------------------------------*/ //嗅探 #10000 $fdisplay(spidata_file, "\n\n测试用例:发送嗅探包,需要在波形文件里检查"); begin $fdisplay(spidata_file, "--->>>嗅探前,检查链路状态寄存器"); //spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(0)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(1)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(2)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(3)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(4)) ); $fdisplay(spidata_file, "--->>>嗅探"); `include "detect_pkt.vh" //设置SM1在写入0x4 len 触发enq //设置SM0在读出0x4 len 触发deq `DEF_detect_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); //无子报文 $fdisplay(spidata_file, "<<发包:"); `DEF_detect_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_detect_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; //8'h01; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_detect_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end `endif // 顺序索引 //#50000 #50000 #50000 $fdisplay(spidata_file, "--->>>嗅探后,检查链路状态寄存器"); //spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(0)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(1)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(2)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(3)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(4)) ); `ifdef ENABLE_SET_ADDR_TEST /*--------------------------------------------------------------------------------------------------------- 测试用例 ---------------------------------------------------------------------------------------------------------*/ $fdisplay(spidata_file, "\n\n测试用例:设置顺序索引"); $display("index @ %d", s_ShinTop_Mst.interface__io_cReg_timeStamp); begin $fdisplay(spidata_file, "--->>>设置顺序地址前,检查顺序地址"); //spi_trans( (16'h0010), (`SPI_READ), (5), (`IF_IDX(0)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(1)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(2)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(3)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(4)) ); $fdisplay(spidata_file, "--->>>设置顺序地址"); `include "set_addr_pkt.vh" //长度 `DEF_set_addr_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); //子报文 $fdisplay(spidata_file, "<<发包:"); `DEF_set_addr_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_set_addr_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_set_addr_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end //测试 spi_trans( (16'hc0), (`SPI_READ), (6), (`IF_IDX(3)) ); spi_trans( (16'h0a), (`SPI_READ), (2), (`IF_IDX(1)) ); spi_trans( (16'h0a), (`SPI_READ), (2), (`IF_IDX(2)) ); spi_trans( (16'h0a), (`SPI_READ), (2), (`IF_IDX(3)) ); spi_trans( (16'h0a), (`SPI_READ), (2), (`IF_IDX(4)) ); //读写 #1000 $fdisplay(spidata_file, "--->>>设置顺序地址后,检查顺序地址"); //spi_trans( (16'h0010), (`SPI_READ), (5), (`IF_IDX(0)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(1)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(2)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(3)) ); spi_trans( (16'h0000), (`SPI_READ), (16), (`IF_IDX(4)) ); `endif `ifdef ENABLE_DET_TEST /*--------------------------------------------------------------------------------------------------------- 测试用例 ---------------------------------------------------------------------------------------------------------*/ //嗅探 #1000 $fdisplay(spidata_file, "\n\n测试用例:发送嗅探包,需要在波形文件里检查"); begin $fdisplay(spidata_file, "嗅探:使用SM0"); $fdisplay(spidata_file, "--->>>嗅探前,检查链路状态寄存器"); //spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(0)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(1)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(2)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(3)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(4)) ); $fdisplay(spidata_file, "--->>>嗅探"); //设置SM1在写入0x3地址触发enq `DEF_detect_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); //无子报文 $fdisplay(spidata_file, "<<发包:"); `DEF_detect_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_detect_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_detect_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end $fdisplay(spidata_file, "--->>>嗅探后,检查链路状态寄存器"); //spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(0)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(1)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(2)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(3)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(4)) ); `endif `ifdef ENABLE_SM1_SEND_TEST begin $fdisplay(spidata_file, "嗅探:使用SM1"); $fdisplay(spidata_file, "--->>>嗅探前,检查链路状态寄存器"); //spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(0)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(1)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(2)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(3)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(4)) ); $fdisplay(spidata_file, "--->>>嗅探"); //设置SM1在写入0x3地址触发enq `DEF_detect_pkt_sm(txBuf); spi_trans( (`MST_TX1_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX1_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); //无子报文MST_TX1_LEN_ADDR $fdisplay(spidata_file, "<<发包:"); `DEF_detect_pkt(txBuf); spi_trans( (`MST_TX1_ADDR), (`SPI_WRITE), (`DEF_detect_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRIGGER(1); spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM1 接收SM1, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX1_ADDR), (`SPI_READ), (`DEF_detect_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end // 顺序索引 $fdisplay(spidata_file, "--->>>嗅探后,检查链路状态寄存器"); //spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(0)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(1)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(2)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(3)) ); spi_trans( (16'h00c0), (`SPI_READ), (6), (`IF_IDX(4)) ); `endif `ifdef ENABLE_EXCHG_DATA_SEQ_TEST /*--------------------------------------------------------------------------------------------------------- 测试用例 1. 交换数据sm0~sm7 2. 交换数据sm0~sm7 3. 交换数据sm0~sm7(中断、状态) 4. 交换数据sm0~sm7(R/W/RW, BR/BW/BRW) 4. 寄存器单读/写/读写,寄存器广播读/写/读写 5. 以上交换数据的错误形式 ---------------------------------------------------------------------------------------------------------*/ $fdisplay(spidata_file, "\n\n测试用例:交换数据"); `ifdef ENABLE_EXCHG_DATA_SEQ0_TEST #1000 $display("read&write @ %d", s_ShinTop_Mst.interface__io_cReg_timeStamp); begin $fdisplay(spidata_file, "--->>>交换数据sm0~sm7"); `include "seq_0_pkt.vh" //设置SM1在写入516 len触发enq `DEF_seq_0_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); $fdisplay(spidata_file, "<<发包:"); `DEF_seq_0_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_seq_0_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_seq_0_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end `endif `ifdef ENABLE_EXCHG_DATA_SEQ1_TEST #1000 $display("read&write @ %d", s_ShinTop_Mst.interface__io_cReg_timeStamp); begin $fdisplay(spidata_file, "\n--->>>交换数据写dev2_sm0/dev1_sm2/dev3_sm4/dev4_sm6"); `include "seq_1_pkt.vh" `DEF_seq_1_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); $fdisplay(spidata_file, "<<发包:"); `DEF_seq_1_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_seq_1_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_seq_1_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end spi_trans( (16'h1800), (`SPI_READ), (64), (`IF_IDX(1)) ); spi_trans( (16'h0800), (`SPI_READ), (64), (`IF_IDX(2)) ); spi_trans( (16'h2800), (`SPI_READ), (64), (`IF_IDX(3)) ); spi_trans( (16'h3800), (`SPI_READ), (64), (`IF_IDX(4)) ); `endif `ifdef ENABLE_EXCHG_DATA_SEQ2_TEST #1000 $display("read&write @ %d", s_ShinTop_Mst.interface__io_cReg_timeStamp); begin $fdisplay(spidata_file, "\n--->>>交换数据读dev1_sm1/dev2_sm3/dev3_sm5/dev4_sm7"); txBuf[3] = 8'h80; txBuf[4] = 8'h00; spi_trans((16'h0306), (`SPI_WRITE), (2), (`IF_IDX(1)) );//dev1_sm1 txBuf[3] = 8'h98; txBuf[4] = 8'h00; spi_trans((16'h030e), (`SPI_WRITE), (2), (`IF_IDX(2)) );//dev2_sm3 txBuf[3] = 8'h81; txBuf[4] = 8'h00; spi_trans((16'h0316), (`SPI_WRITE), (2), (`IF_IDX(3)) );//dev2_sm3 txBuf[3] = 8'h8c; txBuf[4] = 8'h00; spi_trans((16'h031e), (`SPI_WRITE), (2), (`IF_IDX(4)) );//dev2_sm3 for (integer i=0; i < 128; i++) begin txBuf[i + 3] = i + 1; end spi_trans( (16'h1000), (`SPI_WRITE), (128), (`IF_IDX(1)) ); for (integer i=0; i < 152; i++) begin txBuf[i + 3] = i + 2; end spi_trans( (16'h2000), (`SPI_WRITE), (152), (`IF_IDX(2)) ); for (integer i=0; i < 129; i++) begin txBuf[i + 3] = i + 3; end spi_trans( (16'h3000), (`SPI_WRITE), (129), (`IF_IDX(3)) ); for (integer i=0; i < 140; i++) begin txBuf[i + 3] = i + 4; end spi_trans( (16'h4000), (`SPI_WRITE), (140), (`IF_IDX(4)) ); `include "seq_2_pkt.vh" $fdisplay(spidata_file, "<<发包:"); `DEF_seq_2_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); `DEF_seq_2_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_seq_2_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_seq_2_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end `endif `endif `ifdef ENABLE_EXCHG_DATA_BC_TEST #1000 $fdisplay(spidata_file, "\n\n测试用例:广播交换数据"); $display("read&write @ %d", s_ShinTop_Mst.interface__io_cReg_timeStamp); begin $fdisplay(spidata_file, "\n--->>>广播读"); `include "bc_r_pkt.vh" `DEF_bc_r_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); $fdisplay(spidata_file, "<<发包:"); `DEF_bc_r_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_bc_r_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_bc_r_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end #1000 $display("read&write @ %d", s_ShinTop_Mst.interface__io_cReg_timeStamp); begin $fdisplay(spidata_file, "\n--->>>广播写"); `include "bc_w_pkt.vh" `DEF_bc_w_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); $fdisplay(spidata_file, "<<发包:"); `DEF_bc_w_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_bc_w_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_bc_w_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end spi_trans( (16'h0800), (`SPI_READ), (32), (`IF_IDX(1)) ); spi_trans( (16'h0800), (`SPI_READ), (32), (`IF_IDX(2)) ); spi_trans( (16'h0800), (`SPI_READ), (32), (`IF_IDX(3)) ); spi_trans( (16'h0800), (`SPI_READ), (32), (`IF_IDX(4)) ); `endif `ifdef ENABLE_SYNC_TEST /*--------------------------------------------------------------------------------------------------------- 测试用例 1. 测试 同步(sync) 和 同步输出 (sync_out) ---------------------------------------------------------------------------------------------------------*/ // 同步 #1000 $display("sync @ %d", s_ShinTop_Mst.interface__io_cReg_timeStamp); $fdisplay(spidata_file, "\n\n测试用例:测试同步(sync)和同步输出(sync_out)"); begin //设置SM1在写入 0x18 len触发enq `include "sync_pkt.vh" `DEF_sync_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); $fdisplay(spidata_file, "<<发包:"); `DEF_sync_pkt(txBuf); spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_sync_pkt_len), (`IF_IDX(0)) ); //写入SM1 //写入替换时间戳替换地址 txBuf[0+3] = 8'h0c; txBuf[1+3] = 8'hc0; spi_trans( (16'h24), (`SPI_WRITE), (2), (`IF_IDX(0)) ); //写入替换时间戳替换地址寄存器 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_sync_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end //清除替换时间戳替换地址 txBuf[0+3] = 8'h00; txBuf[1+3] = 8'h00; spi_trans( (16'h25), (`SPI_WRITE), (2), (`IF_IDX(0)) ); //清除替换时间戳替换地址寄存器 `include "sync_sig_pkt.vh" `DEF_sync_sig_pkt_sm(txBuf); spi_trans( (`MST_TX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); spi_trans( (`MST_RX_LEN_ADDR), (`SPI_WRITE), (2), (`IF_IDX(0)) ); $fdisplay(spidata_file, "<<发包:"); `DEF_sync_sig_pkt(txBuf); //spi_trans( (16'h1000), (`SPI_WRITE), (8'h94), (`IF_IDX(0)) ); //写入SM1 spi_trans( (`MST_TX_ADDR), (`SPI_WRITE), (`DEF_sync_sig_pkt_len), (`IF_IDX(0)) ); //写入SM1 //发布请求 txBuf[0+3] = `MST_TX_TRG; spi_trans( (16'h20), (`SPI_WRITE), (1), (`IF_IDX(0)) );//发送SM0 接收SM0, 请求发送 @(posedge isResp) #5 begin end $fdisplay(spidata_file, ">>回包:"); spi_trans( (`MST_RX_ADDR), (`SPI_READ), (`DEF_sync_sig_pkt_len), (`IF_IDX(0)) );//读一下SM0的切换地址,将fifo弹出 end //spi_trans( (16'h0100), (`SPI_READ), (32), (`IF_IDX(0)) ); spi_trans( (16'h0100), (`SPI_READ), (32), (`IF_IDX(1)) ); spi_trans( (16'h0130), (`SPI_READ), (32), (`IF_IDX(1)) ); spi_trans( (16'h0100), (`SPI_READ), (32), (`IF_IDX(2)) ); spi_trans( (16'h0130), (`SPI_READ), (32), (`IF_IDX(2)) ); spi_trans( (16'h0100), (`SPI_READ), (32), (`IF_IDX(3)) ); spi_trans( (16'h0130), (`SPI_READ), (32), (`IF_IDX(3)) ); spi_trans( (16'h0100), (`SPI_READ), (32), (`IF_IDX(4)) ); spi_trans( (16'h0130), (`SPI_READ), (32), (`IF_IDX(4)) ); #10000 //清脉冲 txBuf[0+3] = 0; //负载0x122 sync0脉冲宽度 txBuf[1+3] = 0; //负载0x123 txBuf[2+3] = 0; //负载0x124 sync1脉冲宽度 txBuf[3+3] = 0; //负载0x125 txBuf[4+3] = 0; //负载0x126 sync2脉冲宽度 txBuf[5+3] = 0; //负载0x127 txBuf[6+3] = 0; //负载0x128 sync3脉冲宽度 txBuf[7+3] = 0; //负载0x129 spi_trans( (16'h0122), (`SPI_WRITE), (8), (`IF_IDX(1)) ); //slv2 spi_trans( (16'h0122), (`SPI_WRITE), (8), (`IF_IDX(2)) ); //slv2 spi_trans( (16'h0122), (`SPI_WRITE), (8), (`IF_IDX(3)) ); //slv2 spi_trans( (16'h0122), (`SPI_WRITE), (8), (`IF_IDX(4)) ); //slv2 #50000 //复位系统 txBuf[0+3] = 8'h01; spi_trans( (16'h40), (`SPI_WRITE), (1), (`IF_IDX(0)) );//复位主站 spi_trans( (16'h40), (`SPI_WRITE), (1), (`IF_IDX(1)) );//复位从站2 `endif end endmodule