mirror of
https://github.com/bmartini/zynq-axis.git
synced 2024-09-05 19:19:27 +08:00
Since these signals are never used, they do not need to be propagated past the axis.v module.
249 lines
6.2 KiB
Verilog
249 lines
6.2 KiB
Verilog
/**
|
|
* Module:
|
|
* axis_read
|
|
*
|
|
* Description:
|
|
* The axis_read is configured to read an area of memory and then converts
|
|
* the large words that are returned by the AXI into a system stream.
|
|
*
|
|
* Test bench:
|
|
* axis_write_tb.v
|
|
*
|
|
* Created:
|
|
* Fri Nov 7 17:23:00 EST 2014
|
|
*
|
|
* Author:
|
|
* Berin Martini (berin.martini@gmail.com)
|
|
*/
|
|
`ifndef _axis_read_ `define _axis_read_
|
|
|
|
|
|
`include "axis_addr.v"
|
|
`include "axis_read_data.v"
|
|
|
|
module axis_read
|
|
#(parameter
|
|
BUF_AWIDTH = 9,
|
|
|
|
CONFIG_ID = 1,
|
|
CONFIG_ADDR = 23,
|
|
CONFIG_DATA = 24,
|
|
CONFIG_AWIDTH = 5,
|
|
CONFIG_DWIDTH = 32,
|
|
|
|
AXI_LEN_WIDTH = 8,
|
|
AXI_ADDR_WIDTH = 32,
|
|
AXI_DATA_WIDTH = 32,
|
|
DATA_WIDTH = 32)
|
|
(input clk,
|
|
input rst,
|
|
|
|
input [CONFIG_AWIDTH-1:0] cfg_addr,
|
|
input [CONFIG_DWIDTH-1:0] cfg_data,
|
|
input cfg_valid,
|
|
|
|
input axi_arready,
|
|
output [AXI_ADDR_WIDTH-1:0] axi_araddr,
|
|
output [AXI_LEN_WIDTH-1:0] axi_arlen,
|
|
output axi_arvalid,
|
|
|
|
input [AXI_DATA_WIDTH-1:0] axi_rdata,
|
|
input axi_rvalid,
|
|
output axi_rready,
|
|
|
|
output [DATA_WIDTH-1:0] data,
|
|
output valid,
|
|
input ready
|
|
);
|
|
|
|
/**
|
|
* Local parameters
|
|
*/
|
|
|
|
localparam WIDTH_RATIO = AXI_DATA_WIDTH/DATA_WIDTH;
|
|
localparam CONFIG_NB = 2;
|
|
|
|
localparam
|
|
C_IDLE = 0,
|
|
C_CONFIG = 1,
|
|
C_WAIT = 2,
|
|
C_ENABLE = 3;
|
|
|
|
|
|
`ifdef VERBOSE
|
|
initial $display("\using 'axis_read'\n");
|
|
`endif
|
|
|
|
|
|
/**
|
|
* Internal signals
|
|
*/
|
|
|
|
|
|
reg [3:0] c_state;
|
|
reg [3: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;
|
|
reg [CONFIG_DWIDTH*CONFIG_NB-1:0] cfg_store;
|
|
reg [7:0] cfg_cnt;
|
|
|
|
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;
|
|
reg cfg_enable;
|
|
|
|
|
|
/**
|
|
* Implementation
|
|
*/
|
|
|
|
assign start_addr = cfg_store[CONFIG_DWIDTH +: CONFIG_DWIDTH];
|
|
|
|
assign str_length = cfg_store[0 +: CONFIG_DWIDTH];
|
|
|
|
assign id_valid = (CONFIG_ID == cfg_data_r);
|
|
|
|
assign addressed = (CONFIG_ADDR == cfg_addr_r) & cfg_valid_r;
|
|
|
|
assign axis_data = (CONFIG_DATA == cfg_addr_r) & 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
|
|
|
|
|
|
always @(posedge clk)
|
|
if (c_state[C_CONFIG] & axis_data) begin
|
|
cfg_store <= {cfg_store, cfg_data_r};
|
|
end
|
|
|
|
|
|
always @(posedge clk) begin
|
|
cfg_cnt <= 'b0;
|
|
|
|
if (c_state[C_CONFIG]) begin
|
|
cfg_cnt <= cfg_cnt + 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;
|
|
end
|
|
end
|
|
|
|
|
|
always @(posedge clk)
|
|
if (rst) begin
|
|
c_state <= 'b0;
|
|
c_state[C_IDLE] <= 1'b1;
|
|
end
|
|
else c_state <= c_state_nx;
|
|
|
|
|
|
always @* begin : CONFIG_
|
|
c_state_nx = 'b0;
|
|
|
|
case (1'b1)
|
|
c_state[C_IDLE] : begin
|
|
if (addressed & id_valid) begin
|
|
c_state_nx[C_CONFIG] = 1'b1;
|
|
end
|
|
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;
|
|
end
|
|
else c_state_nx[C_CONFIG] = 1'b1;
|
|
end
|
|
c_state[C_WAIT] : begin
|
|
if (cfg_addr_ready & cfg_data_ready) begin
|
|
c_state_nx[C_ENABLE] = 1'b1;
|
|
end
|
|
else c_state_nx[C_WAIT] = 1'b1;
|
|
end
|
|
c_state[C_ENABLE] : begin
|
|
c_state_nx[C_IDLE] = 1'b1;
|
|
end
|
|
default : begin
|
|
c_state_nx[C_IDLE] = 1'b1;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
|
|
axis_addr #(
|
|
.CONFIG_DWIDTH (CONFIG_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))
|
|
axis_addr_ (
|
|
.clk (clk),
|
|
.rst (rst),
|
|
|
|
.cfg_address (cfg_address),
|
|
.cfg_length (cfg_length),
|
|
.cfg_valid (cfg_enable),
|
|
.cfg_ready (cfg_addr_ready),
|
|
|
|
.axi_aready (axi_arready),
|
|
.axi_aaddr (axi_araddr),
|
|
.axi_alen (axi_arlen),
|
|
.axi_avalid (axi_arvalid)
|
|
);
|
|
|
|
|
|
axis_read_data #(
|
|
.BUF_AWIDTH (BUF_AWIDTH),
|
|
.CONFIG_DWIDTH (CONFIG_DWIDTH),
|
|
.WIDTH_RATIO (WIDTH_RATIO),
|
|
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
|
.DATA_WIDTH (DATA_WIDTH))
|
|
axis_read_data_ (
|
|
.clk (clk),
|
|
.rst (rst),
|
|
|
|
.cfg_length (cfg_length),
|
|
.cfg_valid (cfg_enable),
|
|
.cfg_ready (cfg_data_ready),
|
|
|
|
.axi_rdata (axi_rdata),
|
|
.axi_rvalid (axi_rvalid),
|
|
.axi_rready (axi_rready),
|
|
|
|
.data (data),
|
|
.valid (valid),
|
|
.ready (ready)
|
|
);
|
|
|
|
|
|
|
|
endmodule
|
|
|
|
`endif // `ifndef _axis_read_
|