Files
eb001/tb/shinTest/ShinTopSpiTb_clk.v

1121 lines
32 KiB
Verilog
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
`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<slength; i++) begin
if (scmd == 0) begin
$fwrite(spidata_file, "%02h ", txBuf[i + 3]);
end else begin
$fwrite(spidata_file, "%02h ", rxBuf[i + 3]);
end
c_line = 0;
if ((i+1)%16 == 0) begin
$fwrite(spidata_file, "\n");
c_line = 1;
end
end
if (c_line == 0) begin
$fwrite(spidata_file, "\n");
end
c_line = 0;
end
end
end
endtask
always @(posedge _reset_deactive) begin
if (io_int_sig[0]) $fdisplay(spidata_file, "**MST INT SETUP: %t", $realtime);
if (io_int_sig[1]) $fdisplay(spidata_file, "**SLV0 INT SETUP: %t", $realtime);
if (io_int_sig[2]) $fdisplay(spidata_file, "**SLV1 INT SETUP: %t", $realtime);
if (io_int_sig[3]) $fdisplay(spidata_file, "**SLV2 INT SETUP: %t", $realtime);
if (io_int_sig[4]) $fdisplay(spidata_file, "**SLV3 INT SETUP: %t", $realtime);
end
always @(posedge io_int_sig[0]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**MST INT SETUP: %t", $realtime);
end
always @(posedge io_int_sig[1]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV0 INT SETUP: %t", $realtime);
end
always @(posedge io_int_sig[2]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV1 INT SETUP: %t", $realtime);
end
always @(posedge io_int_sig[3]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV2 INT SETUP: %t", $realtime);
end
always @(posedge io_int_sig[4]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV3 INT SETUP: %t", $realtime);
end
always @(negedge io_int_sig[0]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**MST INT CLEAR: %t", $realtime);
end
always @(negedge io_int_sig[1]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV0 INT CLEAR: %t", $realtime);
end
always @(negedge io_int_sig[2]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV1 INT CLEAR: %t", $realtime);
end
always @(negedge io_int_sig[3]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV2 INT CLEAR: %t", $realtime);
end
always @(negedge io_int_sig[4]) begin
if (_reset_deactive == 1'b1)
$fdisplay(spidata_file, "**SLV3 INT CLEAR: %t", $realtime);
end
`define INTERFACE_IDX 0 //internal spi
`define IF_IDX(idx) ((`INTERFACE_IDX)+(idx))
`define IF_IQSPI(idx) ((idx))
`define IF_OQSPI(idx) ((`ALL_DEV_NUM * 2) + (idx))
`define IF_OSPI(idx) ((`ALL_DEV_NUM) + (idx))
`define SPI_WRITE 8'h0
`define SPI_READ 8'h1
`define MST_TX_TRIGGER(idx) (8'h1 + ((idx & 8'h3) * 8'h2) + ((idx & 8'h3) * 8'h8))
`define MST_RX0_ADDR 16'h0800
`define MST_TX0_ADDR 16'h1000
`define MST_RX1_ADDR 16'h1800
`define MST_TX1_ADDR 16'h2000
`define MST_RX2_ADDR 16'h2800
`define MST_TX2_ADDR 16'h3000
`define MST_RX3_ADDR 16'h3800
`define MST_TX3_ADDR 16'h4000
`define MST_RX0_LEN_ADDR 16'h0306
`define MST_TX0_LEN_ADDR 16'h0302
`define MST_RX1_LEN_ADDR 16'h030e
`define MST_TX1_LEN_ADDR 16'h030a
`define MST_RX2_LEN_ADDR 16'h0316
`define MST_TX2_LEN_ADDR 16'h0312
`define MST_RX3_LEN_ADDR 16'h031e
`define MST_TX3_LEN_ADDR 16'h031a
`define MST_TX_TRG (`MST_TX_TRIGGER(0))
`define MST_RX_ADDR (`MST_RX0_ADDR)
`define MST_TX_ADDR (`MST_TX0_ADDR)
`define MST_RX_LEN_ADDR (`MST_RX0_LEN_ADDR)
`define MST_TX_LEN_ADDR (`MST_TX0_LEN_ADDR)
`define SETTING_ENCRYPTION \
txBuf[3 + 0] = 8'hb1;\
txBuf[3 + 1] = 8'hd2;\
txBuf[3 + 2] = 8'hf1;\
txBuf[3 + 3] = 8'h03;\
txBuf[3 + 4] = 8'hf2;\
txBuf[3 + 5] = 8'h01;\
txBuf[3 + 6] = 8'hf5;\
txBuf[3 + 7] = 8'h04;\
txBuf[3 + 8] = 8'ha1;\
txBuf[3 + 9] = 8'h01;\
txBuf[3 + 10] = 8'hd3;\
txBuf[3 + 11] = 8'h07;\
txBuf[3 + 12] = 8'hc8;\
txBuf[3 + 13] = 8'hef;\
txBuf[3 + 14] = 8'hb9;\
txBuf[3 + 15] = 8'h52;\
txBuf[3 + 16] = 8'h01;
`define BEGIN_TESTCASE(filename) \
integer logh;\
logh = $fopen(filename, "w")
`define END_TESTCASE(filename) \
$fclose(logh)
`define SPI_TRANS(addr, cmd, len, iface) \
if (cmd == (`SPI_WRITE)) begin \
f_write(logh, addr, cmd, len);\
for (integer _k = 0; _k < len; _k++) begin \
$fwrite(logh, "8'h%02h ", txBuf[3 + _k]); \
end \
spi_trans(addr, cmd, len, iface); \
end else begin \
spi_trans(addr, cmd, len, iface); \
f_write(logh, addr, cmd, len);\
for (integer _k = 0; _k < len; _k++) begin \
$fwrite(logh, "8'h%02h ", rxBuf[3 + _k]); \
end \
end \
$fwrite(logh, "\n")
task f_write(input [31:0] logh, input [15:0] saddress, input [7:0] scmd, input [12:0] slength);
begin
$fwrite(logh, "16'h%04h 8'h%02h 16'h%04h ", saddress, scmd, slength);
end
endtask
task wait_comm_finished(input [16:0] dev_idx);
begin:WAIT_COMM_FINISHED_CODE
real st;
integer is_run;
st = $realtime;
is_run = 1;
`ifdef enable_wait_clear_int
txBuf[0] = 8'h00;
txBuf[1] = 8'h78;
txBuf[2] = `SPI_WRITE;
txBuf[3] = 8'h03;
txBuf[4] = 8'h00;
txBuf[5] = 8'h00;
txBuf[6] = 8'h00;
length = 8'h07;
idx = `IF_IQSPI(dev_idx);
#500000
@(negedge sck)
isReq <= 1;
@(posedge sck) #500000
isReq <= 0;
@( negedge isBusy) #100000000
begin
end
`endif
while (is_run == 1) begin
txBuf[0] = 8'h00;
txBuf[1] = 8'h74;
txBuf[2] = `SPI_READ;
length = 8'h07;
idx = `IF_IQSPI(dev_idx);
#500000
@(negedge sck)
isReq <= 1;
@(posedge sck) #500000
isReq <= 0;
@( negedge isBusy) #100000000
begin
end
#100000000
//$display("%x %x", rxBuf[3], rxBuf[6]);
if ((rxBuf[3] & 8'h02) == 8'h02)
begin
is_run = 0;
end
if ((rxBuf[6] & 8'h60) != 8'h00)
begin
$display("error occur");
is_run = 0;
end
if (($realtime - st) >= 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