Files
eb001/tb/shinTest/ShinTopSpiTb.v

659 lines
14 KiB
Coq
Raw Normal View History

2025-05-12 15:41:11 +08:00
`timescale 1 ns / 1 ps
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 spi_miso;
2025-05-12 15:41:11 +08:00
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),
.io_ospi_mosi(spi_mosi),
.io_ospi_miso(spi_miso),
2025-05-12 15:41:11 +08:00
.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),
.io_ospi_mosi(spi_mosi),
.io_ospi_miso(spi_miso),
2025-05-12 15:41:11 +08:00
.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),
.io_ospi_mosi(spi_mosi),
.io_ospi_miso(spi_miso),
2025-05-12 15:41:11 +08:00
.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),
.io_ospi_mosi(spi_mosi),
.io_ospi_miso(spi_miso),
2025-05-12 15:41:11 +08:00
.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),
.io_ospi_mosi(spi_mosi),
.io_ospi_miso(spi_miso),
2025-05-12 15:41:11 +08:00
.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_csn = 5'b11111;
#100
reset <= 1;
#240
reset <= 0;
#10000000
2025-05-12 15:41:11 +08:00
$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
`define SCKFRE #640
2025-05-12 15:41:11 +08:00
reg sck = 0;
2025-05-12 15:41:11 +08:00
initial begin
forever begin
`SCKFRE sck <= ~sck;
end
2025-05-12 15:41:11 +08:00
end
assign spi_sck = sck;
2025-05-12 15:41:11 +08:00
reg [7:0] txBuf[0:2047];
reg [7:0] rxBuf[0:2047];
reg [7:0] exChangeReg;
reg [7:0] exChangeReg0;
reg [7:0] exChangeReg1;
reg [7:0] exChangeReg2;
reg [7:0] exChangeReg3;
reg [7:0] exChangeReg4;
2025-05-12 15:41:11 +08:00
// assign spi_mosi[0] = exChangeReg0[7];
// assign spi_mosi[1] = exChangeReg1[7];
// assign spi_mosi[2] = exChangeReg2[7];
// assign spi_mosi[3] = exChangeReg3[7];
// assign spi_mosi[4] = exChangeReg4[7];
assign spi_mosi = exChangeReg[7];
2025-05-12 15:41:11 +08:00
reg isReq = 0;
reg isBusy = 0;
reg [11:0] length;
reg [7:0] idx;
2025-05-12 15:41:11 +08:00
reg [11:0] transCnt;
reg [11:0] byteCnt;
reg [3:0] bitCnt;
2025-05-12 15:41:11 +08:00
always @(posedge sck) begin
if( isReq ) begin
isBusy <= #5 1'b1;
transCnt <= #5 0;
byteCnt <= #5 0;
bitCnt <= #5 0;
spi_csn[idx] <= #5 1'b0;
exChangeReg <= txBuf[0];
end
if( isBusy ) begin
if( transCnt < length ) begin
bitCnt <= bitCnt + 1;
if( bitCnt == 7 ) begin
byteCnt <= byteCnt +1;
rxBuf[byteCnt] <= exChangeReg;
exChangeReg <= txBuf[byteCnt+1];
end else begin
exChangeReg <= {exChangeReg[6:0], spi_miso};
2025-05-12 15:41:11 +08:00
end
end else begin
isBusy <= #5 1'b0;
spi_csn[idx] <= #5 1'b1;
2025-05-12 15:41:11 +08:00
end
end
end
// task spi_trans( );
// begin
// #10
// `SCKFRE spi_sck[idx] <= 1'b0;
// if( idx == 0 ) exChangeReg0 <= #5 address[7:0];
// else if( idx == 1 ) exChangeReg1 <= #5 address[7:0];
// else if( idx == 2 ) exChangeReg2 <= #5 address[7:0];
// else if( idx == 3 ) exChangeReg3 <= #5 address[7:0];
// else if( idx == 4 ) exChangeReg4 <= #5 address[7:0];
// `SCKFRE spi_sck[idx] <= 1'b1;
// `SCKFRE spi_sck[idx] <= 1'b0;
// repeat(8) begin
// `SCKFRE spi_sck[idx] <= 1'b1;
// if( idx == 0 ) exChangeReg0 <= #5 {exChangeReg0[6:0], spi_miso[idx]};
// else if( idx == 1 ) exChangeReg1 <= #5 {exChangeReg1[6:0], spi_miso[idx]};
// else if( idx == 2 ) exChangeReg2 <= #5 {exChangeReg2[6:0], spi_miso[idx]};
// else if( idx == 3 ) exChangeReg3 <= #5 {exChangeReg3[6:0], spi_miso[idx]};
// else if( idx == 4 ) exChangeReg4 <= #5 {exChangeReg4[6:0], spi_miso[idx]};
// `SCKFRE spi_sck[idx] <= 1'b0;
// end
// if( idx == 0 ) exChangeReg0 <= #5 address[15:8];
// else if( idx == 1 ) exChangeReg1 <= #5 address[15:8];
// else if( idx == 2 ) exChangeReg2 <= #5 address[15:8];
// else if( idx == 3 ) exChangeReg3 <= #5 address[15:8];
// else if( idx == 4 ) exChangeReg4 <= #5 address[15:8];
// repeat(8) begin
// `SCKFRE spi_sck[idx] <= 1'b1;
// if( idx == 0 ) exChangeReg0 <= #5 {exChangeReg0[6:0], spi_miso[idx]};
// else if( idx == 1 ) exChangeReg1 <= #5 {exChangeReg1[6:0], spi_miso[idx]};
// else if( idx == 2 ) exChangeReg2 <= #5 {exChangeReg2[6:0], spi_miso[idx]};
// else if( idx == 3 ) exChangeReg3 <= #5 {exChangeReg3[6:0], spi_miso[idx]};
// else if( idx == 4 ) exChangeReg4 <= #5 {exChangeReg4[6:0], spi_miso[idx]};
// `SCKFRE spi_sck[idx] <= 1'b0;
// end
// if( idx == 0 ) exChangeReg0 <= #5 cmd;
// else if( idx == 1 ) exChangeReg1 <= #5 cmd;
// else if( idx == 2 ) exChangeReg2 <= #5 cmd;
// else if( idx == 3 ) exChangeReg3 <= #5 cmd;
// else if( idx == 4 ) exChangeReg4 <= #5 cmd;
// repeat(8) begin
// `SCKFRE spi_sck[idx] <= 1'b1;
// if( idx == 0 ) exChangeReg0 <= #5 {exChangeReg0[6:0], spi_miso[idx]};
// else if( idx == 1 ) exChangeReg1 <= #5 {exChangeReg1[6:0], spi_miso[idx]};
// else if( idx == 2 ) exChangeReg2 <= #5 {exChangeReg2[6:0], spi_miso[idx]};
// else if( idx == 3 ) exChangeReg3 <= #5 {exChangeReg3[6:0], spi_miso[idx]};
// else if( idx == 4 ) exChangeReg4 <= #5 {exChangeReg4[6:0], spi_miso[idx]};
// `SCKFRE spi_sck[idx] <= 1'b0;
// end
// while( transCnt < length ) begin
// if( idx == 0 ) exChangeReg0 <= #5 txBuf[transCnt];
// else if( idx == 1 ) exChangeReg1 <= #5 txBuf[transCnt];
// else if( idx == 2 ) exChangeReg2 <= #5 txBuf[transCnt];
// else if( idx == 3 ) exChangeReg3 <= #5 txBuf[transCnt];
// else if( idx == 4 ) exChangeReg4 <= #5 txBuf[transCnt];
// transCnt <= transCnt + 1;
// repeat(8) begin
// `SCKFRE spi_sck[idx] <= 1'b1;
// if( idx == 0 ) exChangeReg0 <= #5 {exChangeReg0[6:0], spi_miso[idx]};
// else if( idx == 1 ) exChangeReg1 <= #5 {exChangeReg1[6:0], spi_miso[idx]};
// else if( idx == 2 ) exChangeReg2 <= #5 {exChangeReg2[6:0], spi_miso[idx]};
// else if( idx == 3 ) exChangeReg3 <= #5 {exChangeReg3[6:0], spi_miso[idx]};
// else if( idx == 4 ) exChangeReg4 <= #5 {exChangeReg4[6:0], spi_miso[idx]};
// `SCKFRE spi_sck[idx] <= 1'b0;
// end
// rxBuf[transCnt] <= #5
// idx == 0 ? exChangeReg0 :
// idx == 1 ? exChangeReg1 :
// idx == 2 ? exChangeReg2 :
// idx == 3 ? exChangeReg3 :
// exChangeReg4;
// end
// spi_csn[idx] <= 1'b1;
// #2400
// spi_csn[idx] <= 1'b1;
// end
// endtask
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;
idx <= sidx;
#5
@(negedge sck)
isReq <= 1;
@(posedge sck) #5
isReq <= 0;
2025-05-12 15:41:11 +08:00
end
2025-05-12 15:41:11 +08:00
endtask
2025-05-12 15:41:11 +08:00
`define SPI_WRITE 8'h0
`define SPI_READ 8'h1
initial begin
#1000
//设置主站从站
txBuf[0+3] = 8'h01;
spi_trans( (16'h00), (`SPI_WRITE), (1), (0) );
2025-05-12 15:41:11 +08:00
#1000
txBuf[0+3] = 8'h02;
2025-05-12 15:41:11 +08:00
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+3] = 8'h03;
txBuf[1+3] = 8'h00;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) );
//无子报文
txBuf[0+3] = 8'h00;
txBuf[1+3] = 8'h01;//heeader length 0 嗅探包1
txBuf[2+3] = 8'h00;
txBuf[3+3] = 8'h00;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h1000), (`SPI_WRITE), (4), (0) ); //写入SM1
//发布请求
txBuf[0+3] = 8'h04;
txBuf[1+3] = 8'h00;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度
txBuf[0+3] = 8'h01;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h20), (`SPI_WRITE), (1), (0) );//发送SM0 接收SM0, 请求发送
end
// 顺序索引
#50000
#50000
#50000
$display("index @ %d", s_ShinTop_Mst.interface__io_timeStamp);
2025-05-12 15:41:11 +08:00
begin
//设置SM1在写入0xd地址触发enq
txBuf[0+3] = 8'h0d;
txBuf[1+3] = 8'h00;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) );
txBuf[0+3] = 8'h00;
txBuf[1+3] = 8'ha0;//heeader length 10
txBuf[2+3] = 8'h00;
txBuf[3+3] = 8'h00;
2025-05-12 15:41:11 +08:00
//子报文
//设置顺序地址
txBuf[4+3] = 8'h0; //设备索引
txBuf[5+3] = 8'h0; //设备索引类型
txBuf[6+3] = $random; //地址
txBuf[7+3] = $random; //地址
txBuf[8+3] = 8'hd0; //命令d 负载长度2
txBuf[9+3] = 8'd02; //负载长度2
txBuf[10+3] = 8'h0; //工作计数0
txBuf[11+3] = 8'h0; //工作计数0
txBuf[12+3] = 8'h0; //负载
txBuf[13+3] = 8'h0; //负载
2025-05-12 15:41:11 +08:00
spi_trans( (16'h1000), (`SPI_WRITE), (14), (0) ); //写入SM1
//发布请求
txBuf[0+3] = 8'h0e;
txBuf[1+3] = 8'h00;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度
txBuf[0+3] = 8'h01;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h20), (`SPI_WRITE), (1), (0) );//发送SM0 接收SM0, 请求发送
end
//读写
#50000
#50000
#50000
#50000
$display("read&write @ %d", s_ShinTop_Mst.interface__io_timeStamp);
2025-05-12 15:41:11 +08:00
begin
//设置SM1在写入516地址触发enq
txBuf[0+3] = 8'h03;
txBuf[1+3] = 8'h02;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) );
txBuf[0+3] = 8'h20;
txBuf[1+3] = 8'h00;//heeader length 512
txBuf[2+3] = 8'h00;
txBuf[3+3] = 8'h00;
2025-05-12 15:41:11 +08:00
//子报文
txBuf[4+3] = 8'h0;
txBuf[5+3] = 8'h8; //index = 2
txBuf[6+3] = 8'h08; //地址 //SM0
txBuf[7+3] = 8'h30; //地址 //偏置
txBuf[8+3] = 8'h20; //命令2 长度56
txBuf[9+3] = 8'd56; //长度
txBuf[10+3] = $random;
txBuf[11+3] = $random;
2025-05-12 15:41:11 +08:00
for( integer j = 0; j < 64-8; j = j + 1 ) begin
@(posedge clock) #3
txBuf[12+3+j] = $random;
2025-05-12 15:41:11 +08:00
end
//-------------------------
//子报文
txBuf[68+3] = 8'h0;
txBuf[69+3] = 8'h4; //index = 1
txBuf[70+3] = 8'h08; //地址 //SM0
txBuf[71+3] = 8'h40; //地址 //偏置
txBuf[72+3] = 8'h10; //命令1 长度56
txBuf[73+3] = 8'd56; //长度
txBuf[74+3] = $random;
txBuf[75+3] = $random;
2025-05-12 15:41:11 +08:00
for( integer j = 0; j < 64-8; j = j + 1 ) begin
@(posedge clock) #3
txBuf[76+3+j] = $random;
2025-05-12 15:41:11 +08:00
end
//-------------------------
//子报文
txBuf[132+3] = 8'h0;
txBuf[133+3] = 8'hc; //index = 3
txBuf[134+3] = 8'h09; //地址 //SM1
txBuf[135+3] = 8'h40; //地址 //偏置
txBuf[136+3] = 8'h00; //命令0 长度56
txBuf[137+3] = 8'd56; //长度
txBuf[138+3] = $random;
txBuf[139+3] = $random;
2025-05-12 15:41:11 +08:00
for( integer j = 0; j < 64-8; j = j + 1 ) begin
@(posedge clock) #3
txBuf[140+3+j] = $random;
2025-05-12 15:41:11 +08:00
end
//-------------------------
for( integer i = 0 ; i < 5; i = i + 1) begin
//子报文
txBuf[196+3+i*64+0] = $random;
txBuf[196+3+i*64+1] = 8'h0; //index = random
txBuf[196+3+i*64+2] = $random;
txBuf[196+3+i*64+3] = $random;
txBuf[196+3+i*64+4] = 8'h00; //命令0 长度56
txBuf[196+3+i*64+5] = 8'd56; //长度
txBuf[196+3+i*64+6] = $random;
txBuf[196+3+i*64+7] = $random;
2025-05-12 15:41:11 +08:00
for( integer j = 0; j < 64-8; j = j + 1 ) begin
@(posedge clock) #3
txBuf[196+3+i*64+8+j] = $random;
2025-05-12 15:41:11 +08:00
end
end
spi_trans( (16'h1000), (`SPI_WRITE), (516), (0) ); //写入SM1
//发布请求
txBuf[0+3] = 8'h04;
txBuf[1+3] = 8'h02;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度
txBuf[0+3] = 8'h01;
2025-05-12 15:41:11 +08:00
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
$display("sync @ %d", s_ShinTop_Mst.interface__io_timeStamp);
2025-05-12 15:41:11 +08:00
begin
//设置SM1在写入0x3地址触发enq
txBuf[0+3] = 8'h17;
txBuf[1+3] = 8'h00;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h0202), (`SPI_WRITE), (2), (0) );
txBuf[0+3] = 8'h01;
txBuf[1+3] = 8'h40;//heeader length 20
txBuf[2+3] = 8'h00;
txBuf[3+3] = 8'h00;
2025-05-12 15:41:11 +08:00
//子报文
//设置同步
txBuf[4+3] = 8'h0; //设备索引
txBuf[5+3] = 8'h0; //设备索引类型
txBuf[6+3] = $random; //地址
txBuf[7+3] = $random; //地址
txBuf[8+3] = 8'he0; //命令d 负载长度2
txBuf[9+3] = 8'h0c; //负载长度c
txBuf[10+3] = 8'h0; //工作计数0
txBuf[11+3] = 8'h0; //工作计数0
txBuf[12+3] = 0;//timeStamp[7:0]; //负载
txBuf[13+3] = 0;//timeStamp[15:8]; //负载
txBuf[14+3] = 0;//timeStamp[23:16]; //负载
txBuf[15+3] = 0;//timeStamp[31:24]; //负载
txBuf[16+3] = 0;//timeStamp[39:32]; //负载
txBuf[17+3] = 0;//timeStamp[47:40]; //负载
txBuf[18+3] = 0;//timeStamp[55:48]; //负载
txBuf[19+3] = 0;//timeStamp[63:56]; //负载
txBuf[20+3] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[ 7: 0]; //负载
txBuf[21+3] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[15: 8]; //负载
txBuf[22+3] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[23:16]; //负载
txBuf[23+3] = 0;//s_ShinTop_Mst.masterParser.deltaTimeStamp[31:24]; //负载
2025-05-12 15:41:11 +08:00
spi_trans( (16'h1000), (`SPI_WRITE), (24), (0) ); //写入SM1
//发布请求
txBuf[0+3] = 8'h18;
txBuf[1+3] = 8'h00;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h21), (`SPI_WRITE), (2), (0) );//写入长度
txBuf[0+3] = 8'h01;
2025-05-12 15:41:11 +08:00
spi_trans( (16'h20), (`SPI_WRITE), (1), (0) );//发送SM0 接收SM0, 请求发送
end
end
endmodule