7
mirror of https://github.com/parallella/parallella-hw.git synced 2024-11-24 03:34:40 +00:00
parallella-hw/archive/fpga/test/elink_test/elink2stream_tb.v
Andreas Olofsson 046706db8a Reorg
2016-02-03 00:43:14 -05:00

455 lines
12 KiB
Verilog

`timescale 1 ns / 1 ps
`define NULL 0
`define EOF 32'hFFFF_FFFF
`define MAX_LINE_LENGTH 200
module elink2stream_tb;
reg aclk;
reg aresetn;
reg start;
wire reset = ~aresetn;
wire done0;
wire error0;
wire rx_cclk_n;
wire rx_cclk_p;
wire [11:0] param_coreid = 12'h810;
wire TX_rd_wait_n = 1'b1;
wire TX_rd_wait_p = 1'b0;
wire TX_wr_wait_n = 1'b1;
wire TX_wr_wait_p = 1'b0;
wire [31:0]M00_AXI_araddr;
wire [1:0]M00_AXI_arburst;
wire [3:0]M00_AXI_arcache;
wire [0:0]M00_AXI_arid;
wire [7:0]M00_AXI_arlen;
wire M00_AXI_arlock;
wire [2:0]M00_AXI_arprot;
wire [3:0]M00_AXI_arqos;
wire M00_AXI_arready = 1'b1;
wire [2:0]M00_AXI_arsize;
wire M00_AXI_arvalid;
wire [31:0]M00_AXI_awaddr;
wire [1:0]M00_AXI_awburst;
wire [3:0]M00_AXI_awcache;
wire [0:0]M00_AXI_awid;
wire [7:0]M00_AXI_awlen;
wire M00_AXI_awlock;
wire [2:0]M00_AXI_awprot;
wire [3:0]M00_AXI_awqos;
wire M00_AXI_awready = 1'b1;
wire [2:0]M00_AXI_awsize;
wire M00_AXI_awvalid;
wire [0:0]M00_AXI_bid = 1'b0;
wire M00_AXI_bready;
wire [1:0]M00_AXI_bresp = 2'b00;
reg M00_AXI_bvalid;
reg [63:0]M00_AXI_rdata;
reg [0:0]M00_AXI_rid = 1'b0;
reg M00_AXI_rlast;
wire M00_AXI_rready;
wire [1:0]M00_AXI_rresp = 2'b00;
reg M00_AXI_rvalid;
wire [63:0]M00_AXI_wdata;
wire M00_AXI_wlast;
wire M00_AXI_wready = 1'b1;
wire [7:0]M00_AXI_wstrb;
wire M00_AXI_wvalid;
wire [7:0]TX_data_n;
wire [7:0]TX_data_p;
wire TX_frame_n;
wire TX_frame_p;
wire TX_lclk_n;
wire TX_lclk_p;
reg [7:0]RX_data_p;
wire [7:0]RX_data_n = ~RX_data_p;
reg RX_frame_p;
wire RX_frame_n = ~RX_frame_p;
wire RX_lclk_n = TX_lclk_n;
wire RX_lclk_p = TX_lclk_p;
wire RX_rd_wait_n;
wire RX_rd_wait_p;
wire RX_wr_wait_n;
wire RX_wr_wait_p;
// Transaction parameters
reg [31:0] src, dst, data;
reg [3:0] ctrlmode;
reg [1:0] datamode;
reg write;
reg access;
reg stream;
reg [31:0] delay;
reg done;
wire all_done;
assign #5000 all_done = done;
// Transmitter state machine
reg [15:0] pc;
reg [4:0] txstate;
reg [15:0] delaycnt;
reg isstream;
integer writecount;
integer readcount;
integer fileid;
integer fscanret;
reg [8*`MAX_LINE_LENGTH:0] line;
task getnext;
begin // delay src dst data cmode dmode write access stream done
if($feof(fileid)) begin
$display("Unexpected EOF");
$finish;
end
fscanret = $fgets(line, fileid);
fscanret = $sscanf(line, "%d %h %h %h %h %d %d %d %d %d",
delay, src, dst, data, ctrlmode, datamode,
write, access, stream, done);
if(fscanret == 1) begin
src <= 32'd0;
dst <= 32'd0;
data <= 32'd0;
ctrlmode <= 4'd0;
datamode <= 2'd0;
write <= 1'b0;
access <= 1'b0;
stream <= 1'b0;
done <= 1'b0;
end else if(fscanret != 10) begin
$display("ERROR: Wrong number of entries in file: (position %d) %s",
$ftell(fileid), line);
$finish;
end
end
endtask // getnext
initial begin
fileid = $fopen("../../test_prog.dat", "r");
if(fileid == 0) begin
$display("Unable to open file!");
$finish;
end
getnext();
end
wire lclk_delay;
assign #0.8333 lclk_delay = TX_lclk_p;
// Test transmitter
always @ (lclk_delay) begin
if(~done0) begin
pc <= 16'd1;
txstate <= 5'd0;
delaycnt <= 16'd0;
RX_data_p <= 8'd0;
RX_frame_p <= 1'b0;
isstream <= 1'b0;
writecount <= 0;
readcount <= 0;
end else begin
// default is to advance to next state
txstate <= txstate + 1;
case(txstate)
5'd0: begin // Start new transaction or delay
RX_frame_p <= 1'b0;
delaycnt <= delay - 16'd2;
isstream <= 1'b0;
if(done) begin
txstate <= 5'd31;
$display("<-- Transmission complete!");
end else if(delay == 16'd1) begin
txstate <= 5'd0;
pc <= pc + 16'd1;
getnext();
$display("<-- Waiting 1 cycle");
end else if(|delay) begin
txstate <= 5'd16;
$display("<-- Waiting %d cycles", delay);
end else if(RX_wr_wait_p | RX_rd_wait_p) begin
txstate <= 5'd0;
end else begin
if(write) begin
$write("<-- %d Writing ", writecount);
writecount <= writecount + 1;
end else begin
$write("<-- %d Reading ", readcount);
readcount <= readcount + 1;
end
case(datamode)
2'd0: $write("BYTE ");
2'd1: $write("HWORD ");
2'd2: $write("WORD ");
2'd3: $write("DWORD ");
endcase // case (datamode)
if(write && datamode == 3'd3)
$display("0x%H:0x%H to address 0x%H", src, data, dst);
else if(write)
$display("0x%H to address 0x%H", data, dst);
else
$display("from address 0x%H, return to 0x%H", dst, src);
end
end
5'd1: begin // TRAN byte
RX_data_p <= {~write, 7'd0};
RX_frame_p <= 1'b1;
end
5'd2:
RX_data_p <= {ctrlmode, dst[31:28]};
5'd3:
RX_data_p <= dst[27:20];
5'd4:
RX_data_p <= dst[19:12];
5'd5:
RX_data_p <= dst[11:4];
5'd6:
RX_data_p <= {dst[3:0], datamode, write, access};
5'd7: begin
if(isstream) begin
$display("<-- %d Streaming data 0x%H:0x%H",
writecount, src, data);
writecount <= writecount + 1;
end
RX_data_p <= data[31:24];
end
5'd8:
RX_data_p <= data[23:16];
5'd9:
RX_data_p <= data[15:8];
5'd10:
RX_data_p <= data[7:0];
5'd11:
RX_data_p <= src[31:24];
5'd12:
RX_data_p <= src[23:16];
5'd13:
RX_data_p <= src[15:8];
5'd14: begin
RX_data_p <= src[7:0];
pc <= pc + 1;
getnext();
isstream <= stream;
if(stream)
txstate <= 5'd7; // next 'data'
else
txstate <= 5'd0;
end
5'd16: begin // delay, hold eLink idle
delaycnt <= delaycnt - 1;
if(~|delaycnt) begin
pc <= pc + 1;
getnext();
txstate <= 5'd0;
end else begin
txstate <= txstate; // override default
end
end
5'd31: txstate <= txstate; // All done
endcase // case (txstate)
end // else: !if(reset)
end // always @ (TX_lclk_p)
integer awcount, wcount, arcount;
initial begin
awcount = 0;
wcount = 0;
arcount = 0;
end
always @ (posedge aclk) begin
if(M00_AXI_awvalid & M00_AXI_awready) begin
$display("--> %d Write address: 0x%H, size: %d, len: %d",
awcount, M00_AXI_awaddr, M00_AXI_awsize, M00_AXI_awlen);
awcount <= awcount + 1;
end
end
// Respond to write requests
always @ (posedge aclk) begin
if(reset) begin
M00_AXI_bvalid <= 1'b0;
end else begin
if(M00_AXI_awvalid & M00_AXI_awready) begin
$display("--> %d Write data: 0x%H", wcount, M00_AXI_wdata);
M00_AXI_bvalid <= 1'b1;
wcount <= wcount + 1;
end else if(M00_AXI_bready) begin
M00_AXI_bvalid <= 1'b0;
end
end
end
// Respond to read requests
always @ (posedge aclk) begin
if(reset) begin
M00_AXI_rdata <= 64'd0;
M00_AXI_rlast <= 1'b0;
M00_AXI_rvalid <= 1'b0;
end else begin
if(M00_AXI_arvalid & M00_AXI_arready) begin
$display("--> %d Read request: <TBD>", arcount);
arcount <= arcount + 1;
end
end
end
// Reset Generator
initial begin
aresetn = 1'b0;
#500;
// Release the reset on the posedge of the clk.
@(posedge aclk);
aresetn = 1'b1;
end
// Clock Generator
initial aclk = 1'b0;
always #5 aclk = ~aclk;
// Drive the BFM
initial begin
start = 1'b0;
// Wait for end of reset
wait(aresetn === 0) @(posedge aclk);
wait(aresetn === 1) @(posedge aclk);
#500 start = 1'b1;
@(posedge aclk);
$display("=== TB Started");
wait( all_done == 1'b1);
$display("=== TEST_FINISHED");
if ( wcount != writecount || arcount != readcount ) begin
$display("=== TEST: FAILED!\n %d writes sent, %d writes rcvd\n %d reads sent, %d reads rcvd",
writecount, wcount, readcount, arcount);
end else begin
$display("=== TEST: PASSED!");
end
end
always @ (posedge done0)
$display("=== INIT Complete");
always @ (posedge error0)
if( done0 == 1'b0)
$display("=== ERROR FLAG INIT @ %T", $time);
// Create an instance of the example
elink2_stream dut
(.M00_AXI_araddr(M00_AXI_araddr),
.M00_AXI_arburst(M00_AXI_arburst),
.M00_AXI_arcache(M00_AXI_arcache),
.M00_AXI_arid(M00_AXI_arid),
.M00_AXI_arlen(M00_AXI_arlen),
.M00_AXI_arlock(M00_AXI_arlock),
.M00_AXI_arprot(M00_AXI_arprot),
.M00_AXI_arqos(M00_AXI_arqos),
.M00_AXI_arready(M00_AXI_arready),
.M00_AXI_arsize(M00_AXI_arsize),
.M00_AXI_arvalid(M00_AXI_arvalid),
.M00_AXI_awaddr(M00_AXI_awaddr),
.M00_AXI_awburst(M00_AXI_awburst),
.M00_AXI_awcache(M00_AXI_awcache),
.M00_AXI_awid(M00_AXI_awid),
.M00_AXI_awlen(M00_AXI_awlen),
.M00_AXI_awlock(M00_AXI_awlock),
.M00_AXI_awprot(M00_AXI_awprot),
.M00_AXI_awqos(M00_AXI_awqos),
.M00_AXI_awready(M00_AXI_awready),
.M00_AXI_awsize(M00_AXI_awsize),
.M00_AXI_awvalid(M00_AXI_awvalid),
.M00_AXI_bid(M00_AXI_bid),
.M00_AXI_bready(M00_AXI_bready),
.M00_AXI_bresp(M00_AXI_bresp),
.M00_AXI_bvalid(M00_AXI_bvalid),
.M00_AXI_rdata(M00_AXI_rdata),
.M00_AXI_rid(M00_AXI_rid),
.M00_AXI_rlast(M00_AXI_rlast),
.M00_AXI_rready(M00_AXI_rready),
.M00_AXI_rresp(M00_AXI_rresp),
.M00_AXI_rvalid(M00_AXI_rvalid),
.M00_AXI_wdata(M00_AXI_wdata),
.M00_AXI_wlast(M00_AXI_wlast),
.M00_AXI_wready(M00_AXI_wready),
.M00_AXI_wstrb(M00_AXI_wstrb),
.M00_AXI_wvalid(M00_AXI_wvalid),
.RX_data_n(RX_data_n),
.RX_data_p(RX_data_p),
.RX_frame_n(RX_frame_n),
.RX_frame_p(RX_frame_p),
.RX_lclk_n(RX_lclk_n),
.RX_lclk_p(RX_lclk_p),
.RX_rd_wait_n(RX_rd_wait_n),
.RX_rd_wait_p(RX_rd_wait_p),
.RX_wr_wait_n(RX_wr_wait_n),
.RX_wr_wait_p(RX_wr_wait_p),
.TX_data_n(TX_data_n),
.TX_data_p(TX_data_p),
.TX_frame_n(TX_frame_n),
.TX_frame_p(TX_frame_p),
.TX_lclk_n(TX_lclk_n),
.TX_lclk_p(TX_lclk_p),
.TX_rd_wait_n(TX_rd_wait_n),
.TX_rd_wait_p(TX_rd_wait_p),
.TX_wr_wait_n(TX_wr_wait_n),
.TX_wr_wait_p(TX_wr_wait_p),
.aclk(aclk),
.aresetn(aresetn),
.done0(done0),
.error0(error0),
.param_coreid(param_coreid),
.reset(reset),
.rx_cclk_n(rx_cclk_n),
.rx_cclk_p(rx_cclk_p),
.start(start));
endmodule