mirror of
https://github.com/bmartini/zynq-axis.git
synced 2024-09-05 19:19:27 +08:00
Merge branch 'update-axis'
More robust configuration that will allow for the use of the AXIS module in a scatter/gather operation. Will be able to handle contiguous streams of read/write data even when they are part of different configurations.
This commit is contained in:
commit
61089223ef
@ -11,7 +11,8 @@
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_ `define _axis_
|
||||
`ifndef _axis_
|
||||
`define _axis_
|
||||
|
||||
|
||||
`include "axis_write.v"
|
||||
@ -19,14 +20,15 @@
|
||||
|
||||
module axis #(
|
||||
parameter
|
||||
BUF_CFG_AWIDTH = 5,
|
||||
BUF_AWIDTH = 9,
|
||||
|
||||
CONFIG_ID_WR = 1,
|
||||
CONFIG_ID_RD = 2,
|
||||
CONFIG_ADDR = 23,
|
||||
CONFIG_DATA = 24,
|
||||
CONFIG_AWIDTH = 5,
|
||||
CONFIG_DWIDTH = 32,
|
||||
CFG_ID_WR = 1,
|
||||
CFG_ID_RD = 2,
|
||||
CFG_ADDR = 23,
|
||||
CFG_DATA = 24,
|
||||
CFG_AWIDTH = 5,
|
||||
CFG_DWIDTH = 32,
|
||||
|
||||
STREAM_WIDTH = 32,
|
||||
|
||||
@ -38,8 +40,8 @@ module axis #(
|
||||
input rst,
|
||||
|
||||
// configuation
|
||||
input [CONFIG_AWIDTH-1:0] cfg_addr,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_data,
|
||||
input [CFG_AWIDTH-1:0] cfg_addr,
|
||||
input [CFG_DWIDTH-1:0] cfg_data,
|
||||
input cfg_valid,
|
||||
|
||||
// stream interface
|
||||
@ -119,6 +121,24 @@ module axis #(
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
reg [CFG_AWIDTH-1:0] cfg_addr_r;
|
||||
reg [CFG_DWIDTH-1:0] cfg_data_r;
|
||||
reg cfg_valid_r;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_valid_r <= 1'b0;
|
||||
else cfg_valid_r <= cfg_valid;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk) begin
|
||||
cfg_addr_r <= cfg_addr;
|
||||
cfg_data_r <= cfg_data;
|
||||
end
|
||||
|
||||
|
||||
// write path static values
|
||||
assign axi_awlock = 1'h0; // NORMAL_ACCESS
|
||||
assign axi_awcache = 4'h0; // NON_CACHE_NON_BUFFER
|
||||
@ -126,8 +146,6 @@ module axis #(
|
||||
assign axi_awburst = 2'h1; // INCREMENTING
|
||||
assign axi_awqos = 4'h0; // NOT_QOS_PARTICIPANT
|
||||
assign axi_awsize = BURST_SIZE;
|
||||
assign axi_awid = {AXI_ID_WIDTH{1'b0}};
|
||||
assign axi_wid = {AXI_ID_WIDTH{1'b0}};
|
||||
assign axi_wstrb = {(AXI_DATA_WIDTH/8){1'b1}};
|
||||
|
||||
// read path static values
|
||||
@ -137,7 +155,6 @@ module axis #(
|
||||
assign axi_arburst = 2'h1; // INCREMENTING
|
||||
assign axi_arqos = 4'h0; // NOT_QOS_PARTICIPANT
|
||||
assign axi_arsize = BURST_SIZE;
|
||||
assign axi_arid = {AXI_ID_WIDTH{1'b0}};
|
||||
|
||||
|
||||
// assume that all writes are successful and therefore do not need to
|
||||
@ -146,14 +163,16 @@ module axis #(
|
||||
|
||||
|
||||
axis_write #(
|
||||
.BUF_CFG_AWIDTH (BUF_CFG_AWIDTH),
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID_WR),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.CFG_ID (CFG_ID_WR),
|
||||
.CFG_ADDR (CFG_ADDR),
|
||||
.CFG_DATA (CFG_DATA),
|
||||
.CFG_AWIDTH (CFG_AWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
@ -162,17 +181,20 @@ module axis #(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_addr (cfg_addr),
|
||||
.cfg_data (cfg_data),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_addr (cfg_addr_r),
|
||||
.cfg_data (cfg_data_r),
|
||||
.cfg_valid (cfg_valid_r),
|
||||
.cfg_ready (),
|
||||
|
||||
.axi_awready (axi_awready),
|
||||
.axi_awid (axi_awid),
|
||||
.axi_awaddr (axi_awaddr),
|
||||
.axi_awlen (axi_awlen),
|
||||
.axi_awvalid (axi_awvalid),
|
||||
.axi_awready (axi_awready),
|
||||
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wid (axi_wid),
|
||||
.axi_wdata (axi_wdata),
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wvalid (axi_wvalid),
|
||||
.axi_wready (axi_wready),
|
||||
|
||||
@ -183,14 +205,16 @@ module axis #(
|
||||
|
||||
|
||||
axis_read #(
|
||||
.BUF_CFG_AWIDTH (BUF_CFG_AWIDTH),
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID_RD),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.CFG_ID (CFG_ID_RD),
|
||||
.CFG_ADDR (CFG_ADDR),
|
||||
.CFG_DATA (CFG_DATA),
|
||||
.CFG_AWIDTH (CFG_AWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
|
||||
.AXI_ID_WIDTH (AXI_ID_WIDTH),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
@ -199,16 +223,19 @@ module axis #(
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.cfg_addr (cfg_addr),
|
||||
.cfg_data (cfg_data),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_addr (cfg_addr_r),
|
||||
.cfg_data (cfg_data_r),
|
||||
.cfg_valid (cfg_valid_r),
|
||||
.cfg_ready (),
|
||||
|
||||
.axi_arready (axi_arready),
|
||||
.axi_arid (axi_arid),
|
||||
.axi_araddr (axi_araddr),
|
||||
.axi_arlen (axi_arlen),
|
||||
.axi_arvalid (axi_arvalid),
|
||||
.axi_arready (axi_arready),
|
||||
|
||||
.axi_rdata (axi_rdata),
|
||||
.axi_rlast (axi_rlast),
|
||||
.axi_rvalid (axi_rvalid),
|
||||
.axi_rready (axi_rready),
|
||||
|
||||
|
@ -14,12 +14,17 @@
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_addr_ `define _axis_addr_
|
||||
`ifndef _axis_addr_
|
||||
`define _axis_addr_
|
||||
|
||||
`include "fifo_simple.v"
|
||||
|
||||
`define MIN(p,q) (p)<(q)?(p):(q)
|
||||
|
||||
module axis_addr
|
||||
#(parameter
|
||||
CONFIG_DWIDTH = 32,
|
||||
BUF_CFG_AWIDTH = 5,
|
||||
CFG_DWIDTH = 32,
|
||||
WIDTH_RATIO = 16,
|
||||
CONVERT_SHIFT = 3,
|
||||
AXI_LEN_WIDTH = 8,
|
||||
@ -28,10 +33,10 @@ module axis_addr
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_DWIDTH-1:0] cfg_address,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
input [CFG_DWIDTH-1:0] cfg_address,
|
||||
input [CFG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_val,
|
||||
output cfg_rdy,
|
||||
|
||||
input axi_aready,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_aaddr,
|
||||
@ -43,11 +48,12 @@ module axis_addr
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam BURST_NB_WIDTH = CONFIG_DWIDTH-AXI_LEN_WIDTH;
|
||||
localparam AWIDTH = `MIN(CFG_DWIDTH, AXI_ADDR_WIDTH);
|
||||
localparam BURST_NB_WIDTH = CFG_DWIDTH-AXI_LEN_WIDTH;
|
||||
localparam BURST_LENGTH = 1<<AXI_LEN_WIDTH;
|
||||
|
||||
localparam
|
||||
IDLE = 0,
|
||||
CONFIG = 0,
|
||||
SETUP = 1,
|
||||
BURST = 2,
|
||||
LAST = 3,
|
||||
@ -68,6 +74,13 @@ module axis_addr
|
||||
reg [4:0] state;
|
||||
reg [4:0] state_nx;
|
||||
|
||||
wire cfg_buf_pop;
|
||||
wire cfg_buf_full;
|
||||
wire cfg_buf_empty;
|
||||
wire [CFG_DWIDTH-1:0] cfg_buf_address;
|
||||
wire [CFG_DWIDTH-1:0] cfg_buf_length;
|
||||
reg cfg_buf_valid;
|
||||
|
||||
reg last_en;
|
||||
reg [AXI_LEN_WIDTH-1:0] last_nb;
|
||||
|
||||
@ -76,61 +89,71 @@ module axis_addr
|
||||
reg [BURST_NB_WIDTH-1:0] burst_cnt;
|
||||
wire burst_done;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length_r;
|
||||
reg cfg_valid_r;
|
||||
reg [AXI_ADDR_WIDTH-1:0] axi_address;
|
||||
reg [CFG_DWIDTH-1:0] axi_length;
|
||||
reg axi_valid;
|
||||
reg cfg_done;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] axi_address;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_ready = state[IDLE];
|
||||
|
||||
assign axi_aaddr = axi_address;
|
||||
assign cfg_rdy = ~cfg_buf_full;
|
||||
|
||||
assign axi_alen = state[BURST] ? (BURST_LENGTH-1) : last_nb;
|
||||
|
||||
assign axi_avalid = state[BURST] | state[LAST];
|
||||
fifo_simple #(
|
||||
.DATA_WIDTH (2*CFG_DWIDTH),
|
||||
.ADDR_WIDTH (BUF_CFG_AWIDTH))
|
||||
cfg_buffer_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
assign burst_done = (burst_nb == burst_cnt);
|
||||
.count (),
|
||||
.empty (cfg_buf_empty),
|
||||
.empty_a (),
|
||||
.full (cfg_buf_full),
|
||||
.full_a (),
|
||||
|
||||
.push_data ({cfg_address, cfg_length}),
|
||||
.push (cfg_val),
|
||||
|
||||
.pop_data ({cfg_buf_address, cfg_buf_length}),
|
||||
.pop (cfg_buf_pop)
|
||||
);
|
||||
|
||||
|
||||
assign cfg_buf_pop = ~cfg_buf_empty & state[CONFIG];
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_valid_r <= 1'b0;
|
||||
else cfg_valid_r <= cfg_valid;
|
||||
if (rst) begin
|
||||
cfg_buf_valid <= 1'b0;
|
||||
axi_valid <= 1'b0;
|
||||
cfg_done <= 1'b0;
|
||||
end
|
||||
else begin
|
||||
cfg_buf_valid <= cfg_buf_pop;
|
||||
axi_valid <= cfg_buf_valid;
|
||||
cfg_done <= axi_valid;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
if (cfg_buf_valid) begin
|
||||
// the shift converts from number of stream elements to number of
|
||||
// bursts to be sent to the memory after stream is packed. adding a
|
||||
// bit to the length ensures that the shift rounds up
|
||||
|
||||
cfg_length_r <= (cfg_length+WIDTH_RATIO-1) >> CONVERT_SHIFT;
|
||||
axi_length <= (cfg_buf_length+WIDTH_RATIO-1) >> CONVERT_SHIFT;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_done <= 1'b0;
|
||||
else cfg_done <= cfg_valid_r;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid_r) begin
|
||||
last_en <= |(cfg_length_r[AXI_LEN_WIDTH-1:0]);
|
||||
last_nb <= cfg_length_r[AXI_LEN_WIDTH-1:0]-1;
|
||||
|
||||
burst_en <= |(cfg_length_r[AXI_LEN_WIDTH +: BURST_NB_WIDTH]);
|
||||
burst_nb <= cfg_length_r[AXI_LEN_WIDTH +: BURST_NB_WIDTH]-1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
axi_address <= cfg_address;
|
||||
if (cfg_buf_valid) begin
|
||||
axi_address <= {AXI_ADDR_WIDTH{1'b0}};
|
||||
axi_address[AWIDTH-1:0] <= cfg_buf_address[AWIDTH-1:0];
|
||||
end
|
||||
else if (axi_aready & state[BURST]) begin
|
||||
// e.g. each burst has 256 long words & each long word has 32 bytes
|
||||
@ -139,7 +162,17 @@ module axis_addr
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) begin
|
||||
if (axi_valid) begin
|
||||
last_en <= |(axi_length[AXI_LEN_WIDTH-1:0]);
|
||||
last_nb <= axi_length[AXI_LEN_WIDTH-1:0]-1;
|
||||
|
||||
burst_en <= |(axi_length[AXI_LEN_WIDTH +: BURST_NB_WIDTH]);
|
||||
burst_nb <= axi_length[AXI_LEN_WIDTH +: BURST_NB_WIDTH]-1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (axi_valid) begin
|
||||
burst_cnt <= 'b0;
|
||||
end
|
||||
else if (axi_aready & state[BURST]) begin
|
||||
@ -147,10 +180,13 @@ module axis_addr
|
||||
end
|
||||
|
||||
|
||||
assign burst_done = (burst_nb == burst_cnt);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
state <= 'b0;
|
||||
state[IDLE] <= 1'b1;
|
||||
state <= 'b0;
|
||||
state[CONFIG] <= 1'b1;
|
||||
end
|
||||
else state <= state_nx;
|
||||
|
||||
@ -159,11 +195,11 @@ module axis_addr
|
||||
state_nx = 'b0;
|
||||
|
||||
case (1'b1)
|
||||
state[IDLE] : begin
|
||||
if (cfg_valid) begin
|
||||
state[CONFIG] : begin
|
||||
if ( ~cfg_buf_empty) begin
|
||||
state_nx[SETUP] = 1'b1;
|
||||
end
|
||||
else state_nx[IDLE] = 1'b1;
|
||||
else state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
state[SETUP] : begin
|
||||
if (cfg_done & burst_en) begin
|
||||
@ -190,15 +226,24 @@ module axis_addr
|
||||
else state_nx[LAST] = 1'b1;
|
||||
end
|
||||
state[DONE] : begin
|
||||
state_nx[IDLE] = 1'b1;
|
||||
state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
default : begin
|
||||
state_nx[IDLE] = 1'b1;
|
||||
state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
assign axi_aaddr = axi_address;
|
||||
|
||||
assign axi_alen = state[BURST] ? (BURST_LENGTH-1) : last_nb;
|
||||
|
||||
assign axi_avalid = state[BURST] | state[LAST];
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`undef MIN
|
||||
|
||||
`endif // `ifndef _axis_addr_
|
||||
|
@ -50,7 +50,7 @@ module axis_addr_tb;
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
localparam CFG_DWIDTH = 32;
|
||||
localparam WIDTH_RATIO = 16;
|
||||
localparam AXI_LEN_WIDTH = 8;
|
||||
localparam AXI_ADDR_WIDTH = 32;
|
||||
@ -67,10 +67,10 @@ module axis_addr_tb;
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_address;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_valid;
|
||||
wire cfg_ready;
|
||||
reg [CFG_DWIDTH-1:0] cfg_address;
|
||||
reg [CFG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_val;
|
||||
wire cfg_rdy;
|
||||
|
||||
reg axi_aready;
|
||||
wire [AXI_ADDR_WIDTH-1:0] axi_aaddr;
|
||||
@ -83,7 +83,7 @@ module axis_addr_tb;
|
||||
*/
|
||||
|
||||
axis_addr #(
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
@ -94,8 +94,8 @@ module axis_addr_tb;
|
||||
|
||||
.cfg_address (cfg_address),
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_ready (cfg_ready),
|
||||
.cfg_val (cfg_val),
|
||||
.cfg_rdy (cfg_rdy),
|
||||
|
||||
.axi_aready (axi_aready),
|
||||
.axi_aaddr (axi_aaddr),
|
||||
@ -116,8 +116,8 @@ module axis_addr_tb;
|
||||
"\t%d\t%d\t%b\t%b",
|
||||
cfg_address,
|
||||
cfg_length,
|
||||
cfg_valid,
|
||||
cfg_ready,
|
||||
cfg_val,
|
||||
cfg_rdy,
|
||||
|
||||
"\t%d\t%d\t%b\t%b",
|
||||
axi_aaddr,
|
||||
@ -169,7 +169,7 @@ module axis_addr_tb;
|
||||
|
||||
cfg_address = 'b0;
|
||||
cfg_length = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
cfg_val = 'b0;
|
||||
|
||||
axi_aready = 'b0;
|
||||
//end init
|
||||
@ -193,11 +193,11 @@ module axis_addr_tb;
|
||||
cfg_address <= 255;
|
||||
//cfg_length <= 8;
|
||||
cfg_length <= 256+256+64;
|
||||
cfg_valid <= 1'b1;
|
||||
cfg_val <= 1'b1;
|
||||
@(negedge clk);
|
||||
cfg_address <= 'b0;
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
cfg_val <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
|
@ -1,107 +0,0 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_deserializer
|
||||
*
|
||||
* Description:
|
||||
* Deserializes multiple 'up' flow bus data words into a single, larger
|
||||
* 'down' data words. Arranges them first to the right and moving left.
|
||||
*
|
||||
* If there is a pause in the incoming 'up' stream the values already written
|
||||
* into the larger 'down' word will stay until enough 'up' data has been sent
|
||||
* in to complete the 'down' word unless a 'up_last' signal forces the down
|
||||
* transfer. The module will stall when the down_ready flag deasserts.
|
||||
*
|
||||
* Testbench:
|
||||
* axis_deserializer_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Thu Nov 6 17:29:58 EST 2014
|
||||
*
|
||||
* Authors:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_deserializer_ `define _axis_deserializer_
|
||||
|
||||
module axis_deserializer
|
||||
#(parameter
|
||||
DATA_NB = 2,
|
||||
DATA_WIDTH = 8)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
output up_ready,
|
||||
input up_valid,
|
||||
input [DATA_WIDTH-1:0] up_data,
|
||||
input up_last,
|
||||
|
||||
input down_ready,
|
||||
output reg down_valid,
|
||||
output reg [(DATA_WIDTH*DATA_NB)-1:0] down_data,
|
||||
output reg down_last
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_deserializer' with %0d words\n", DATA_NB);
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
genvar ii;
|
||||
|
||||
wire [DATA_NB:0] token_i;
|
||||
reg [DATA_NB-1:0] token;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign token_i = {token, token[DATA_NB-1]};
|
||||
|
||||
assign up_ready = down_ready;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) down_last <= 1'b0;
|
||||
else if (down_ready) down_last <= up_last;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) down_valid <= 1'b0;
|
||||
else if (down_ready) begin
|
||||
down_valid <= (token[DATA_NB-1] & up_valid) | up_last;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst | (down_ready & up_last)) token <= 'b1;
|
||||
else if (down_ready & up_valid) begin
|
||||
token <= token_i[0 +: DATA_NB];
|
||||
end
|
||||
|
||||
|
||||
generate
|
||||
for (ii=0; ii<DATA_NB; ii=ii+1) begin : CONCAT_
|
||||
|
||||
always @(posedge clk)
|
||||
if (down_ready & token[ii]) begin
|
||||
down_data[ii*DATA_WIDTH +: DATA_WIDTH] <= up_data;
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_deserializer_
|
231
hdl/axis/axis_gbox.v
Normal file
231
hdl/axis/axis_gbox.v
Normal file
@ -0,0 +1,231 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_gbox
|
||||
*
|
||||
* Description:
|
||||
* The AXIS Gear Box will serializes or deserializes a stream of data
|
||||
* depending of the relative widths of the streams. Is only one register deep.
|
||||
*
|
||||
* Serializes the 'up' data word into multiple smaller 'down' data words. The
|
||||
* module will stall when the dn_rdy flag deasserts.
|
||||
*
|
||||
* Deserializes multiple 'up' flow bus data words into a single, larger
|
||||
* 'down' data words. Arranges them first to the right and moving left. If
|
||||
* there is a pause in the incoming 'up' stream the values already written
|
||||
* into the larger 'down' word will stay until enough 'up' data has been sent
|
||||
* in to complete the 'down' word unless a 'up_last' signal forces the down
|
||||
* transfer. The module will stall when the 'dn_rdy' flag deasserts.
|
||||
*
|
||||
* Testbench:
|
||||
* axis_gbox_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Sun Jun 3 17:57:34 PDT 2018
|
||||
*
|
||||
* Authors:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_gbox_
|
||||
`define _axis_gbox_
|
||||
|
||||
|
||||
module axis_gbox
|
||||
#(parameter
|
||||
DATA_UP_WIDTH = 2,
|
||||
DATA_DN_WIDTH = 8)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [DATA_UP_WIDTH-1:0] up_data,
|
||||
input up_last,
|
||||
input up_val,
|
||||
output up_rdy,
|
||||
|
||||
output [DATA_DN_WIDTH-1:0] dn_data,
|
||||
output dn_last,
|
||||
output dn_val,
|
||||
input dn_rdy
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial begin
|
||||
$display("<axis_gbox> up words: %d, dn word: %d\n"
|
||||
, DATA_UP_WIDTH
|
||||
, DATA_DN_WIDTH
|
||||
);
|
||||
`endif
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
generate
|
||||
if (DATA_UP_WIDTH == DATA_DN_WIDTH) begin : PASS_
|
||||
|
||||
reg [DATA_DN_WIDTH-1:0] dn_data_i;
|
||||
reg dn_last_i;
|
||||
reg dn_val_i;
|
||||
|
||||
|
||||
assign up_rdy = dn_rdy;
|
||||
|
||||
assign dn_data = dn_data_i;
|
||||
|
||||
assign dn_last = dn_last_i & dn_rdy;
|
||||
|
||||
assign dn_val = dn_val_i & dn_rdy;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (dn_rdy & up_val) begin
|
||||
dn_data_i <= up_data;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) dn_last_i <= 1'b0;
|
||||
else if (dn_rdy) dn_last_i <= up_val & up_last;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) dn_val_i <= 1'b0;
|
||||
else if (dn_rdy) dn_val_i <= up_val;
|
||||
|
||||
|
||||
end
|
||||
else if (DATA_UP_WIDTH > DATA_DN_WIDTH) begin : SERIAL_
|
||||
|
||||
localparam DATA_NB = DATA_UP_WIDTH/DATA_DN_WIDTH;
|
||||
|
||||
|
||||
wire [2*DATA_NB-1:0] token_nx;
|
||||
reg [DATA_NB-1:0] token;
|
||||
reg [DATA_UP_WIDTH-1:0] serial_data;
|
||||
reg [DATA_NB-1:0] serial_last;
|
||||
reg [DATA_NB-1:0] serial_valid;
|
||||
|
||||
|
||||
assign up_rdy = dn_rdy & token[0];
|
||||
|
||||
assign dn_data = serial_data[0 +: DATA_DN_WIDTH];
|
||||
|
||||
assign dn_last = serial_last[0] & dn_rdy;
|
||||
|
||||
assign dn_val = serial_valid[0] & dn_rdy;
|
||||
|
||||
assign token_nx = {token, token};
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) token <= 'b1;
|
||||
else if (dn_rdy) begin
|
||||
|
||||
if ( ~token[0] | (up_rdy & up_val)) begin
|
||||
token <= token_nx[DATA_NB-1 +: DATA_NB];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (dn_rdy) begin
|
||||
|
||||
serial_data <= serial_data >> DATA_DN_WIDTH;
|
||||
if (up_rdy & up_val) begin
|
||||
serial_data <= up_data;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) serial_last <= 'b0;
|
||||
else if (dn_rdy) begin
|
||||
|
||||
serial_last <= serial_last >> 1;
|
||||
if (up_rdy & up_val & up_last) begin
|
||||
serial_last <= 'b0;
|
||||
serial_last[DATA_NB-1] <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) serial_valid <= 'b0;
|
||||
else if (dn_rdy) begin
|
||||
|
||||
serial_valid <= serial_valid >> 1;
|
||||
if (up_rdy & up_val) begin
|
||||
serial_valid <= {DATA_NB{1'b1}};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
else if (DATA_UP_WIDTH < DATA_DN_WIDTH) begin : DSERIAL_
|
||||
|
||||
localparam DATA_NB = DATA_DN_WIDTH/DATA_UP_WIDTH;
|
||||
|
||||
integer ii;
|
||||
wire [2*DATA_NB-1:0] token_nx;
|
||||
reg [DATA_NB-1:0] token;
|
||||
reg [DATA_DN_WIDTH-1:0] dn_data_i;
|
||||
reg dn_last_i;
|
||||
reg dn_val_i;
|
||||
|
||||
|
||||
assign up_rdy = dn_rdy;
|
||||
|
||||
assign dn_data = dn_data_i;
|
||||
|
||||
assign dn_last = dn_last_i & dn_rdy;
|
||||
|
||||
assign dn_val = dn_val_i & dn_rdy;
|
||||
|
||||
assign token_nx = {token, token};
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) dn_last_i <= 1'b0;
|
||||
else if (dn_rdy) begin
|
||||
dn_last_i <= up_val & up_last;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) dn_val_i <= 1'b0;
|
||||
else if (dn_rdy) begin
|
||||
dn_val_i <= (token[DATA_NB-1] & up_val) | (up_val & up_last);
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst | (dn_rdy & up_val & up_last)) token <= 'b1;
|
||||
else if (dn_rdy & up_val) begin
|
||||
token <= token_nx[DATA_NB-1 +: DATA_NB];
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
for (ii=0; ii<DATA_NB; ii=ii+1) begin
|
||||
if (dn_rdy & token[ii]) begin
|
||||
dn_data_i[ii*DATA_UP_WIDTH +: DATA_UP_WIDTH] <= up_data;
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_gbox_
|
@ -1,9 +1,9 @@
|
||||
/**
|
||||
* Testbench for:
|
||||
* axis_deserializer
|
||||
* axis_gbox
|
||||
*
|
||||
* Created:
|
||||
* Thu Nov 6 17:29:45 EST 2014
|
||||
* Sun Jun 3 17:57:21 PDT 2018
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
@ -15,9 +15,9 @@
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_deserializer.v"
|
||||
`include "axis_gbox.v"
|
||||
|
||||
module axis_deserializer_tb;
|
||||
module axis_gbox_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
@ -50,15 +50,22 @@ module axis_deserializer_tb;
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam DATA_NB = 3;
|
||||
localparam DATA_WIDTH = 8;
|
||||
localparam DATA_UP_WIDTH = 24;
|
||||
localparam DATA_DN_WIDTH = 8;
|
||||
localparam DATA_NB = DATA_UP_WIDTH/DATA_DN_WIDTH;
|
||||
|
||||
//localparam DATA_UP_WIDTH = 8;
|
||||
//localparam DATA_DN_WIDTH = 24;
|
||||
//localparam DATA_NB = DATA_DN_WIDTH/DATA_UP_WIDTH;
|
||||
|
||||
localparam STREAM_LENGTH = 256;
|
||||
localparam STREAM_WIDTH = (DATA_DN_WIDTH < DATA_UP_WIDTH) ?
|
||||
DATA_DN_WIDTH : DATA_UP_WIDTH ;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial begin
|
||||
$display("Testbench for unit 'axis_deserializer' data width: %d, nb: %d",
|
||||
DATA_WIDTH, DATA_NB);
|
||||
$display("Testbench for unit 'axis_gbox' data up width: %d, down: %d",
|
||||
DATA_UP_WIDTH, DATA_DN_WIDTH);
|
||||
end
|
||||
`endif
|
||||
|
||||
@ -67,41 +74,41 @@ module axis_deserializer_tb;
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
reg rst;
|
||||
|
||||
reg [DATA_WIDTH-1:0] up_data;
|
||||
reg up_valid;
|
||||
wire up_ready;
|
||||
reg up_last;
|
||||
wire [DATA_UP_WIDTH-1:0] up_data;
|
||||
reg up_last;
|
||||
wire up_val;
|
||||
wire up_rdy;
|
||||
|
||||
wire [DATA_NB*DATA_WIDTH-1:0] down_data;
|
||||
wire down_valid;
|
||||
reg down_ready;
|
||||
wire down_last;
|
||||
wire [DATA_DN_WIDTH-1:0] dn_data;
|
||||
wire dn_last;
|
||||
wire dn_val;
|
||||
reg dn_rdy;
|
||||
|
||||
reg [DATA_WIDTH-1:0] stream [0:STREAM_LENGTH-1];
|
||||
integer cnt;
|
||||
reg [STREAM_WIDTH-1:0] stream [0:STREAM_LENGTH-1];
|
||||
integer cnt;
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_deserializer #(
|
||||
.DATA_NB (DATA_NB),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
axis_gbox #(
|
||||
.DATA_UP_WIDTH (DATA_UP_WIDTH),
|
||||
.DATA_DN_WIDTH (DATA_DN_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.up_data (up_data),
|
||||
.up_valid (up_valid),
|
||||
.up_ready (up_ready),
|
||||
.up_last (up_last),
|
||||
.up_val (up_val),
|
||||
.up_rdy (up_rdy),
|
||||
|
||||
.down_data (down_data),
|
||||
.down_valid (down_valid),
|
||||
.down_ready (down_ready),
|
||||
.down_last (down_last)
|
||||
.dn_data (dn_data),
|
||||
.dn_last (dn_last),
|
||||
.dn_val (dn_val),
|
||||
.dn_rdy (dn_rdy)
|
||||
);
|
||||
|
||||
|
||||
@ -114,20 +121,21 @@ module axis_deserializer_tb;
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
"\tu: %x",
|
||||
up_data,
|
||||
up_valid,
|
||||
up_ready,
|
||||
|
||||
"\tv %b\tr %b\tl %b",
|
||||
up_val,
|
||||
up_rdy,
|
||||
up_last,
|
||||
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
down_data,
|
||||
down_valid,
|
||||
down_ready,
|
||||
down_last,
|
||||
dn_data,
|
||||
dn_val,
|
||||
dn_rdy,
|
||||
dn_last,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
@ -135,7 +143,7 @@ module axis_deserializer_tb;
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\tu_d",
|
||||
"\tu_v",
|
||||
"\t\tu_v",
|
||||
"\tu_r",
|
||||
"\tu_l",
|
||||
|
||||
@ -152,25 +160,17 @@ module axis_deserializer_tb;
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
assign up_data = {stream[cnt]+4'd2, stream[cnt]+4'd1, stream[cnt]};
|
||||
//assign up_data = stream[cnt];
|
||||
|
||||
assign up_val = 1'b1;
|
||||
|
||||
always @(posedge clk)
|
||||
if (up_ready) begin
|
||||
if (up_rdy & up_val) begin
|
||||
cnt <= cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
up_data <= stream[cnt];
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
up_valid <= 1'b0;
|
||||
|
||||
if (up_ready) begin
|
||||
up_valid <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
@ -178,12 +178,12 @@ module axis_deserializer_tb;
|
||||
rst = 0;
|
||||
|
||||
up_last = 'b0;
|
||||
|
||||
down_ready = 'b0;
|
||||
dn_rdy = 'b0;
|
||||
|
||||
cnt = 0;
|
||||
repeat (STREAM_LENGTH) begin
|
||||
stream[cnt] = cnt + 1;
|
||||
stream[cnt] = (DATA_NB*cnt)+1;
|
||||
//stream[cnt] = cnt + 1;
|
||||
cnt = cnt + 1;
|
||||
end
|
||||
cnt = 0;
|
||||
@ -203,9 +203,10 @@ module axis_deserializer_tb;
|
||||
$display("test continuous ready");
|
||||
`endif
|
||||
|
||||
down_ready <= 1'b1;
|
||||
@(negedge clk);
|
||||
dn_rdy <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
dn_rdy <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
@ -213,41 +214,28 @@ module axis_deserializer_tb;
|
||||
$display("test non-continuous ready");
|
||||
`endif
|
||||
|
||||
down_ready <= 1'b1;
|
||||
dn_rdy <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
dn_rdy <= 1'b0;
|
||||
up_last <= 1'b1;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
dn_rdy <= 1'b1;
|
||||
repeat (3) @(negedge clk);
|
||||
up_last <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
dn_rdy <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
dn_rdy <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
dn_rdy <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
dn_rdy <= 1'b1;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test continuous ready with unalined last");
|
||||
`endif
|
||||
|
||||
cnt <= 0;
|
||||
repeat(3) @(negedge clk);
|
||||
|
||||
down_ready <= 1'b1;
|
||||
//repeat(15) @(negedge clk);
|
||||
repeat(16) @(negedge clk);
|
||||
//repeat(17) @(negedge clk);
|
||||
//repeat(18) @(negedge clk);
|
||||
up_last <= 1'b1;
|
||||
dn_rdy <= 1'b0;
|
||||
@(negedge clk);
|
||||
up_last <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
dn_rdy <= 1'b1;
|
||||
@(negedge clk);
|
||||
dn_rdy <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* the large words that are returned by the AXI into a system stream.
|
||||
*
|
||||
* Test bench:
|
||||
* axis_write_tb.v
|
||||
* axis_read_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 17:23:00 EST 2014
|
||||
@ -15,7 +15,8 @@
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_read_ `define _axis_read_
|
||||
`ifndef _axis_read_
|
||||
`define _axis_read_
|
||||
|
||||
|
||||
`include "axis_addr.v"
|
||||
@ -23,14 +24,16 @@
|
||||
|
||||
module axis_read
|
||||
#(parameter
|
||||
BUF_CFG_AWIDTH = 5,
|
||||
BUF_AWIDTH = 9,
|
||||
|
||||
CONFIG_ID = 1,
|
||||
CONFIG_ADDR = 23,
|
||||
CONFIG_DATA = 24,
|
||||
CONFIG_AWIDTH = 5,
|
||||
CONFIG_DWIDTH = 32,
|
||||
CFG_ID = 1,
|
||||
CFG_ADDR = 23,
|
||||
CFG_DATA = 24,
|
||||
CFG_AWIDTH = 5,
|
||||
CFG_DWIDTH = 32,
|
||||
|
||||
AXI_ID_WIDTH = 8,
|
||||
AXI_LEN_WIDTH = 8,
|
||||
AXI_ADDR_WIDTH = 32,
|
||||
AXI_DATA_WIDTH = 32,
|
||||
@ -38,16 +41,19 @@ module axis_read
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_AWIDTH-1:0] cfg_addr,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_data,
|
||||
input [CFG_AWIDTH-1:0] cfg_addr,
|
||||
input [CFG_DWIDTH-1:0] cfg_data,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
|
||||
input axi_arready,
|
||||
output reg [AXI_ID_WIDTH-1:0] axi_arid,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_araddr,
|
||||
output [AXI_LEN_WIDTH-1:0] axi_arlen,
|
||||
output axi_arvalid,
|
||||
input axi_arready,
|
||||
|
||||
input [AXI_DATA_WIDTH-1:0] axi_rdata,
|
||||
input axi_rlast,
|
||||
input axi_rvalid,
|
||||
output axi_rready,
|
||||
|
||||
@ -61,14 +67,13 @@ module axis_read
|
||||
*/
|
||||
|
||||
localparam WIDTH_RATIO = AXI_DATA_WIDTH/DATA_WIDTH;
|
||||
localparam CONFIG_NB = 2;
|
||||
localparam STORE_WIDTH = CONFIG_DWIDTH*CONFIG_NB;
|
||||
localparam CFG_NB = 2;
|
||||
localparam STORE_WIDTH = CFG_DWIDTH*CFG_NB;
|
||||
|
||||
localparam
|
||||
C_IDLE = 0,
|
||||
C_CONFIG = 1,
|
||||
C_WAIT = 2,
|
||||
C_ENABLE = 3;
|
||||
C_STALL = 2;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
@ -81,23 +86,19 @@ module axis_read
|
||||
*/
|
||||
|
||||
|
||||
reg [3:0] c_state;
|
||||
reg [3:0] c_state_nx;
|
||||
reg [2:0] c_state;
|
||||
reg [2:0] c_state_nx;
|
||||
|
||||
wire cfg_addr_ready;
|
||||
wire cfg_data_ready;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr_r;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data_r;
|
||||
reg cfg_valid_r;
|
||||
wire [STORE_WIDTH+CONFIG_DWIDTH-1:0] cfg_store_i;
|
||||
wire [STORE_WIDTH+CFG_DWIDTH-1:0] cfg_store_i;
|
||||
reg [STORE_WIDTH-1:0] cfg_store;
|
||||
reg [7:0] cfg_cnt;
|
||||
wire cfg_done;
|
||||
|
||||
wire [CONFIG_DWIDTH-1:0] start_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_address;
|
||||
wire [CONFIG_DWIDTH-1:0] str_length;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
wire [CFG_DWIDTH-1:0] cfg_address;
|
||||
wire [CFG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_enable;
|
||||
wire id_valid;
|
||||
wire addressed;
|
||||
@ -108,30 +109,21 @@ module axis_read
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_store_i = {cfg_store, cfg_data_r};
|
||||
assign cfg_store_i = {cfg_store, cfg_data};
|
||||
|
||||
assign start_addr = cfg_store[CONFIG_DWIDTH +: CONFIG_DWIDTH];
|
||||
assign cfg_address = cfg_store[CFG_DWIDTH +: CFG_DWIDTH];
|
||||
|
||||
assign str_length = cfg_store[0 +: CONFIG_DWIDTH];
|
||||
assign cfg_length = cfg_store[0 +: CFG_DWIDTH];
|
||||
|
||||
assign id_valid = (CONFIG_ID == cfg_data_r);
|
||||
assign id_valid = (CFG_ID == cfg_data);
|
||||
|
||||
assign addressed = (CONFIG_ADDR == cfg_addr_r) & cfg_valid_r;
|
||||
assign addressed = (CFG_ADDR == cfg_addr) & cfg_valid;
|
||||
|
||||
assign axis_data = (CONFIG_DATA == cfg_addr_r) & cfg_valid_r;
|
||||
assign axis_data = (CFG_DATA == cfg_addr) & cfg_valid;
|
||||
|
||||
assign cfg_ready = ~c_state[C_STALL];
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_valid_r <= 1'b0;
|
||||
else cfg_valid_r <= cfg_valid;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk) begin
|
||||
cfg_addr_r <= cfg_addr;
|
||||
cfg_data_r <= cfg_data;
|
||||
end
|
||||
assign cfg_done = ((CFG_NB-1) == cfg_cnt);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
@ -144,22 +136,25 @@ module axis_read
|
||||
cfg_cnt <= 'b0;
|
||||
|
||||
if (c_state[C_CONFIG]) begin
|
||||
cfg_cnt <= cfg_cnt + {7'b0, axis_data};
|
||||
cfg_cnt <= cfg_cnt + {7'd0, axis_data};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_enable <= 1'b0;
|
||||
else cfg_enable <= c_state[C_ENABLE];
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (c_state[C_ENABLE]) begin
|
||||
cfg_address <= start_addr;
|
||||
cfg_length <= str_length;
|
||||
if (rst) cfg_enable <= 1'b0;
|
||||
else if ( ~c_state[C_STALL]) begin
|
||||
cfg_enable <= c_state[C_CONFIG] & axis_data & cfg_done;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
axi_arid <= {AXI_ID_WIDTH{1'b0}};
|
||||
end
|
||||
else if (axi_arvalid && axi_arready) begin
|
||||
axi_arid <= axi_arid + {{(AXI_ID_WIDTH-1){1'b0}}, 1'b1};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
@ -181,19 +176,19 @@ module axis_read
|
||||
else c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
c_state[C_CONFIG] : begin
|
||||
if (axis_data & ((CONFIG_NB-1) <= cfg_cnt)) begin
|
||||
c_state_nx[C_WAIT] = 1'b1;
|
||||
if (axis_data & cfg_done & cfg_addr_ready & cfg_data_ready) begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
else if (axis_data & cfg_done) begin
|
||||
c_state_nx[C_STALL] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_CONFIG] = 1'b1;
|
||||
end
|
||||
c_state[C_WAIT] : begin
|
||||
c_state[C_STALL] : begin
|
||||
if (cfg_addr_ready & cfg_data_ready) begin
|
||||
c_state_nx[C_ENABLE] = 1'b1;
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_WAIT] = 1'b1;
|
||||
end
|
||||
c_state[C_ENABLE] : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
else c_state_nx[C_STALL] = 1'b1;
|
||||
end
|
||||
default : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
@ -203,9 +198,11 @@ module axis_read
|
||||
|
||||
|
||||
axis_addr #(
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.BUF_CFG_AWIDTH (BUF_CFG_AWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH))
|
||||
@ -215,8 +212,8 @@ module axis_read
|
||||
|
||||
.cfg_address (cfg_address),
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_addr_ready),
|
||||
.cfg_val (cfg_enable & ~c_state[C_STALL]),
|
||||
.cfg_rdy (cfg_addr_ready),
|
||||
|
||||
.axi_aready (axi_arready),
|
||||
.axi_aaddr (axi_araddr),
|
||||
@ -226,9 +223,10 @@ module axis_read
|
||||
|
||||
|
||||
axis_read_data #(
|
||||
.BUF_CFG_AWIDTH (BUF_CFG_AWIDTH),
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
axis_read_data_ (
|
||||
@ -236,10 +234,11 @@ module axis_read
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_data_ready),
|
||||
.cfg_val (cfg_enable & ~c_state[C_STALL]),
|
||||
.cfg_rdy (cfg_data_ready),
|
||||
|
||||
.axi_rdata (axi_rdata),
|
||||
.axi_rlast (axi_rlast),
|
||||
.axi_rvalid (axi_rvalid),
|
||||
.axi_rready (axi_rready),
|
||||
|
||||
|
@ -14,33 +14,35 @@
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_read_data_ `define _axis_read_data_
|
||||
`ifndef _axis_read_data_
|
||||
`define _axis_read_data_
|
||||
|
||||
|
||||
`include "fifo_simple.v"
|
||||
`include "axis_serializer.v"
|
||||
`include "axis_gbox.v"
|
||||
|
||||
module axis_read_data
|
||||
#(parameter
|
||||
BUF_CFG_AWIDTH = 5,
|
||||
BUF_AWIDTH = 9,
|
||||
CONFIG_DWIDTH = 32,
|
||||
WIDTH_RATIO = 2,
|
||||
CFG_DWIDTH = 32,
|
||||
|
||||
AXI_DATA_WIDTH = 64,
|
||||
DATA_WIDTH = 32)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
input [CFG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_val,
|
||||
output cfg_rdy,
|
||||
|
||||
input [AXI_DATA_WIDTH-1:0] axi_rdata,
|
||||
input axi_rlast,
|
||||
input axi_rvalid,
|
||||
output axi_rready,
|
||||
|
||||
output [DATA_WIDTH-1:0] data,
|
||||
output reg valid,
|
||||
output valid,
|
||||
input ready
|
||||
);
|
||||
|
||||
@ -49,10 +51,10 @@ module axis_read_data
|
||||
*/
|
||||
|
||||
localparam
|
||||
IDLE = 0,
|
||||
ACTIVE = 1,
|
||||
WAIT = 2,
|
||||
DONE = 3;
|
||||
RESET = 0,
|
||||
CONFIG = 1,
|
||||
SET = 2,
|
||||
ACTIVE = 3;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
@ -67,84 +69,122 @@ module axis_read_data
|
||||
reg [3:0] state;
|
||||
reg [3:0] state_nx;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] str_cnt;
|
||||
reg [CONFIG_DWIDTH-1:0] str_length;
|
||||
wire cfg_buf_pop;
|
||||
wire cfg_buf_full;
|
||||
wire cfg_buf_empty;
|
||||
wire [CFG_DWIDTH-1:0] cfg_buf_length;
|
||||
|
||||
wire buf_pop;
|
||||
wire buf_full;
|
||||
reg [CFG_DWIDTH-1:0] str_cnt;
|
||||
reg [CFG_DWIDTH-1:0] str_length;
|
||||
|
||||
wire buf_afull;
|
||||
wire buf_empty;
|
||||
wire [DATA_WIDTH-1:0] buf_data;
|
||||
wire buf_valid;
|
||||
wire [AXI_DATA_WIDTH-1:0] buf_data;
|
||||
wire buf_last;
|
||||
reg buf_en;
|
||||
wire buf_pop;
|
||||
wire buf_rdy;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_ready = state[IDLE];
|
||||
|
||||
assign buf_pop = ~buf_empty & ready;
|
||||
assign cfg_rdy = ~cfg_buf_full;
|
||||
|
||||
|
||||
fifo_simple #(
|
||||
.DATA_WIDTH (CFG_DWIDTH),
|
||||
.ADDR_WIDTH (BUF_CFG_AWIDTH))
|
||||
cfg_buffer_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.count (),
|
||||
.empty (cfg_buf_empty),
|
||||
.empty_a (),
|
||||
.full (cfg_buf_full),
|
||||
.full_a (),
|
||||
|
||||
.push_data (cfg_length),
|
||||
.push (cfg_val),
|
||||
|
||||
.pop_data (cfg_buf_length),
|
||||
.pop (cfg_buf_pop)
|
||||
);
|
||||
|
||||
assign cfg_buf_pop = ~cfg_buf_empty & state[CONFIG];
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
str_length <= cfg_length-1;
|
||||
if (state[SET]) begin
|
||||
str_length <= cfg_buf_length-1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) str_cnt <= 'b0;
|
||||
else if (buf_pop) begin
|
||||
if (state[SET]) str_cnt <= 'b0;
|
||||
else if (valid) begin
|
||||
str_cnt <= str_cnt + 'b1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) valid <= 1'b0;
|
||||
else valid <= buf_pop & state[ACTIVE];
|
||||
assign axi_rready = ~buf_afull;
|
||||
|
||||
|
||||
fifo_simple #(
|
||||
.DATA_WIDTH (DATA_WIDTH),
|
||||
.DATA_WIDTH (1+AXI_DATA_WIDTH),
|
||||
.ADDR_WIDTH (BUF_AWIDTH))
|
||||
buffer_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
.rst (rst),
|
||||
|
||||
.count (),
|
||||
.empty (buf_empty),
|
||||
.empty_a (),
|
||||
.full (buf_full),
|
||||
.full_a (),
|
||||
.full (),
|
||||
.full_a (buf_afull),
|
||||
|
||||
.push_data (buf_data),
|
||||
.push (buf_valid),
|
||||
.push_data ({axi_rlast, axi_rdata}),
|
||||
.push (axi_rvalid & axi_rready),
|
||||
|
||||
.pop_data (data),
|
||||
.pop_data ({buf_last, buf_data}),
|
||||
.pop (buf_pop)
|
||||
);
|
||||
|
||||
|
||||
axis_serializer #(
|
||||
.DATA_NB (WIDTH_RATIO),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
assign buf_pop = ~buf_en | buf_rdy;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) buf_en <= 1'b0;
|
||||
else if (buf_pop) buf_en <= ~buf_empty;
|
||||
|
||||
|
||||
axis_gbox #(
|
||||
.DATA_UP_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_DN_WIDTH (DATA_WIDTH))
|
||||
serializer_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
.rst (state[RESET]),
|
||||
|
||||
.up_data (axi_rdata),
|
||||
.up_valid (axi_rvalid),
|
||||
.up_ready (axi_rready),
|
||||
.up_data (buf_data),
|
||||
.up_last (buf_last),
|
||||
.up_val (buf_en),
|
||||
.up_rdy (buf_rdy),
|
||||
|
||||
.down_data (buf_data),
|
||||
.down_valid (buf_valid),
|
||||
.down_ready ( ~buf_full)
|
||||
.dn_data (data),
|
||||
.dn_last (),
|
||||
.dn_val (valid),
|
||||
.dn_rdy (ready & state[ACTIVE])
|
||||
);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
state <= 'b0;
|
||||
state[IDLE] <= 1'b1;
|
||||
state <= 'b0;
|
||||
state[RESET] <= 1'b1;
|
||||
end
|
||||
else state <= state_nx;
|
||||
|
||||
@ -153,32 +193,36 @@ module axis_read_data
|
||||
state_nx = 'b0;
|
||||
|
||||
case (1'b1)
|
||||
state[IDLE] : begin
|
||||
if (cfg_valid) begin
|
||||
state_nx[ACTIVE] = 1'b1;
|
||||
state[RESET] : begin
|
||||
state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
state[CONFIG] : begin
|
||||
if ( ~cfg_buf_empty) begin
|
||||
state_nx[SET] = 1'b1;
|
||||
end
|
||||
else state_nx[IDLE] = 1'b1;
|
||||
else state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
state[SET] : begin
|
||||
state_nx[ACTIVE] = 1'b1;
|
||||
end
|
||||
state[ACTIVE] : begin
|
||||
if (buf_pop & (str_length == str_cnt)) begin
|
||||
state_nx[WAIT] = 1'b1;
|
||||
if (valid & (str_length == str_cnt) & ~(buf_en & buf_rdy)) begin
|
||||
// serializer may contain leftover data
|
||||
state_nx[RESET] = 1'b1;
|
||||
end
|
||||
else if (valid & (str_length == str_cnt) & (buf_en & buf_rdy)) begin
|
||||
// serializer contains valid data
|
||||
state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
else state_nx[ACTIVE] = 1'b1;
|
||||
end
|
||||
state[WAIT] : begin
|
||||
state_nx[DONE] = 1'b1;
|
||||
end
|
||||
state[DONE] : begin
|
||||
state_nx[IDLE] = 1'b1;
|
||||
end
|
||||
default : begin
|
||||
state_nx[IDLE] = 1'b1;
|
||||
state_nx[RESET] = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_read_data_
|
||||
|
@ -53,8 +53,7 @@ module axis_read_data_tb;
|
||||
localparam STREAM_LENGTH = (256*8*2)-4;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
localparam WIDTH_RATIO = 8;
|
||||
localparam CFG_DWIDTH = 32;
|
||||
localparam AXI_DATA_WIDTH = 256;
|
||||
localparam DATA_WIDTH = 32;
|
||||
|
||||
@ -70,11 +69,12 @@ module axis_read_data_tb;
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_valid;
|
||||
wire cfg_ready;
|
||||
reg [CFG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_val;
|
||||
wire cfg_rdy;
|
||||
|
||||
reg [AXI_DATA_WIDTH-1:0] axi_rdata;
|
||||
reg axi_rlast;
|
||||
reg axi_rvalid;
|
||||
wire axi_rready;
|
||||
|
||||
@ -89,8 +89,7 @@ module axis_read_data_tb;
|
||||
|
||||
axis_read_data #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
@ -99,10 +98,11 @@ module axis_read_data_tb;
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_ready (cfg_ready),
|
||||
.cfg_val (cfg_val),
|
||||
.cfg_rdy (cfg_rdy),
|
||||
|
||||
.axi_rdata (axi_rdata),
|
||||
.axi_rlast (axi_rlast),
|
||||
.axi_rvalid (axi_rvalid),
|
||||
.axi_rready (axi_rready),
|
||||
|
||||
@ -121,13 +121,14 @@ module axis_read_data_tb;
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\t%d\t%b",
|
||||
"\t%d\t%b\t%b",
|
||||
cfg_length,
|
||||
cfg_valid,
|
||||
cfg_ready,
|
||||
cfg_val,
|
||||
cfg_rdy,
|
||||
|
||||
"\t%x\t%b\t%b",
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
axi_rdata,
|
||||
axi_rlast,
|
||||
axi_rvalid,
|
||||
axi_rready,
|
||||
|
||||
@ -152,7 +153,8 @@ module axis_read_data_tb;
|
||||
"\tc_r",
|
||||
|
||||
"\t\t\t\t\t\tr_d",
|
||||
"\t\t\tr_v",
|
||||
"\t\t\t\tr_l",
|
||||
"\tr_v",
|
||||
"\tr_r",
|
||||
|
||||
"\t\ts_d",
|
||||
@ -173,9 +175,10 @@ module axis_read_data_tb;
|
||||
rst = 0;
|
||||
|
||||
cfg_length = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
cfg_val = 'b0;
|
||||
|
||||
axi_rdata = 'b0;
|
||||
axi_rlast = 'b0;
|
||||
axi_rvalid = 'b0;
|
||||
|
||||
ready = 'b0;
|
||||
@ -198,11 +201,11 @@ module axis_read_data_tb;
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= 10;
|
||||
cfg_valid <= 1'b1;
|
||||
cfg_val <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
cfg_val <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
@ -217,10 +220,12 @@ module axis_read_data_tb;
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_rdata <= {32'd9, 32'd8, 32'd7, 32'd6, 32'd5, 32'd4, 32'd3, 32'd2};
|
||||
axi_rlast <= 1'b1;
|
||||
while ( ~axi_rready) @(negedge clk);
|
||||
axi_rvalid <= 1'b1;
|
||||
@(negedge clk);
|
||||
axi_rdata <= 'b0;
|
||||
axi_rlast <= 1'b0;
|
||||
axi_rvalid <= 1'b0;
|
||||
|
||||
repeat(15) @(negedge clk);
|
||||
|
@ -54,11 +54,11 @@ module axis_read_tb;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
|
||||
localparam CONFIG_ID = 1;
|
||||
localparam CONFIG_ADDR = 23;
|
||||
localparam CONFIG_DATA = 24;
|
||||
localparam CONFIG_AWIDTH = 5;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
localparam CFG_ID = 1;
|
||||
localparam CFG_ADDR = 23;
|
||||
localparam CFG_DATA = 24;
|
||||
localparam CFG_AWIDTH = 5;
|
||||
localparam CFG_DWIDTH = 32;
|
||||
|
||||
localparam AXI_ADDR_WIDTH = 32;
|
||||
localparam AXI_DATA_WIDTH = 256;
|
||||
@ -76,8 +76,8 @@ module axis_read_tb;
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data;
|
||||
reg [CFG_AWIDTH-1:0] cfg_addr;
|
||||
reg [CFG_DWIDTH-1:0] cfg_data;
|
||||
reg cfg_valid;
|
||||
|
||||
reg axi_arready;
|
||||
@ -101,11 +101,11 @@ module axis_read_tb;
|
||||
axis_read #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.CFG_ID (CFG_ID),
|
||||
.CFG_ADDR (CFG_ADDR),
|
||||
.CFG_DATA (CFG_DATA),
|
||||
.CFG_AWIDTH (CFG_AWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
@ -235,8 +235,8 @@ module axis_read_tb;
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_addr <= CFG_ADDR;
|
||||
cfg_data <= CFG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
@ -246,7 +246,7 @@ module axis_read_tb;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
// memory address
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
@ -257,7 +257,7 @@ module axis_read_tb;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
// length of flow stream
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
@ -302,17 +302,17 @@ module axis_read_tb;
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_addr <= CFG_ADDR;
|
||||
cfg_data <= CFG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 20;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
@ -370,17 +370,17 @@ module axis_read_tb;
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_addr <= CFG_ADDR;
|
||||
cfg_data <= CFG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 255;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= STREAM_LENGTH;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
@ -1,117 +0,0 @@
|
||||
/**
|
||||
* Module:
|
||||
* axis_serializer
|
||||
*
|
||||
* Description:
|
||||
* Serializes the 'up' flow bus data word into multiple smaller 'down' data
|
||||
* words. The module will stall when the down_ready flag deasserts.
|
||||
*
|
||||
* Testbench:
|
||||
* axis_serializer_tb.v
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 11:50:04 EST 2014
|
||||
*
|
||||
* Authors:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_serializer_ `define _axis_serializer_
|
||||
|
||||
|
||||
module axis_serializer
|
||||
#(parameter
|
||||
DATA_NB = 2,
|
||||
DATA_WIDTH = 8)
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
output up_ready,
|
||||
input up_valid,
|
||||
input [(DATA_WIDTH*DATA_NB)-1:0] up_data,
|
||||
|
||||
input down_ready,
|
||||
output reg down_valid,
|
||||
output reg [DATA_WIDTH-1:0] down_data
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
initial $display("\using 'axis_serializer' with %0d words\n", DATA_NB);
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* Internal signals
|
||||
*/
|
||||
|
||||
wire [2*DATA_NB-1:0] token_nx;
|
||||
reg [DATA_NB-1:0] token;
|
||||
reg [DATA_NB:0] serial_valid;
|
||||
reg [(DATA_WIDTH*DATA_NB)-1:0] serial_data;
|
||||
wire serial_start;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign up_ready = down_ready & token[0];
|
||||
|
||||
assign serial_start = |(token >> 1);
|
||||
|
||||
assign token_nx = {token, token};
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) token <= 'b1;
|
||||
else if (down_ready) begin
|
||||
|
||||
if (serial_start | (up_ready & up_valid)) begin
|
||||
token <= token_nx[DATA_NB-1 +: DATA_NB];
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (down_ready) begin
|
||||
|
||||
serial_data <= serial_data >> DATA_WIDTH;
|
||||
if (up_ready & up_valid) begin
|
||||
serial_data <= up_data;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) serial_valid <= 'b0;
|
||||
else if (down_ready) begin
|
||||
|
||||
serial_valid <= {serial_valid[0 +: DATA_NB], 1'b0};
|
||||
if (up_ready & up_valid) begin
|
||||
serial_valid <= {serial_valid[0 +: DATA_NB], 1'b1};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (down_ready) begin
|
||||
down_data <= serial_data[0 +: DATA_WIDTH];
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) down_valid <= 1'b0;
|
||||
else if (down_ready) begin
|
||||
down_valid <= |(serial_valid[0 +: DATA_NB]);
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_serializer_
|
@ -1,243 +0,0 @@
|
||||
/**
|
||||
* Testbench for:
|
||||
* axis_serializer
|
||||
*
|
||||
* Created:
|
||||
* Fri Nov 7 11:49:55 EST 2014
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_serializer.v"
|
||||
|
||||
module axis_serializer_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
localparam DATA_NB = 3;
|
||||
localparam DATA_WIDTH = 8;
|
||||
|
||||
localparam STREAM_LENGTH = 256;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial begin
|
||||
$display("Testbench for unit 'axis_serializer' data width: %d, nb: %d",
|
||||
DATA_WIDTH, DATA_NB);
|
||||
end
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [DATA_NB*DATA_WIDTH-1:0] up_data;
|
||||
wire up_valid;
|
||||
wire up_ready;
|
||||
|
||||
wire [DATA_WIDTH-1:0] down_data;
|
||||
wire down_valid;
|
||||
reg down_ready;
|
||||
|
||||
reg [DATA_WIDTH-1:0] stream [0:STREAM_LENGTH-1];
|
||||
integer cnt;
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_serializer #(
|
||||
.DATA_NB (DATA_NB),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.up_data (up_data),
|
||||
.up_valid (up_valid),
|
||||
.up_ready (up_ready),
|
||||
|
||||
.down_data (down_data),
|
||||
.down_valid (down_valid),
|
||||
.down_ready (down_ready)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
"\tu2: %d\tu1: %d\tu0: %d",
|
||||
up_data[2*DATA_WIDTH+:DATA_WIDTH],
|
||||
up_data[1*DATA_WIDTH+:DATA_WIDTH],
|
||||
up_data[0*DATA_WIDTH+:DATA_WIDTH],
|
||||
|
||||
"\tv %b\tr %b",
|
||||
up_valid,
|
||||
up_ready,
|
||||
|
||||
"\t%d\t%b\t%b",
|
||||
down_data,
|
||||
down_valid,
|
||||
down_ready,
|
||||
|
||||
"\t%b",
|
||||
uut.token,
|
||||
|
||||
"\t%x\t%b",
|
||||
uut.serial_data,
|
||||
uut.serial_valid,
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
"\tu2_d",
|
||||
"\tu1_d",
|
||||
"\tu0_d",
|
||||
|
||||
"\tu_v",
|
||||
"\tu_r",
|
||||
|
||||
"\td_d",
|
||||
"\td_v",
|
||||
"\td_r",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
//assign up_valid = up_ready;
|
||||
assign up_valid = 1'b1;
|
||||
|
||||
always @(posedge clk)
|
||||
if (up_ready & up_valid) begin
|
||||
cnt <= cnt + 1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
up_data <= {stream[cnt]+4'd2, stream[cnt]+4'd1, stream[cnt]};
|
||||
|
||||
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
|
||||
down_ready = 'b0;
|
||||
|
||||
cnt = 0;
|
||||
repeat (STREAM_LENGTH) begin
|
||||
stream[cnt] = (DATA_NB*cnt)+1;
|
||||
cnt = cnt + 1;
|
||||
end
|
||||
cnt = 0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
repeat(6) @(negedge clk);
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test continuous ready");
|
||||
`endif
|
||||
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("test non-continuous ready");
|
||||
`endif
|
||||
|
||||
down_ready <= 1'b1;
|
||||
repeat(20) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
repeat(5) @(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b1;
|
||||
@(negedge clk);
|
||||
down_ready <= 1'b0;
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
@ -3,7 +3,7 @@
|
||||
* axis_write
|
||||
*
|
||||
* Description:
|
||||
* The axis_write takes a system stream an translate it to the axi data
|
||||
* The axis_write takes a system stream and translates it to the axi data
|
||||
* channel protocol.
|
||||
*
|
||||
* Test bench:
|
||||
@ -15,7 +15,8 @@
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_write_ `define _axis_write_
|
||||
`ifndef _axis_write_
|
||||
`define _axis_write_
|
||||
|
||||
|
||||
`include "axis_addr.v"
|
||||
@ -23,14 +24,16 @@
|
||||
|
||||
module axis_write
|
||||
#(parameter
|
||||
BUF_CFG_AWIDTH = 5,
|
||||
BUF_AWIDTH = 9,
|
||||
|
||||
CONFIG_ID = 1,
|
||||
CONFIG_ADDR = 23,
|
||||
CONFIG_DATA = 24,
|
||||
CONFIG_AWIDTH = 5,
|
||||
CONFIG_DWIDTH = 32,
|
||||
CFG_ID = 1,
|
||||
CFG_ADDR = 23,
|
||||
CFG_DATA = 24,
|
||||
CFG_AWIDTH = 5,
|
||||
CFG_DWIDTH = 32,
|
||||
|
||||
AXI_ID_WIDTH = 8,
|
||||
AXI_LEN_WIDTH = 8,
|
||||
AXI_ADDR_WIDTH = 32,
|
||||
AXI_DATA_WIDTH = 32,
|
||||
@ -38,17 +41,20 @@ module axis_write
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_AWIDTH-1:0] cfg_addr,
|
||||
input [CONFIG_DWIDTH-1:0] cfg_data,
|
||||
input [CFG_AWIDTH-1:0] cfg_addr,
|
||||
input [CFG_DWIDTH-1:0] cfg_data,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
|
||||
input axi_awready,
|
||||
output reg [AXI_ID_WIDTH-1:0] axi_awid,
|
||||
output [AXI_ADDR_WIDTH-1:0] axi_awaddr,
|
||||
output [AXI_LEN_WIDTH-1:0] axi_awlen,
|
||||
output axi_awvalid,
|
||||
input axi_awready,
|
||||
|
||||
output axi_wlast,
|
||||
output reg [AXI_ID_WIDTH-1:0] axi_wid,
|
||||
output [AXI_DATA_WIDTH-1:0] axi_wdata,
|
||||
output axi_wlast,
|
||||
output axi_wvalid,
|
||||
input axi_wready,
|
||||
|
||||
@ -62,14 +68,13 @@ module axis_write
|
||||
*/
|
||||
|
||||
localparam WIDTH_RATIO = AXI_DATA_WIDTH/DATA_WIDTH;
|
||||
localparam CONFIG_NB = 2;
|
||||
localparam STORE_WIDTH = CONFIG_DWIDTH*CONFIG_NB;
|
||||
localparam CFG_NB = 2;
|
||||
localparam STORE_WIDTH = CFG_DWIDTH*CFG_NB;
|
||||
|
||||
localparam
|
||||
C_IDLE = 0,
|
||||
C_CONFIG = 1,
|
||||
C_WAIT = 2,
|
||||
C_ENABLE = 3;
|
||||
C_STALL = 2;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
@ -82,23 +87,19 @@ module axis_write
|
||||
*/
|
||||
|
||||
|
||||
reg [3:0] c_state;
|
||||
reg [3:0] c_state_nx;
|
||||
reg [2:0] c_state;
|
||||
reg [2:0] c_state_nx;
|
||||
|
||||
wire cfg_addr_ready;
|
||||
wire cfg_data_ready;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr_r;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data_r;
|
||||
reg cfg_valid_r;
|
||||
wire [STORE_WIDTH+CONFIG_DWIDTH-1:0] cfg_store_i;
|
||||
wire [STORE_WIDTH+CFG_DWIDTH-1:0] cfg_store_i;
|
||||
reg [STORE_WIDTH-1:0] cfg_store;
|
||||
reg [7:0] cfg_cnt;
|
||||
wire cfg_done;
|
||||
|
||||
wire [CONFIG_DWIDTH-1:0] start_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_address;
|
||||
wire [CONFIG_DWIDTH-1:0] str_length;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
wire [CFG_DWIDTH-1:0] cfg_address;
|
||||
wire [CFG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_enable;
|
||||
wire id_valid;
|
||||
wire addressed;
|
||||
@ -109,30 +110,21 @@ module axis_write
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_store_i = {cfg_store, cfg_data_r};
|
||||
assign cfg_store_i = {cfg_store, cfg_data};
|
||||
|
||||
assign start_addr = cfg_store[CONFIG_DWIDTH +: CONFIG_DWIDTH];
|
||||
assign cfg_address = cfg_store[CFG_DWIDTH +: CFG_DWIDTH];
|
||||
|
||||
assign str_length = cfg_store[0 +: CONFIG_DWIDTH];
|
||||
assign cfg_length = cfg_store[0 +: CFG_DWIDTH];
|
||||
|
||||
assign id_valid = (CONFIG_ID == cfg_data_r);
|
||||
assign id_valid = (CFG_ID == cfg_data);
|
||||
|
||||
assign addressed = (CONFIG_ADDR == cfg_addr_r) & cfg_valid_r;
|
||||
assign addressed = (CFG_ADDR == cfg_addr) & cfg_valid;
|
||||
|
||||
assign axis_data = (CONFIG_DATA == cfg_addr_r) & cfg_valid_r;
|
||||
assign axis_data = (CFG_DATA == cfg_addr) & cfg_valid;
|
||||
|
||||
assign cfg_ready = ~c_state[C_STALL];
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_valid_r <= 1'b0;
|
||||
else cfg_valid_r <= cfg_valid;
|
||||
|
||||
|
||||
// register for improved timing
|
||||
always @(posedge clk) begin
|
||||
cfg_addr_r <= cfg_addr;
|
||||
cfg_data_r <= cfg_data;
|
||||
end
|
||||
assign cfg_done = ((CFG_NB-1) == cfg_cnt);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
@ -151,16 +143,28 @@ module axis_write
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) cfg_enable <= 1'b0;
|
||||
else cfg_enable <= c_state[C_ENABLE];
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (c_state[C_ENABLE]) begin
|
||||
cfg_address <= start_addr;
|
||||
cfg_length <= str_length;
|
||||
if (rst) cfg_enable <= 1'b0;
|
||||
else if ( ~c_state[C_STALL]) begin
|
||||
cfg_enable <= c_state[C_CONFIG] & axis_data & cfg_done;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
axi_awid <= {AXI_ID_WIDTH{1'b0}};
|
||||
end
|
||||
else if (axi_awvalid && axi_awready) begin
|
||||
axi_awid <= axi_awid + {{(AXI_ID_WIDTH-1){1'b0}}, 1'b1};
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
axi_wid <= {AXI_ID_WIDTH{1'b0}};
|
||||
end
|
||||
else if (axi_wvalid & axi_wready & axi_wlast) begin
|
||||
axi_wid <= axi_wid + {{(AXI_ID_WIDTH-1){1'b0}}, 1'b1};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
@ -182,19 +186,19 @@ module axis_write
|
||||
else c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
c_state[C_CONFIG] : begin
|
||||
if (axis_data & ((CONFIG_NB-1) <= cfg_cnt)) begin
|
||||
c_state_nx[C_WAIT] = 1'b1;
|
||||
if (axis_data & cfg_done & cfg_addr_ready & cfg_data_ready) begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
else if (axis_data & cfg_done) begin
|
||||
c_state_nx[C_STALL] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_CONFIG] = 1'b1;
|
||||
end
|
||||
c_state[C_WAIT] : begin
|
||||
c_state[C_STALL] : begin
|
||||
if (cfg_addr_ready & cfg_data_ready) begin
|
||||
c_state_nx[C_ENABLE] = 1'b1;
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
end
|
||||
else c_state_nx[C_WAIT] = 1'b1;
|
||||
end
|
||||
c_state[C_ENABLE] : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
else c_state_nx[C_STALL] = 1'b1;
|
||||
end
|
||||
default : begin
|
||||
c_state_nx[C_IDLE] = 1'b1;
|
||||
@ -204,9 +208,11 @@ module axis_write
|
||||
|
||||
|
||||
axis_addr #(
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.BUF_CFG_AWIDTH (BUF_CFG_AWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH))
|
||||
@ -216,8 +222,8 @@ module axis_write
|
||||
|
||||
.cfg_address (cfg_address),
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_addr_ready),
|
||||
.cfg_val (cfg_enable & ~c_state[C_STALL]),
|
||||
.cfg_rdy (cfg_addr_ready),
|
||||
|
||||
.axi_aready (axi_awready),
|
||||
.axi_aaddr (axi_awaddr),
|
||||
@ -227,10 +233,11 @@ module axis_write
|
||||
|
||||
|
||||
axis_write_data #(
|
||||
.BUF_CFG_AWIDTH (BUF_CFG_AWIDTH),
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
@ -239,8 +246,8 @@ module axis_write
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_enable),
|
||||
.cfg_ready (cfg_data_ready),
|
||||
.cfg_val (cfg_enable & ~c_state[C_STALL]),
|
||||
.cfg_rdy (cfg_data_ready),
|
||||
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wdata (axi_wdata),
|
||||
|
@ -14,17 +14,18 @@
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _axis_write_data_ `define _axis_write_data_
|
||||
`ifndef _axis_write_data_
|
||||
`define _axis_write_data_
|
||||
|
||||
|
||||
`include "fifo_simple.v"
|
||||
`include "axis_deserializer.v"
|
||||
`include "axis_gbox.v"
|
||||
|
||||
module axis_write_data
|
||||
#(parameter
|
||||
BUF_CFG_AWIDTH = 5,
|
||||
BUF_AWIDTH = 9,
|
||||
CONFIG_DWIDTH = 32,
|
||||
WIDTH_RATIO = 2,
|
||||
CFG_DWIDTH = 32,
|
||||
CONVERT_SHIFT = 3,
|
||||
|
||||
AXI_LEN_WIDTH = 8,
|
||||
@ -33,9 +34,9 @@ module axis_write_data
|
||||
(input clk,
|
||||
input rst,
|
||||
|
||||
input [CONFIG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_valid,
|
||||
output cfg_ready,
|
||||
input [CFG_DWIDTH-1:0] cfg_length,
|
||||
input cfg_val,
|
||||
output cfg_rdy,
|
||||
|
||||
output axi_wlast,
|
||||
output [AXI_DATA_WIDTH-1:0] axi_wdata,
|
||||
@ -55,10 +56,10 @@ module axis_write_data
|
||||
localparam BURST_LAST = (1<<BURST_WIDTH)-1;
|
||||
|
||||
localparam
|
||||
IDLE = 0,
|
||||
ACTIVE = 1,
|
||||
WAIT = 2,
|
||||
DONE = 3;
|
||||
CONFIG = 0,
|
||||
SET = 1,
|
||||
LOAD = 2,
|
||||
ACTIVE = 3;
|
||||
|
||||
|
||||
`ifdef VERBOSE
|
||||
@ -73,58 +74,66 @@ module axis_write_data
|
||||
reg [3:0] state;
|
||||
reg [3:0] state_nx;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] str_cnt;
|
||||
reg [CONFIG_DWIDTH-1:0] str_length;
|
||||
wire cfg_buf_pop;
|
||||
wire cfg_buf_full;
|
||||
wire cfg_buf_empty;
|
||||
wire [CFG_DWIDTH-1:0] cfg_buf_length;
|
||||
|
||||
reg [CFG_DWIDTH-1:0] str_cnt;
|
||||
reg [CFG_DWIDTH-1:0] str_next;
|
||||
reg [CFG_DWIDTH-1:0] str_length;
|
||||
|
||||
wire [BUF_AWIDTH:0] buf_count;
|
||||
wire buf_pop;
|
||||
wire buf_empty;
|
||||
|
||||
reg deser_done;
|
||||
reg deser_last;
|
||||
wire [DATA_WIDTH-1:0] deser_data;
|
||||
reg deser_valid;
|
||||
reg deser_en;
|
||||
wire deser_rdy;
|
||||
|
||||
/**
|
||||
* Implementation
|
||||
*/
|
||||
|
||||
assign cfg_ready = state[IDLE];
|
||||
|
||||
assign buf_pop = ~buf_empty & axi_wready;
|
||||
assign cfg_rdy = ~cfg_buf_full;
|
||||
|
||||
|
||||
fifo_simple #(
|
||||
.DATA_WIDTH (CFG_DWIDTH),
|
||||
.ADDR_WIDTH (BUF_CFG_AWIDTH))
|
||||
cfg_buffer_ (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
|
||||
.count (),
|
||||
.empty (cfg_buf_empty),
|
||||
.empty_a (),
|
||||
.full (cfg_buf_full),
|
||||
.full_a (),
|
||||
|
||||
.push_data (cfg_length),
|
||||
.push (cfg_val),
|
||||
|
||||
.pop_data (cfg_buf_length),
|
||||
.pop (cfg_buf_pop)
|
||||
);
|
||||
|
||||
assign cfg_buf_pop = ~cfg_buf_empty & state[CONFIG];
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (cfg_valid) begin
|
||||
str_length <= cfg_length-1;
|
||||
if (state[SET]) begin
|
||||
str_length <= cfg_buf_length-'b1;
|
||||
end
|
||||
|
||||
|
||||
// use axi_wready as a stall signal
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) deser_valid <= 1'b0;
|
||||
else if (axi_wready) deser_valid <= buf_pop;
|
||||
|
||||
|
||||
// half way mark ready flag
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) ready <= 1'b0;
|
||||
else ready <= ~|(buf_count[BUF_AWIDTH:BUF_AWIDTH-1]);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) str_cnt <= 'b0;
|
||||
else if (axi_wready & buf_pop) begin
|
||||
str_cnt <= str_cnt + 'd1;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[IDLE]) deser_last <= 1'b0;
|
||||
else if (axi_wready) begin
|
||||
// trigger on last word in stream or last word in burst
|
||||
deser_last <= buf_pop &
|
||||
((str_length == str_cnt) | (BURST_LAST == str_cnt[0 +: BURST_WIDTH]));
|
||||
end
|
||||
if (rst) ready <= 1'b0;
|
||||
else ready <= ~|(buf_count[BUF_AWIDTH:BUF_AWIDTH-1]);
|
||||
|
||||
|
||||
fifo_simple #(
|
||||
@ -132,7 +141,7 @@ module axis_write_data
|
||||
.ADDR_WIDTH (BUF_AWIDTH))
|
||||
buffer_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
.rst (rst),
|
||||
|
||||
.count (buf_count),
|
||||
.empty (buf_empty),
|
||||
@ -148,29 +157,78 @@ module axis_write_data
|
||||
);
|
||||
|
||||
|
||||
axis_deserializer #(
|
||||
.DATA_NB (WIDTH_RATIO),
|
||||
.DATA_WIDTH (DATA_WIDTH))
|
||||
assign buf_pop = ~deser_en | (deser_rdy & state[ACTIVE]);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) deser_en <= 1'b0;
|
||||
else if (buf_pop) deser_en <= ~buf_empty;
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[LOAD]) begin
|
||||
deser_done <= str_next[0] & (str_length == {CFG_DWIDTH{1'b0}});
|
||||
end
|
||||
else if (buf_pop) begin
|
||||
// trigger on last word in stream
|
||||
deser_done <= ~buf_empty & (str_length == str_cnt);
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[LOAD]) begin
|
||||
deser_last <= str_next[0] &
|
||||
((str_length == {CFG_DWIDTH{1'b0}}) | (BURST_LAST == {BURST_WIDTH{1'b0}}));
|
||||
end
|
||||
else if (buf_pop) begin
|
||||
// trigger on last word in stream or last word in burst
|
||||
deser_last <= ~buf_empty &
|
||||
((str_length == str_cnt) | (BURST_LAST == str_cnt[0 +: BURST_WIDTH]));
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (state[LOAD]) begin
|
||||
str_cnt <= str_next;
|
||||
end
|
||||
else if (buf_pop) begin
|
||||
str_cnt <= str_cnt + {{CFG_DWIDTH-1{1'b0}}, ~buf_empty};
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) str_next <= 'b0;
|
||||
else if (deser_en & deser_rdy & deser_done & state[ACTIVE]) begin
|
||||
// if buffer is not empty when one stream is done it means the 1st
|
||||
// word of the next stream is already in the pipeline
|
||||
|
||||
str_next <= {{CFG_DWIDTH-1{1'b0}}, ~buf_empty};
|
||||
end
|
||||
|
||||
|
||||
axis_gbox #(
|
||||
.DATA_UP_WIDTH (DATA_WIDTH),
|
||||
.DATA_DN_WIDTH (AXI_DATA_WIDTH))
|
||||
deser_ (
|
||||
.clk (clk),
|
||||
.rst (state[IDLE]),
|
||||
.rst (rst),
|
||||
|
||||
.up_data (deser_data),
|
||||
.up_valid (deser_valid),
|
||||
.up_ready (),
|
||||
.up_last (deser_last),
|
||||
.up_val (deser_en & state[ACTIVE]),
|
||||
.up_rdy (deser_rdy),
|
||||
|
||||
.down_data (axi_wdata),
|
||||
.down_valid (axi_wvalid),
|
||||
.down_ready (axi_wready),
|
||||
.down_last (axi_wlast)
|
||||
.dn_data (axi_wdata),
|
||||
.dn_last (axi_wlast),
|
||||
.dn_val (axi_wvalid),
|
||||
.dn_rdy (axi_wready)
|
||||
);
|
||||
|
||||
|
||||
always @(posedge clk)
|
||||
if (rst) begin
|
||||
state <= 'b0;
|
||||
state[IDLE] <= 1'b1;
|
||||
state <= 'b0;
|
||||
state[CONFIG] <= 1'b1;
|
||||
end
|
||||
else state <= state_nx;
|
||||
|
||||
@ -179,34 +237,32 @@ module axis_write_data
|
||||
state_nx = 'b0;
|
||||
|
||||
case (1'b1)
|
||||
state[IDLE] : begin
|
||||
if (cfg_valid) begin
|
||||
state_nx[ACTIVE] = 1'b1;
|
||||
state[CONFIG] : begin
|
||||
if ( ~cfg_buf_empty) begin
|
||||
state_nx[SET] = 1'b1;
|
||||
end
|
||||
else state_nx[IDLE] = 1'b1;
|
||||
else state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
state[SET] : begin
|
||||
state_nx[LOAD] = 1'b1;
|
||||
end
|
||||
state[LOAD] : begin
|
||||
state_nx[ACTIVE] = 1'b1;
|
||||
end
|
||||
state[ACTIVE] : begin
|
||||
if (axi_wready & buf_pop & (str_length == str_cnt)) begin
|
||||
state_nx[WAIT] = 1'b1;
|
||||
if (deser_en & deser_rdy & deser_done) begin
|
||||
state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
else state_nx[ACTIVE] = 1'b1;
|
||||
end
|
||||
state[WAIT] : begin
|
||||
if (axi_wready & axi_wlast) begin
|
||||
state_nx[DONE] = 1'b1;
|
||||
end
|
||||
else state_nx[WAIT] = 1'b1;
|
||||
end
|
||||
state[DONE] : begin
|
||||
state_nx[IDLE] = 1'b1;
|
||||
end
|
||||
default : begin
|
||||
state_nx[IDLE] = 1'b1;
|
||||
state_nx[CONFIG] = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`endif // `ifndef _axis_write_data_
|
||||
|
@ -53,7 +53,7 @@ module axis_write_data_tb;
|
||||
localparam STREAM_LENGTH = (256*8*2)-4;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
localparam CFG_DWIDTH = 32;
|
||||
|
||||
localparam AXI_LEN_WIDTH = 4;
|
||||
localparam AXI_DATA_WIDTH = 64;
|
||||
@ -73,11 +73,9 @@ module axis_write_data_tb;
|
||||
|
||||
reg rst;
|
||||
|
||||
wire done;
|
||||
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_valid;
|
||||
wire cfg_ready;
|
||||
reg [CFG_DWIDTH-1:0] cfg_length;
|
||||
reg cfg_val;
|
||||
wire cfg_rdy;
|
||||
|
||||
wire axi_wlast;
|
||||
wire [AXI_DATA_WIDTH-1:0] axi_wdata;
|
||||
@ -95,8 +93,7 @@ module axis_write_data_tb;
|
||||
|
||||
axis_write_data #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.WIDTH_RATIO (WIDTH_RATIO),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
.CONVERT_SHIFT ($clog2(WIDTH_RATIO)),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
@ -107,8 +104,8 @@ module axis_write_data_tb;
|
||||
.rst (rst),
|
||||
|
||||
.cfg_length (cfg_length),
|
||||
.cfg_valid (cfg_valid),
|
||||
.cfg_ready (cfg_ready),
|
||||
.cfg_val (cfg_val),
|
||||
.cfg_rdy (cfg_rdy),
|
||||
|
||||
.axi_wlast (axi_wlast),
|
||||
.axi_wdata (axi_wdata),
|
||||
@ -132,8 +129,8 @@ module axis_write_data_tb;
|
||||
|
||||
"\t%d\t%b\t%b",
|
||||
cfg_length,
|
||||
cfg_valid,
|
||||
cfg_ready,
|
||||
cfg_val,
|
||||
cfg_rdy,
|
||||
|
||||
"\t%x\t%b\t%b\t%b",
|
||||
axi_wdata,
|
||||
@ -149,6 +146,9 @@ module axis_write_data_tb;
|
||||
"\t%b",
|
||||
uut.state,
|
||||
|
||||
"\t%d",
|
||||
uut.str_cnt,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
@ -184,7 +184,7 @@ module axis_write_data_tb;
|
||||
rst = 0;
|
||||
|
||||
cfg_length = 'b0;
|
||||
cfg_valid = 'b0;
|
||||
cfg_val = 'b0;
|
||||
|
||||
axi_wready = 'b0;
|
||||
data = 'b0;
|
||||
@ -208,11 +208,11 @@ module axis_write_data_tb;
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
cfg_val <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
cfg_val <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
@ -285,11 +285,11 @@ module axis_write_data_tb;
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
cfg_val <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
cfg_val <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
@ -337,11 +337,19 @@ module axis_write_data_tb;
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_length <= STREAM_LENGTH;
|
||||
cfg_valid <= 1'b1;
|
||||
cfg_val <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 1;
|
||||
cfg_val <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 1;
|
||||
cfg_val <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_length <= 'b0;
|
||||
cfg_valid <= 1'b0;
|
||||
cfg_val <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
|
||||
@ -355,7 +363,7 @@ module axis_write_data_tb;
|
||||
axi_wready <= 1'b1;
|
||||
repeat(15) @(negedge clk);
|
||||
|
||||
repeat (STREAM_LENGTH) begin
|
||||
repeat (STREAM_LENGTH+1) begin
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
@ -363,6 +371,11 @@ module axis_write_data_tb;
|
||||
valid <= 1'b0;
|
||||
|
||||
|
||||
repeat(15) @(negedge clk);
|
||||
data <= data + 1;
|
||||
valid <= 1'b1;
|
||||
@(negedge clk);
|
||||
valid <= 1'b0;
|
||||
repeat(15) @(negedge clk);
|
||||
axi_wready <= 1'b0;
|
||||
|
||||
|
@ -54,11 +54,11 @@ module axis_write_tb;
|
||||
|
||||
localparam BUF_AWIDTH = 4;
|
||||
|
||||
localparam CONFIG_ID = 1;
|
||||
localparam CONFIG_ADDR = 23;
|
||||
localparam CONFIG_DATA = 24;
|
||||
localparam CONFIG_AWIDTH = 5;
|
||||
localparam CONFIG_DWIDTH = 32;
|
||||
localparam CFG_ID = 1;
|
||||
localparam CFG_ADDR = 23;
|
||||
localparam CFG_DATA = 24;
|
||||
localparam CFG_AWIDTH = 5;
|
||||
localparam CFG_DWIDTH = 32;
|
||||
|
||||
localparam AXI_LEN_WIDTH = 2;
|
||||
localparam AXI_ADDR_WIDTH = 32;
|
||||
@ -77,8 +77,8 @@ module axis_write_tb;
|
||||
|
||||
reg rst;
|
||||
|
||||
reg [CONFIG_AWIDTH-1:0] cfg_addr;
|
||||
reg [CONFIG_DWIDTH-1:0] cfg_data;
|
||||
reg [CFG_AWIDTH-1:0] cfg_addr;
|
||||
reg [CFG_DWIDTH-1:0] cfg_data;
|
||||
reg cfg_valid;
|
||||
|
||||
reg axi_awready;
|
||||
@ -103,11 +103,11 @@ module axis_write_tb;
|
||||
axis_write #(
|
||||
.BUF_AWIDTH (BUF_AWIDTH),
|
||||
|
||||
.CONFIG_ID (CONFIG_ID),
|
||||
.CONFIG_ADDR (CONFIG_ADDR),
|
||||
.CONFIG_DATA (CONFIG_DATA),
|
||||
.CONFIG_AWIDTH (CONFIG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
||||
.CFG_ID (CFG_ID),
|
||||
.CFG_ADDR (CFG_ADDR),
|
||||
.CFG_DATA (CFG_DATA),
|
||||
.CFG_AWIDTH (CFG_AWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
|
||||
.AXI_LEN_WIDTH (AXI_LEN_WIDTH),
|
||||
.AXI_ADDR_WIDTH (AXI_ADDR_WIDTH),
|
||||
@ -240,8 +240,8 @@ module axis_write_tb;
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_addr <= CFG_ADDR;
|
||||
cfg_data <= CFG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
@ -250,7 +250,7 @@ module axis_write_tb;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
@ -260,7 +260,7 @@ module axis_write_tb;
|
||||
cfg_valid <= 1'b0;
|
||||
repeat(5) @(negedge clk);
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
@ -320,17 +320,17 @@ module axis_write_tb;
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_addr <= CFG_ADDR;
|
||||
cfg_data <= CFG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 4;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 8;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
@ -375,17 +375,17 @@ module axis_write_tb;
|
||||
`endif
|
||||
|
||||
repeat(5) @(negedge clk);
|
||||
cfg_addr <= CONFIG_ADDR;
|
||||
cfg_data <= CONFIG_ID;
|
||||
cfg_addr <= CFG_ADDR;
|
||||
cfg_data <= CFG_ID;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= 255;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
||||
cfg_addr <= CONFIG_DATA;
|
||||
cfg_addr <= CFG_DATA;
|
||||
cfg_data <= STREAM_LENGTH;
|
||||
cfg_valid <= 1'b1;
|
||||
@(negedge clk)
|
||||
|
@ -1,4 +1,5 @@
|
||||
`ifndef _axi4lite_cfg_ `define _axi4lite_cfg_
|
||||
`ifndef _axi4lite_cfg_
|
||||
`define _axi4lite_cfg_
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
|
@ -14,7 +14,8 @@
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
`ifndef _fifo_simple_ `define _fifo_simple_
|
||||
`ifndef _fifo_simple_
|
||||
`define _fifo_simple_
|
||||
|
||||
|
||||
module fifo_simple
|
||||
|
@ -210,12 +210,12 @@ module axis_loopback #(
|
||||
|
||||
axis #(
|
||||
.BUF_AWIDTH (9),
|
||||
.CONFIG_ID_RD (1),
|
||||
.CONFIG_ID_WR (2),
|
||||
.CONFIG_ADDR (CFG_AXIS_ADDR),
|
||||
.CONFIG_DATA (CFG_AXIS_DATA),
|
||||
.CONFIG_AWIDTH (CFG_AWIDTH),
|
||||
.CONFIG_DWIDTH (CFG_DWIDTH),
|
||||
.CFG_ID_RD (1),
|
||||
.CFG_ID_WR (2),
|
||||
.CFG_ADDR (CFG_AXIS_ADDR),
|
||||
.CFG_DATA (CFG_AXIS_DATA),
|
||||
.CFG_AWIDTH (CFG_AWIDTH),
|
||||
.CFG_DWIDTH (CFG_DWIDTH),
|
||||
.STREAM_WIDTH (SYS_DWIDTH),
|
||||
.AXI_ID_WIDTH (C_M00_AXI_ID_WIDTH),
|
||||
.AXI_LEN_WIDTH (C_M00_AXI_BURST_LEN),
|
||||
|
132
hdl/top/axis_loopback_tb.v
Normal file
132
hdl/top/axis_loopback_tb.v
Normal file
@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Testbench:
|
||||
* axis_loopback
|
||||
*
|
||||
* Created:
|
||||
* Sun Jun 3 14:42:30 PDT 2018
|
||||
*
|
||||
* Author:
|
||||
* Berin Martini (berin.martini@gmail.com)
|
||||
*/
|
||||
|
||||
`timescale 1ns/10ps
|
||||
|
||||
`define TB_VERBOSE
|
||||
//`define VERBOSE
|
||||
|
||||
|
||||
`include "axis_loopback.v"
|
||||
|
||||
module axis_loopback_tb;
|
||||
|
||||
/**
|
||||
* Clock and control functions
|
||||
*/
|
||||
|
||||
// Generate a clk
|
||||
reg clk;
|
||||
always #1 clk = !clk;
|
||||
|
||||
// End of simulation event definition
|
||||
event end_trigger;
|
||||
always @(end_trigger) $finish;
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
// Display header information
|
||||
initial #1 display_header();
|
||||
always @(end_trigger) display_header();
|
||||
|
||||
// And strobe signals at each clk
|
||||
always @(posedge clk) display_signals();
|
||||
`endif
|
||||
|
||||
// initial begin
|
||||
// $dumpfile("result.vcd"); // Waveform file
|
||||
// $dumpvars;
|
||||
// end
|
||||
|
||||
|
||||
/**
|
||||
* Local parameters
|
||||
*/
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
initial $display("Testbench for unit 'axis_loopback'");
|
||||
`endif
|
||||
|
||||
|
||||
/**
|
||||
* signals, registers and wires
|
||||
*/
|
||||
|
||||
reg rst;
|
||||
|
||||
|
||||
/**
|
||||
* Unit under test
|
||||
*/
|
||||
|
||||
axis_loopback
|
||||
uut (
|
||||
.clk (clk),
|
||||
.rst_n ( ~rst)
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Wave form display
|
||||
*/
|
||||
|
||||
task display_signals;
|
||||
$display(
|
||||
"%d\t%d",
|
||||
$time, rst,
|
||||
|
||||
);
|
||||
|
||||
endtask // display_signals
|
||||
|
||||
task display_header;
|
||||
$display(
|
||||
"\t\ttime\trst",
|
||||
|
||||
);
|
||||
endtask
|
||||
|
||||
|
||||
/**
|
||||
* Testbench program
|
||||
*/
|
||||
|
||||
initial begin
|
||||
// init values
|
||||
clk = 0;
|
||||
rst = 0;
|
||||
//end init
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("RESET");
|
||||
`endif
|
||||
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b1;
|
||||
repeat(6) @(negedge clk);
|
||||
rst <= 1'b0;
|
||||
@(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("wait");
|
||||
`endif
|
||||
|
||||
repeat(10) @(negedge clk);
|
||||
|
||||
|
||||
`ifdef TB_VERBOSE
|
||||
$display("END");
|
||||
`endif
|
||||
-> end_trigger;
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user