`timescale 1 ns / 1 ps module ShinTopSpiTb( ); reg clock; reg reset; reg clk8x; wire [3:0] dDat_w; wire [3:0] uDat_w; reg [4:0] spi_sck; reg [4:0] spi_mosi; wire [4:0] spi_miso; reg [4:0] spi_csn; ShinTop s_ShinTop_Mst( .clock(clock), .reset(reset), .io_clk8x(clk8x), .io_dDatIn(1'b0), .io_dDatOut(dDat_w[0]), .io_uDatIn(uDat_w[0]), .io_uDatOut(), .io_ospi_sck (spi_sck[0]), .io_ospi_mosi(spi_mosi[0]), .io_ospi_miso(spi_miso[0]), .io_ospi_csn (spi_csn[0]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_rsp_bits_length() ); ShinTop s_ShinTop_slv0( .clock(clock), .reset(reset), .io_clk8x(clk8x), .io_dDatIn(dDat_w[0]), .io_dDatOut(dDat_w[1]), .io_uDatIn(uDat_w[1]), .io_uDatOut(uDat_w[0]), .io_ospi_sck (spi_sck[1]), .io_ospi_mosi(spi_mosi[1]), .io_ospi_miso(spi_miso[1]), .io_ospi_csn (spi_csn[1]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_rsp_bits_length() ); ShinTop s_ShinTop_slv1( .clock(clock), .reset(reset), .io_clk8x(clk8x), .io_dDatIn(dDat_w[1]), .io_dDatOut(dDat_w[2]), .io_uDatIn(uDat_w[2]), .io_uDatOut(uDat_w[1]), .io_ospi_sck (spi_sck[2]), .io_ospi_mosi(spi_mosi[2]), .io_ospi_miso(spi_miso[2]), .io_ospi_csn (spi_csn[2]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_rsp_bits_length() ); ShinTop s_ShinTop_slv2( .clock(clock), .reset(reset), .io_clk8x(clk8x), .io_dDatIn(dDat_w[2]), .io_dDatOut(dDat_w[3]), .io_uDatIn(uDat_w[3]), .io_uDatOut(uDat_w[2]), .io_ospi_sck (spi_sck[3]), .io_ospi_mosi(spi_mosi[3]), .io_ospi_miso(spi_miso[3]), .io_ospi_csn (spi_csn[3]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_rsp_bits_length() ); ShinTop s_ShinTop_slv3( .clock(clock), .reset(reset), .io_clk8x(clk8x), .io_dDatIn(dDat_w[3]), .io_dDatOut(), .io_uDatIn(1'b0), .io_uDatOut(uDat_w[3]), .io_ospi_sck (spi_sck[4]), .io_ospi_mosi(spi_mosi[4]), .io_ospi_miso(spi_miso[4]), .io_ospi_csn (spi_csn[4]), .io_rsp_valid(), .io_rsp_bits_isError(), .io_rsp_bits_length() ); initial begin clock = 0; clk8x = 0; reset = 0; spi_sck = 5'b0; spi_mosi = 5'b0; spi_csn = 5'b11111; #100 reset <= 1; #240 reset <= 0; #3000000 $display("Time Out !!!"); $stop; end initial begin forever begin #10 clk8x <= ~clk8x; end end initial begin forever begin #80 clock <= ~clock; end end initial begin $dumpfile("./tb/build/wave.vcd"); //生成的vcd文件名称 $dumpvars(0, ShinTopSpiTb);//tb模块名称 end initial begin for( integer i = 0; i < 5; i = i + 1 ) begin forever begin #1000 spi_sck[i] <= spi_csn[i] == 1'b0 ? ~spi_sck[i] : 1'b0; end end end reg [7:0] txBuf[0:2047]; reg [7:0] rxBuf[0:2047]; task spi_trans( input [15:0] address, input [7:0] cmd, input [10:0] length, input [7:0] idx ); reg [10:0] transCnt; reg [7:0] exChangeReg; begin #10 spi_csn[idx] <= 1'b0; transCnt <= 0; exChangeReg <= address[7:0]; repeat(8) begin @(posedge spi_sck[idx]) #5 exChangeReg <= {exChangeReg[6:0], spi_miso[idx]}; spi_mosi[idx] <= exChangeReg[7]; end exChangeReg <= address[15:8]; repeat(8) begin @(posedge spi_sck[idx]) #5 exChangeReg <= {exChangeReg[6:0], spi_miso[idx]}; spi_mosi[idx] <= exChangeReg[7]; end exChangeReg <= cmd; repeat(8) begin @(posedge spi_sck[idx]) #5 exChangeReg <= {exChangeReg[6:0], spi_miso[idx]}; spi_mosi[idx] <= exChangeReg[7]; end while( transCnt < length ) begin exChangeReg <= txBuf[transCnt]; transCnt <= transCnt + 1; repeat(8) begin @(posedge spi_sck[idx]) #5 exChangeReg <= {exChangeReg[6:0], spi_miso[idx]}; spi_mosi[idx] <= exChangeReg[7]; end rxBuf[transCnt] <= exChangeReg; end @(negedge spi_sck[idx]) #5 spi_csn[idx] <= 1'b1; end endtask `define SPI_WRITE 8'h0 `define SPI_READ 8'h1 initial begin #1000 //设置主站从站 txBuf[0] = 8'h01; spi_trans( (16'h0), (`SPI_WRITE), (1), (0) ); #1000 txBuf[0] = 8'h02; spi_trans( (16'h0), (`SPI_WRITE), (1), (1) ); #1000 spi_trans( (16'h0), (`SPI_WRITE), (1), (2) ); #1000 spi_trans( (16'h0), (`SPI_WRITE), (1), (3) ); #1000 spi_trans( (16'h0), (`SPI_WRITE), (1), (4) ); //嗅探 #10000 begin //设置SM1在写入0x3地址触发enq txBuf[0] = 8'h03; txBuf[1] = 8'h00; spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) ); //无子报文 txBuf[0] = 8'h00; txBuf[1] = 8'h01;//heeader length 0 嗅探包1 txBuf[2] = 8'h00; txBuf[3] = 8'h00; spi_trans( (16'h1000), (`SPI_WRITE), (4), (0) ); //写入SM1 //发布请求 txBuf[0] = 8'h04; txBuf[1] = 8'h00; spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度 txBuf[0] = 8'h01; spi_trans( (16'h20), (`SPI_WRITE), (1), (0) );//发送SM0 接收SM0, 请求发送 end // 顺序索引 #50000 #50000 #50000 begin //设置SM1在写入0xd地址触发enq txBuf[0] = 8'h0d; txBuf[1] = 8'h00; spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) ); txBuf[0] = 8'h00; txBuf[1] = 8'ha0;//heeader length 10 txBuf[2] = 8'h00; txBuf[3] = 8'h00; //子报文 //设置顺序地址 txBuf[4] = 8'h0; //设备索引 txBuf[5] = 8'h0; //设备索引、类型 txBuf[6] = $random; //地址 txBuf[7] = $random; //地址 txBuf[8] = 8'hd0; //命令d 负载长度2 txBuf[9] = 8'd02; //负载长度2 txBuf[10] = 8'h0; //工作计数0 txBuf[11] = 8'h0; //工作计数0 txBuf[12] = 8'h0; //负载 txBuf[13] = 8'h0; //负载 spi_trans( (16'h1000), (`SPI_WRITE), (14), (0) ); //写入SM1 //发布请求 txBuf[0] = 8'h0e; txBuf[1] = 8'h00; spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度 txBuf[0] = 8'h01; spi_trans( (16'h20), (`SPI_WRITE), (1), (0) );//发送SM0 接收SM0, 请求发送 end //读写 #50000 #50000 #50000 #50000 begin //设置SM1在写入516地址触发enq txBuf[0] = 8'h03; txBuf[1] = 8'h02; spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) ); txBuf[0] = 8'h20; txBuf[1] = 8'h00;//heeader length 512 txBuf[2] = 8'h00; txBuf[3] = 8'h00; //子报文 txBuf[4] = 8'h0; txBuf[5] = 8'h8; //index = 2 txBuf[6] = 8'h08; //地址 //SM0 txBuf[7] = 8'h30; //地址 //偏置 txBuf[8] = 8'h20; //命令2 长度56 txBuf[9] = 8'd56; //长度 txBuf[10] = $random; txBuf[11] = $random; for( integer j = 0; j < 64-8; j = j + 1 ) begin @(posedge clock) #3 txBuf[12+j] = $random; end //------------------------- //子报文 txBuf[68] = 8'h0; txBuf[69] = 8'h4; //index = 1 txBuf[70] = 8'h08; //地址 //SM0 txBuf[71] = 8'h40; //地址 //偏置 txBuf[72] = 8'h10; //命令1 长度56 txBuf[73] = 8'd56; //长度 txBuf[74] = $random; txBuf[75] = $random; for( integer j = 0; j < 64-8; j = j + 1 ) begin @(posedge clock) #3 txBuf[76+j] = $random; end //------------------------- //子报文 txBuf[132] = 8'h0; txBuf[133] = 8'hc; //index = 3 txBuf[134] = 8'h09; //地址 //SM1 txBuf[135] = 8'h40; //地址 //偏置 txBuf[136] = 8'h00; //命令0 长度56 txBuf[137] = 8'd56; //长度 txBuf[138] = $random; txBuf[139] = $random; for( integer j = 0; j < 64-8; j = j + 1 ) begin @(posedge clock) #3 txBuf[140+j] = $random; end //------------------------- for( integer i = 0 ; i < 5; i = i + 1) begin //子报文 txBuf[196+i*64+0] = $random; txBuf[196+i*64+1] = 8'h0; //index = random txBuf[196+i*64+2] = $random; txBuf[196+i*64+3] = $random; txBuf[196+i*64+4] = 8'h00; //命令0 长度56 txBuf[196+i*64+5] = 8'd56; //长度 txBuf[196+i*64+6] = $random; txBuf[196+i*64+7] = $random; for( integer j = 0; j < 64-8; j = j + 1 ) begin @(posedge clock) #3 txBuf[196+i*64+8+j] = $random; end end spi_trans( (16'h1000), (`SPI_WRITE), (516), (0) ); //写入SM1 //发布请求 txBuf[0] = 8'h04; txBuf[1] = 8'h02; spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度 txBuf[0] = 8'h01; spi_trans( (16'h20), (`SPI_WRITE), (1), (0) );//发送SM0 接收SM0, 请求发送 end // 同步 #90000 #90000 #90000 #90000 #90000 #90000 #90000 #90000 #90000 #90000 #90000 #90000 #90000 #90000 begin //设置SM1在写入0x3地址触发enq txBuf[0] = 8'h17; txBuf[1] = 8'h00; spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) ); txBuf[0] = 8'h01; txBuf[1] = 8'h40;//heeader length 20 txBuf[2] = 8'h00; txBuf[3] = 8'h00; //子报文 //设置同步 txBuf[4] = 8'h0; //设备索引 txBuf[5] = 8'h0; //设备索引、类型 txBuf[6] = $random; //地址 txBuf[7] = $random; //地址 txBuf[8] = 8'he0; //命令d 负载长度2 txBuf[9] = 8'h0c; //负载长度c txBuf[10] = 8'h0; //工作计数0 txBuf[11] = 8'h0; //工作计数0 txBuf[12] = 0;//timeStamp[7:0]; //负载 txBuf[13] = 0;//timeStamp[15:8]; //负载 txBuf[14] = 0;//timeStamp[23:16]; //负载 txBuf[15] = 0;//timeStamp[31:24]; //负载 txBuf[16] = 0;//timeStamp[39:32]; //负载 txBuf[17] = 0;//timeStamp[47:40]; //负载 txBuf[18] = 0;//timeStamp[55:48]; //负载 txBuf[19] = 0;//timeStamp[63:56]; //负载 txBuf[20] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[ 7: 0]; //负载 txBuf[21] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[15: 8]; //负载 txBuf[22] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[23:16]; //负载 txBuf[23] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[31:24]; //负载 spi_trans( (16'h1000), (`SPI_WRITE), (24), (0) ); //写入SM1 //发布请求 txBuf[0] = 8'h18; txBuf[1] = 8'h00; spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度 txBuf[0] = 8'h01; spi_trans( (16'h20), (`SPI_WRITE), (1), (0) );//发送SM0 接收SM0, 请求发送 end end endmodule