1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

Add AXI RAM interface modules, AXI dual port RAM module, and testbench

This commit is contained in:
Alex Forencich 2019-02-01 18:22:03 -08:00
parent 199a5544ca
commit 57dd292ae9
6 changed files with 1898 additions and 0 deletions

372
rtl/axi_dp_ram.v Normal file
View File

@ -0,0 +1,372 @@
/*
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* AXI4 dual port RAM
*/
module axi_dp_ram #
(
parameter DATA_WIDTH = 32, // width of data bus in bits
parameter ADDR_WIDTH = 16, // width of address bus in bits
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter ID_WIDTH = 8,
parameter A_PIPELINE_OUTPUT = 0,
parameter B_PIPELINE_OUTPUT = 0,
parameter A_INTERLEAVE = 0,
parameter B_INTERLEAVE = 0
)
(
input wire a_clk,
input wire a_rst,
input wire b_clk,
input wire b_rst,
input wire [ID_WIDTH-1:0] s_axi_a_awid,
input wire [ADDR_WIDTH-1:0] s_axi_a_awaddr,
input wire [7:0] s_axi_a_awlen,
input wire [2:0] s_axi_a_awsize,
input wire [1:0] s_axi_a_awburst,
input wire s_axi_a_awlock,
input wire [3:0] s_axi_a_awcache,
input wire [2:0] s_axi_a_awprot,
input wire s_axi_a_awvalid,
output wire s_axi_a_awready,
input wire [DATA_WIDTH-1:0] s_axi_a_wdata,
input wire [STRB_WIDTH-1:0] s_axi_a_wstrb,
input wire s_axi_a_wlast,
input wire s_axi_a_wvalid,
output wire s_axi_a_wready,
output wire [ID_WIDTH-1:0] s_axi_a_bid,
output wire [1:0] s_axi_a_bresp,
output wire s_axi_a_bvalid,
input wire s_axi_a_bready,
input wire [ID_WIDTH-1:0] s_axi_a_arid,
input wire [ADDR_WIDTH-1:0] s_axi_a_araddr,
input wire [7:0] s_axi_a_arlen,
input wire [2:0] s_axi_a_arsize,
input wire [1:0] s_axi_a_arburst,
input wire s_axi_a_arlock,
input wire [3:0] s_axi_a_arcache,
input wire [2:0] s_axi_a_arprot,
input wire s_axi_a_arvalid,
output wire s_axi_a_arready,
output wire [ID_WIDTH-1:0] s_axi_a_rid,
output wire [DATA_WIDTH-1:0] s_axi_a_rdata,
output wire [1:0] s_axi_a_rresp,
output wire s_axi_a_rlast,
output wire s_axi_a_rvalid,
input wire s_axi_a_rready,
input wire [ID_WIDTH-1:0] s_axi_b_awid,
input wire [ADDR_WIDTH-1:0] s_axi_b_awaddr,
input wire [7:0] s_axi_b_awlen,
input wire [2:0] s_axi_b_awsize,
input wire [1:0] s_axi_b_awburst,
input wire s_axi_b_awlock,
input wire [3:0] s_axi_b_awcache,
input wire [2:0] s_axi_b_awprot,
input wire s_axi_b_awvalid,
output wire s_axi_b_awready,
input wire [DATA_WIDTH-1:0] s_axi_b_wdata,
input wire [STRB_WIDTH-1:0] s_axi_b_wstrb,
input wire s_axi_b_wlast,
input wire s_axi_b_wvalid,
output wire s_axi_b_wready,
output wire [ID_WIDTH-1:0] s_axi_b_bid,
output wire [1:0] s_axi_b_bresp,
output wire s_axi_b_bvalid,
input wire s_axi_b_bready,
input wire [ID_WIDTH-1:0] s_axi_b_arid,
input wire [ADDR_WIDTH-1:0] s_axi_b_araddr,
input wire [7:0] s_axi_b_arlen,
input wire [2:0] s_axi_b_arsize,
input wire [1:0] s_axi_b_arburst,
input wire s_axi_b_arlock,
input wire [3:0] s_axi_b_arcache,
input wire [2:0] s_axi_b_arprot,
input wire s_axi_b_arvalid,
output wire s_axi_b_arready,
output wire [ID_WIDTH-1:0] s_axi_b_rid,
output wire [DATA_WIDTH-1:0] s_axi_b_rdata,
output wire [1:0] s_axi_b_rresp,
output wire s_axi_b_rlast,
output wire s_axi_b_rvalid,
input wire s_axi_b_rready
);
parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(STRB_WIDTH);
parameter WORD_WIDTH = STRB_WIDTH;
parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH;
// bus width assertions
initial begin
if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin
$error("Error: AXI data width not evenly divisble");
$finish;
end
if (2**$clog2(WORD_WIDTH) != WORD_WIDTH) begin
$error("Error: AXI word width must be even power of two");
$finish;
end
end
wire [ID_WIDTH-1:0] ram_a_cmd_id;
wire [ADDR_WIDTH-1:0] ram_a_cmd_addr;
wire [DATA_WIDTH-1:0] ram_a_cmd_wr_data;
wire [STRB_WIDTH-1:0] ram_a_cmd_wr_strb;
wire ram_a_cmd_wr_en;
wire ram_a_cmd_rd_en;
wire ram_a_cmd_last;
reg ram_a_cmd_ready_reg = 1'b1;
reg [ID_WIDTH-1:0] ram_a_rd_resp_id_reg = {ID_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] ram_a_rd_resp_data_reg = {DATA_WIDTH{1'b0}};
reg ram_a_rd_resp_last_reg = 1'b0;
reg ram_a_rd_resp_valid_reg = 1'b0;
wire ram_a_rd_resp_ready;
wire [ID_WIDTH-1:0] ram_b_cmd_id;
wire [ADDR_WIDTH-1:0] ram_b_cmd_addr;
wire [DATA_WIDTH-1:0] ram_b_cmd_wr_data;
wire [STRB_WIDTH-1:0] ram_b_cmd_wr_strb;
wire ram_b_cmd_wr_en;
wire ram_b_cmd_rd_en;
wire ram_b_cmd_last;
reg ram_b_cmd_ready_reg = 1'b1;
reg [ID_WIDTH-1:0] ram_b_rd_resp_id_reg = {ID_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] ram_b_rd_resp_data_reg = {DATA_WIDTH{1'b0}};
reg ram_b_rd_resp_last_reg = 1'b0;
reg ram_b_rd_resp_valid_reg = 1'b0;
wire ram_b_rd_resp_ready;
axi_ram_wr_rd_if #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.ID_WIDTH(ID_WIDTH),
.PIPELINE_OUTPUT(A_PIPELINE_OUTPUT),
.INTERLEAVE(A_INTERLEAVE)
)
a_if (
.clk(a_clk),
.rst(a_rst),
/*
* AXI slave interface
*/
.s_axi_awid(s_axi_a_awid),
.s_axi_awaddr(s_axi_a_awaddr),
.s_axi_awlen(s_axi_a_awlen),
.s_axi_awsize(s_axi_a_awsize),
.s_axi_awburst(s_axi_a_awburst),
.s_axi_awlock(s_axi_a_awlock),
.s_axi_awcache(s_axi_a_awcache),
.s_axi_awprot(s_axi_a_awprot),
.s_axi_awvalid(s_axi_a_awvalid),
.s_axi_awready(s_axi_a_awready),
.s_axi_wdata(s_axi_a_wdata),
.s_axi_wstrb(s_axi_a_wstrb),
.s_axi_wlast(s_axi_a_wlast),
.s_axi_wvalid(s_axi_a_wvalid),
.s_axi_wready(s_axi_a_wready),
.s_axi_bid(s_axi_a_bid),
.s_axi_bresp(s_axi_a_bresp),
.s_axi_bvalid(s_axi_a_bvalid),
.s_axi_bready(s_axi_a_bready),
.s_axi_arid(s_axi_a_arid),
.s_axi_araddr(s_axi_a_araddr),
.s_axi_arlen(s_axi_a_arlen),
.s_axi_arsize(s_axi_a_arsize),
.s_axi_arburst(s_axi_a_arburst),
.s_axi_arlock(s_axi_a_arlock),
.s_axi_arcache(s_axi_a_arcache),
.s_axi_arprot(s_axi_a_arprot),
.s_axi_arvalid(s_axi_a_arvalid),
.s_axi_arready(s_axi_a_arready),
.s_axi_rid(s_axi_a_rid),
.s_axi_rdata(s_axi_a_rdata),
.s_axi_rresp(s_axi_a_rresp),
.s_axi_rlast(s_axi_a_rlast),
.s_axi_rvalid(s_axi_a_rvalid),
.s_axi_rready(s_axi_a_rready),
/*
* RAM interface
*/
.ram_cmd_id(ram_a_cmd_id),
.ram_cmd_addr(ram_a_cmd_addr),
.ram_cmd_wr_data(ram_a_cmd_wr_data),
.ram_cmd_wr_strb(ram_a_cmd_wr_strb),
.ram_cmd_wr_en(ram_a_cmd_wr_en),
.ram_cmd_rd_en(ram_a_cmd_rd_en),
.ram_cmd_last(ram_a_cmd_last),
.ram_cmd_ready(ram_a_cmd_ready_reg),
.ram_rd_resp_id(ram_a_rd_resp_id_reg),
.ram_rd_resp_data(ram_a_rd_resp_data_reg),
.ram_rd_resp_last(ram_a_rd_resp_last_reg),
.ram_rd_resp_valid(ram_a_rd_resp_valid_reg),
.ram_rd_resp_ready(ram_a_rd_resp_ready)
);
axi_ram_wr_rd_if #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.ID_WIDTH(ID_WIDTH),
.PIPELINE_OUTPUT(B_PIPELINE_OUTPUT),
.INTERLEAVE(B_INTERLEAVE)
)
b_if (
.clk(b_clk),
.rst(b_rst),
/*
* AXI slave interface
*/
.s_axi_awid(s_axi_b_awid),
.s_axi_awaddr(s_axi_b_awaddr),
.s_axi_awlen(s_axi_b_awlen),
.s_axi_awsize(s_axi_b_awsize),
.s_axi_awburst(s_axi_b_awburst),
.s_axi_awlock(s_axi_b_awlock),
.s_axi_awcache(s_axi_b_awcache),
.s_axi_awprot(s_axi_b_awprot),
.s_axi_awvalid(s_axi_b_awvalid),
.s_axi_awready(s_axi_b_awready),
.s_axi_wdata(s_axi_b_wdata),
.s_axi_wstrb(s_axi_b_wstrb),
.s_axi_wlast(s_axi_b_wlast),
.s_axi_wvalid(s_axi_b_wvalid),
.s_axi_wready(s_axi_b_wready),
.s_axi_bid(s_axi_b_bid),
.s_axi_bresp(s_axi_b_bresp),
.s_axi_bvalid(s_axi_b_bvalid),
.s_axi_bready(s_axi_b_bready),
.s_axi_arid(s_axi_b_arid),
.s_axi_araddr(s_axi_b_araddr),
.s_axi_arlen(s_axi_b_arlen),
.s_axi_arsize(s_axi_b_arsize),
.s_axi_arburst(s_axi_b_arburst),
.s_axi_arlock(s_axi_b_arlock),
.s_axi_arcache(s_axi_b_arcache),
.s_axi_arprot(s_axi_b_arprot),
.s_axi_arvalid(s_axi_b_arvalid),
.s_axi_arready(s_axi_b_arready),
.s_axi_rid(s_axi_b_rid),
.s_axi_rdata(s_axi_b_rdata),
.s_axi_rresp(s_axi_b_rresp),
.s_axi_rlast(s_axi_b_rlast),
.s_axi_rvalid(s_axi_b_rvalid),
.s_axi_rready(s_axi_b_rready),
/*
* RAM interface
*/
.ram_cmd_id(ram_b_cmd_id),
.ram_cmd_addr(ram_b_cmd_addr),
.ram_cmd_wr_data(ram_b_cmd_wr_data),
.ram_cmd_wr_strb(ram_b_cmd_wr_strb),
.ram_cmd_wr_en(ram_b_cmd_wr_en),
.ram_cmd_rd_en(ram_b_cmd_rd_en),
.ram_cmd_last(ram_b_cmd_last),
.ram_cmd_ready(ram_b_cmd_ready_reg),
.ram_rd_resp_id(ram_b_rd_resp_id_reg),
.ram_rd_resp_data(ram_b_rd_resp_data_reg),
.ram_rd_resp_last(ram_b_rd_resp_last_reg),
.ram_rd_resp_valid(ram_b_rd_resp_valid_reg),
.ram_rd_resp_ready(ram_b_rd_resp_ready)
);
// (* RAM_STYLE="BLOCK" *)
reg [DATA_WIDTH-1:0] mem[(2**VALID_ADDR_WIDTH)-1:0];
wire [VALID_ADDR_WIDTH-1:0] addr_a_valid = ram_a_cmd_addr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
wire [VALID_ADDR_WIDTH-1:0] addr_b_valid = ram_b_cmd_addr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
integer i, j;
initial begin
// two nested loops for smaller number of iterations per loop
// workaround for synthesizer complaints about large loop counts
for (i = 0; i < 2**ADDR_WIDTH; i = i + 2**(ADDR_WIDTH/2)) begin
for (j = i; j < i + 2**(ADDR_WIDTH/2); j = j + 1) begin
mem[j] = 0;
end
end
end
always @(posedge a_clk) begin
ram_a_rd_resp_valid_reg <= ram_a_rd_resp_valid_reg && !ram_a_rd_resp_ready;
ram_a_cmd_ready_reg <= !ram_a_rd_resp_valid_reg || ram_a_rd_resp_ready;
if (ram_a_cmd_ready_reg && ram_a_cmd_rd_en) begin
ram_a_rd_resp_id_reg <= ram_a_cmd_id;
ram_a_rd_resp_data_reg <= mem[addr_a_valid];
ram_a_rd_resp_last_reg <= ram_a_cmd_last;
ram_a_rd_resp_valid_reg <= 1'b1;
ram_a_cmd_ready_reg <= ram_a_rd_resp_ready;
end else if (ram_a_cmd_ready_reg && ram_a_cmd_wr_en) begin
for (i = 0; i < WORD_WIDTH; i = i + 1) begin
if (ram_a_cmd_wr_strb[i]) begin
mem[addr_a_valid][8*i +: 8] <= ram_a_cmd_wr_data[8*i +: 8];
end
end
end
if (a_rst) begin
ram_a_cmd_ready_reg <= 1'b1;
ram_a_rd_resp_valid_reg <= 1'b0;
end
end
always @(posedge b_clk) begin
ram_b_rd_resp_valid_reg <= ram_b_rd_resp_valid_reg && !ram_b_rd_resp_ready;
ram_b_cmd_ready_reg <= !ram_b_rd_resp_valid_reg || ram_b_rd_resp_ready;
if (ram_b_cmd_ready_reg && ram_b_cmd_rd_en) begin
ram_b_rd_resp_id_reg <= ram_b_cmd_id;
ram_b_rd_resp_data_reg <= mem[addr_b_valid];
ram_b_rd_resp_last_reg <= ram_b_cmd_last;
ram_b_rd_resp_valid_reg <= 1'b1;
ram_b_cmd_ready_reg <= ram_b_rd_resp_ready;
end else if (ram_b_cmd_ready_reg && ram_b_cmd_wr_en) begin
for (i = 0; i < WORD_WIDTH; i = i + 1) begin
if (ram_b_cmd_wr_strb[i]) begin
mem[addr_b_valid][8*i +: 8] <= ram_b_cmd_wr_data[8*i +: 8];
end
end
end
if (b_rst) begin
ram_a_cmd_ready_reg <= 1'b1;
ram_b_rd_resp_valid_reg <= 1'b0;
end
end
endmodule

226
rtl/axi_ram_rd_if.v Normal file
View File

@ -0,0 +1,226 @@
/*
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* AXI4 RAM read interface
*/
module axi_ram_rd_if #
(
parameter DATA_WIDTH = 32, // width of data bus in bits
parameter ADDR_WIDTH = 16, // width of address bus in bits
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter ID_WIDTH = 8,
parameter PIPELINE_OUTPUT = 0
)
(
input wire clk,
input wire rst,
/*
* AXI slave interface
*/
input wire [ID_WIDTH-1:0] s_axi_arid,
input wire [ADDR_WIDTH-1:0] s_axi_araddr,
input wire [7:0] s_axi_arlen,
input wire [2:0] s_axi_arsize,
input wire [1:0] s_axi_arburst,
input wire s_axi_arlock,
input wire [3:0] s_axi_arcache,
input wire [2:0] s_axi_arprot,
input wire s_axi_arvalid,
output wire s_axi_arready,
output wire [ID_WIDTH-1:0] s_axi_rid,
output wire [DATA_WIDTH-1:0] s_axi_rdata,
output wire [1:0] s_axi_rresp,
output wire s_axi_rlast,
output wire s_axi_rvalid,
input wire s_axi_rready,
/*
* RAM interface
*/
output wire [ID_WIDTH-1:0] ram_rd_cmd_id,
output wire [ADDR_WIDTH-1:0] ram_rd_cmd_addr,
output wire ram_rd_cmd_en,
output wire ram_rd_cmd_last,
input wire ram_rd_cmd_ready,
input wire [ID_WIDTH-1:0] ram_rd_resp_id,
input wire [DATA_WIDTH-1:0] ram_rd_resp_data,
input wire ram_rd_resp_last,
input wire ram_rd_resp_valid,
output wire ram_rd_resp_ready
);
parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(STRB_WIDTH);
parameter WORD_WIDTH = STRB_WIDTH;
parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH;
// bus width assertions
initial begin
if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin
$error("Error: AXI data width not evenly divisble");
$finish;
end
if (2**$clog2(WORD_WIDTH) != WORD_WIDTH) begin
$error("Error: AXI word width must be even power of two");
$finish;
end
end
localparam [0:0]
STATE_IDLE = 1'd0,
STATE_BURST = 1'd1;
reg [0:0] state_reg = STATE_IDLE, state_next;
reg [ID_WIDTH-1:0] read_id_reg = {ID_WIDTH{1'b0}}, read_id_next;
reg [ADDR_WIDTH-1:0] read_addr_reg = {ADDR_WIDTH{1'b0}}, read_addr_next;
reg read_addr_valid_reg = 1'b0, read_addr_valid_next;
reg read_addr_ready;
reg read_last_reg = 1'b0, read_last_next;
reg [7:0] read_count_reg = 8'd0, read_count_next;
reg [2:0] read_size_reg = 3'd0, read_size_next;
reg [1:0] read_burst_reg = 2'd0, read_burst_next;
reg s_axi_arready_reg = 1'b0, s_axi_arready_next;
reg [ID_WIDTH-1:0] s_axi_rid_pipe_reg = {ID_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] s_axi_rdata_pipe_reg = {DATA_WIDTH{1'b0}};
reg s_axi_rlast_pipe_reg = 1'b0;
reg s_axi_rvalid_pipe_reg = 1'b0;
assign s_axi_arready = s_axi_arready_reg;
assign s_axi_rid = PIPELINE_OUTPUT ? s_axi_rid_pipe_reg : ram_rd_resp_id;
assign s_axi_rdata = PIPELINE_OUTPUT ? s_axi_rdata_pipe_reg : ram_rd_resp_data;
assign s_axi_rresp = 2'b00;
assign s_axi_rlast = PIPELINE_OUTPUT ? s_axi_rlast_pipe_reg : ram_rd_resp_last;
assign s_axi_rvalid = PIPELINE_OUTPUT ? s_axi_rvalid_pipe_reg : ram_rd_resp_valid;
assign ram_rd_cmd_id = read_id_reg;
assign ram_rd_cmd_addr = read_addr_reg;
assign ram_rd_cmd_en = read_addr_valid_reg;
assign ram_rd_cmd_last = read_last_reg;
assign ram_rd_resp_ready = s_axi_rready || (PIPELINE_OUTPUT && !s_axi_rvalid_pipe_reg);
always @* begin
state_next = STATE_IDLE;
read_addr_ready = ram_rd_cmd_ready;
read_id_next = read_id_reg;
read_addr_next = read_addr_reg;
read_addr_valid_next = read_addr_valid_reg;
read_last_next = read_last_reg;
read_count_next = read_count_reg;
read_size_next = read_size_reg;
read_burst_next = read_burst_reg;
s_axi_arready_next = 1'b0;
if (ram_rd_cmd_ready && ram_rd_cmd_en) begin
read_addr_ready = 1'b1;
read_addr_valid_next = !read_last_reg;
end
case (state_reg)
STATE_IDLE: begin
s_axi_arready_next = (read_addr_ready || !read_addr_valid_reg);
if (s_axi_arready & s_axi_arvalid) begin
read_id_next = s_axi_arid;
read_addr_next = s_axi_araddr;
read_count_next = s_axi_arlen;
read_size_next = s_axi_arsize < $clog2(STRB_WIDTH) ? s_axi_arsize : $clog2(STRB_WIDTH);
read_burst_next = s_axi_arburst;
s_axi_arready_next = 1'b0;
read_addr_valid_next = 1'b1;
if (s_axi_arlen > 0) begin
read_last_next = 1'b0;
state_next = STATE_BURST;
end else begin
read_last_next = 1'b1;
state_next = STATE_IDLE;
end
end else begin
state_next = STATE_IDLE;
end
end
STATE_BURST: begin
s_axi_arready_next = 1'b0;
if (read_addr_ready) begin
if (read_burst_reg != 2'b00) begin
read_addr_next = read_addr_reg + (1 << read_size_reg);
end
read_count_next = read_count_reg - 1;
read_last_next = read_count_next == 0;
if (read_count_reg > 0) begin
state_next = STATE_BURST;
end else begin
state_next = STATE_IDLE;
end
end else begin
state_next = STATE_BURST;
end
end
endcase
end
always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
read_addr_valid_reg <= 1'b0;
s_axi_arready_reg <= 1'b0;
s_axi_rvalid_pipe_reg <= 1'b0;
end else begin
state_reg <= state_next;
read_addr_valid_reg <= read_addr_valid_next;
s_axi_arready_reg <= s_axi_arready_next;
if (!s_axi_rvalid_pipe_reg || s_axi_rready) begin
s_axi_rvalid_pipe_reg <= ram_rd_resp_valid;
end
end
read_id_reg <= read_id_next;
read_addr_reg <= read_addr_next;
read_last_reg <= read_last_next;
read_count_reg <= read_count_next;
read_size_reg <= read_size_next;
read_burst_reg <= read_burst_next;
if (!s_axi_rvalid_pipe_reg || s_axi_rready) begin
s_axi_rid_pipe_reg <= ram_rd_resp_id;
s_axi_rdata_pipe_reg <= ram_rd_resp_data;
s_axi_rlast_pipe_reg <= ram_rd_resp_last;
end
end
endmodule

219
rtl/axi_ram_wr_if.v Normal file
View File

@ -0,0 +1,219 @@
/*
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* AXI4 RAM write interface
*/
module axi_ram_wr_if #
(
parameter DATA_WIDTH = 32, // width of data bus in bits
parameter ADDR_WIDTH = 16, // width of address bus in bits
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter ID_WIDTH = 8
)
(
input wire clk,
input wire rst,
/*
* AXI slave interface
*/
input wire [ID_WIDTH-1:0] s_axi_awid,
input wire [ADDR_WIDTH-1:0] s_axi_awaddr,
input wire [7:0] s_axi_awlen,
input wire [2:0] s_axi_awsize,
input wire [1:0] s_axi_awburst,
input wire s_axi_awlock,
input wire [3:0] s_axi_awcache,
input wire [2:0] s_axi_awprot,
input wire s_axi_awvalid,
output wire s_axi_awready,
input wire [DATA_WIDTH-1:0] s_axi_wdata,
input wire [STRB_WIDTH-1:0] s_axi_wstrb,
input wire s_axi_wlast,
input wire s_axi_wvalid,
output wire s_axi_wready,
output wire [ID_WIDTH-1:0] s_axi_bid,
output wire [1:0] s_axi_bresp,
output wire s_axi_bvalid,
input wire s_axi_bready,
/*
* RAM interface
*/
output wire [ADDR_WIDTH-1:0] ram_wr_cmd_addr,
output wire [DATA_WIDTH-1:0] ram_wr_cmd_data,
output wire [STRB_WIDTH-1:0] ram_wr_cmd_strb,
output wire ram_wr_cmd_en,
output wire ram_wr_cmd_last,
input wire ram_wr_cmd_ready
);
parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(STRB_WIDTH);
parameter WORD_WIDTH = STRB_WIDTH;
parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH;
// bus width assertions
initial begin
if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin
$error("Error: AXI data width not evenly divisble");
$finish;
end
if (2**$clog2(WORD_WIDTH) != WORD_WIDTH) begin
$error("Error: AXI word width must be even power of two");
$finish;
end
end
localparam [0:0]
STATE_IDLE = 1'd0,
STATE_BURST = 1'd1;
reg [0:0] state_reg = STATE_IDLE, state_next;
reg [ID_WIDTH-1:0] write_id_reg = {ID_WIDTH{1'b0}}, write_id_next;
reg [ADDR_WIDTH-1:0] write_addr_reg = {ADDR_WIDTH{1'b0}}, write_addr_next;
reg write_addr_valid_reg = 1'b0, write_addr_valid_next;
reg write_addr_ready;
reg write_last_reg = 1'b0, write_last_next;
reg [7:0] write_count_reg = 8'd0, write_count_next;
reg [2:0] write_size_reg = 3'd0, write_size_next;
reg [1:0] write_burst_reg = 2'd0, write_burst_next;
reg s_axi_awready_reg = 1'b0, s_axi_awready_next;
reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}}, s_axi_bid_next;
reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next;
assign s_axi_awready = s_axi_awready_reg;
assign s_axi_wready = write_addr_valid_reg && ram_wr_cmd_ready;
assign s_axi_bid = s_axi_bid_reg;
assign s_axi_bresp = 2'b00;
assign s_axi_bvalid = s_axi_bvalid_reg;
assign ram_wr_cmd_addr = write_addr_reg;
assign ram_wr_cmd_data = s_axi_wdata;
assign ram_wr_cmd_strb = s_axi_wstrb;
assign ram_wr_cmd_en = write_addr_valid_reg && s_axi_wvalid;
assign ram_wr_cmd_last = write_last_reg;
always @* begin
state_next = STATE_IDLE;
write_addr_ready = 1'b0;
write_id_next = write_id_reg;
write_addr_next = write_addr_reg;
write_addr_valid_next = write_addr_valid_reg;
write_last_next = write_last_reg;
write_count_next = write_count_reg;
write_size_next = write_size_reg;
write_burst_next = write_burst_reg;
s_axi_awready_next = 1'b0;
s_axi_bid_next = s_axi_bid_reg;
s_axi_bvalid_next = s_axi_bvalid_reg && !s_axi_bready;
if (ram_wr_cmd_ready && ram_wr_cmd_en) begin
write_addr_ready = 1'b1;
write_addr_valid_next = !write_last_reg;
end
case (state_reg)
STATE_IDLE: begin
s_axi_awready_next = (write_addr_ready || !write_addr_valid_reg) && (!s_axi_bvalid || s_axi_bready);
if (s_axi_awready & s_axi_awvalid) begin
write_id_next = s_axi_awid;
write_addr_next = s_axi_awaddr;
write_count_next = s_axi_awlen;
write_size_next = s_axi_awsize < $clog2(STRB_WIDTH) ? s_axi_awsize : $clog2(STRB_WIDTH);
write_burst_next = s_axi_awburst;
write_addr_valid_next = 1'b1;
s_axi_awready_next = 1'b0;
if (s_axi_awlen > 0) begin
write_last_next = 1'b0;
state_next = STATE_BURST;
end else begin
s_axi_bid_next = write_id_next;
s_axi_bvalid_next = 1'b1;
write_last_next = 1'b1;
state_next = STATE_IDLE;
end
end else begin
state_next = STATE_IDLE;
end
end
STATE_BURST: begin
s_axi_awready_next = 1'b0;
if (write_addr_ready) begin
if (write_burst_reg != 2'b00) begin
write_addr_next = write_addr_reg + (1 << write_size_reg);
end
write_count_next = write_count_reg - 1;
write_last_next = write_count_next == 0;
if (write_count_reg > 0) begin
state_next = STATE_BURST;
end else begin
s_axi_bid_next = write_id_reg;
s_axi_bvalid_next = 1'b1;
state_next = STATE_IDLE;
end
end else begin
state_next = STATE_BURST;
end
end
endcase
end
always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
write_addr_valid_reg <= 1'b0;
s_axi_awready_reg <= 1'b0;
s_axi_bvalid_reg <= 1'b0;
end else begin
state_reg <= state_next;
write_addr_valid_reg <= write_addr_valid_next;
s_axi_awready_reg <= s_axi_awready_next;
s_axi_bvalid_reg <= s_axi_bvalid_next;
end
write_id_reg <= write_id_next;
write_addr_reg <= write_addr_next;
write_last_reg <= write_last_next;
write_count_reg <= write_count_next;
write_size_reg <= write_size_next;
write_burst_reg <= write_burst_next;
s_axi_bid_reg <= s_axi_bid_next;
end
endmodule

238
rtl/axi_ram_wr_rd_if.v Normal file
View File

@ -0,0 +1,238 @@
/*
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* AXI4 RAM read/write interface
*/
module axi_ram_wr_rd_if #
(
parameter DATA_WIDTH = 32, // width of data bus in bits
parameter ADDR_WIDTH = 16, // width of address bus in bits
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter ID_WIDTH = 8,
parameter PIPELINE_OUTPUT = 0,
parameter INTERLEAVE = 0
)
(
input wire clk,
input wire rst,
/*
* AXI slave interface
*/
input wire [ID_WIDTH-1:0] s_axi_awid,
input wire [ADDR_WIDTH-1:0] s_axi_awaddr,
input wire [7:0] s_axi_awlen,
input wire [2:0] s_axi_awsize,
input wire [1:0] s_axi_awburst,
input wire s_axi_awlock,
input wire [3:0] s_axi_awcache,
input wire [2:0] s_axi_awprot,
input wire s_axi_awvalid,
output wire s_axi_awready,
input wire [DATA_WIDTH-1:0] s_axi_wdata,
input wire [STRB_WIDTH-1:0] s_axi_wstrb,
input wire s_axi_wlast,
input wire s_axi_wvalid,
output wire s_axi_wready,
output wire [ID_WIDTH-1:0] s_axi_bid,
output wire [1:0] s_axi_bresp,
output wire s_axi_bvalid,
input wire s_axi_bready,
input wire [ID_WIDTH-1:0] s_axi_arid,
input wire [ADDR_WIDTH-1:0] s_axi_araddr,
input wire [7:0] s_axi_arlen,
input wire [2:0] s_axi_arsize,
input wire [1:0] s_axi_arburst,
input wire s_axi_arlock,
input wire [3:0] s_axi_arcache,
input wire [2:0] s_axi_arprot,
input wire s_axi_arvalid,
output wire s_axi_arready,
output wire [ID_WIDTH-1:0] s_axi_rid,
output wire [DATA_WIDTH-1:0] s_axi_rdata,
output wire [1:0] s_axi_rresp,
output wire s_axi_rlast,
output wire s_axi_rvalid,
input wire s_axi_rready,
/*
* RAM interface
*/
output wire [ID_WIDTH-1:0] ram_cmd_id,
output wire [ADDR_WIDTH-1:0] ram_cmd_addr,
output wire [DATA_WIDTH-1:0] ram_cmd_wr_data,
output wire [STRB_WIDTH-1:0] ram_cmd_wr_strb,
output wire ram_cmd_wr_en,
output wire ram_cmd_rd_en,
output wire ram_cmd_last,
input wire ram_cmd_ready,
input wire [ID_WIDTH-1:0] ram_rd_resp_id,
input wire [DATA_WIDTH-1:0] ram_rd_resp_data,
input wire ram_rd_resp_last,
input wire ram_rd_resp_valid,
output wire ram_rd_resp_ready
);
wire [ADDR_WIDTH-1:0] ram_wr_cmd_addr;
wire ram_wr_cmd_en;
wire ram_wr_cmd_last;
wire ram_wr_cmd_ready;
wire [ADDR_WIDTH-1:0] ram_rd_cmd_addr;
wire ram_rd_cmd_en;
wire ram_rd_cmd_last;
wire ram_rd_cmd_ready;
axi_ram_wr_if #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.ID_WIDTH(ID_WIDTH)
)
axi_ram_wr_if_inst (
.clk(clk),
.rst(rst),
.s_axi_awid(s_axi_awid),
.s_axi_awaddr(s_axi_awaddr),
.s_axi_awlen(s_axi_awlen),
.s_axi_awsize(s_axi_awsize),
.s_axi_awburst(s_axi_awburst),
.s_axi_awlock(s_axi_awlock),
.s_axi_awcache(s_axi_awcache),
.s_axi_awprot(s_axi_awprot),
.s_axi_awvalid(s_axi_awvalid),
.s_axi_awready(s_axi_awready),
.s_axi_wdata(s_axi_wdata),
.s_axi_wstrb(s_axi_wstrb),
.s_axi_wlast(s_axi_wlast),
.s_axi_wvalid(s_axi_wvalid),
.s_axi_wready(s_axi_wready),
.s_axi_bid(s_axi_bid),
.s_axi_bresp(s_axi_bresp),
.s_axi_bvalid(s_axi_bvalid),
.s_axi_bready(s_axi_bready),
.ram_wr_cmd_addr(ram_wr_cmd_addr),
.ram_wr_cmd_data(ram_cmd_wr_data),
.ram_wr_cmd_strb(ram_cmd_wr_strb),
.ram_wr_cmd_en(ram_wr_cmd_en),
.ram_wr_cmd_last(ram_wr_cmd_last),
.ram_wr_cmd_ready(ram_wr_cmd_ready)
);
axi_ram_rd_if #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.ID_WIDTH(ID_WIDTH),
.PIPELINE_OUTPUT(PIPELINE_OUTPUT)
)
axi_ram_rd_if_inst (
.clk(clk),
.rst(rst),
.s_axi_arid(s_axi_arid),
.s_axi_araddr(s_axi_araddr),
.s_axi_arlen(s_axi_arlen),
.s_axi_arsize(s_axi_arsize),
.s_axi_arburst(s_axi_arburst),
.s_axi_arlock(s_axi_arlock),
.s_axi_arcache(s_axi_arcache),
.s_axi_arprot(s_axi_arprot),
.s_axi_arvalid(s_axi_arvalid),
.s_axi_arready(s_axi_arready),
.s_axi_rid(s_axi_rid),
.s_axi_rdata(s_axi_rdata),
.s_axi_rresp(s_axi_rresp),
.s_axi_rlast(s_axi_rlast),
.s_axi_rvalid(s_axi_rvalid),
.s_axi_rready(s_axi_rready),
.ram_rd_cmd_id(ram_cmd_id),
.ram_rd_cmd_addr(ram_rd_cmd_addr),
.ram_rd_cmd_en(ram_rd_cmd_en),
.ram_rd_cmd_last(ram_rd_cmd_last),
.ram_rd_cmd_ready(ram_rd_cmd_ready),
.ram_rd_resp_id(ram_rd_resp_id),
.ram_rd_resp_data(ram_rd_resp_data),
.ram_rd_resp_last(ram_rd_resp_last),
.ram_rd_resp_valid(ram_rd_resp_valid),
.ram_rd_resp_ready(ram_rd_resp_ready)
);
// arbitration
reg read_eligible;
reg write_eligible;
reg write_en;
reg read_en;
reg last_read_reg = 1'b0, last_read_next;
reg transaction_reg = 1'b0, transaction_next;
assign ram_cmd_wr_en = write_en;
assign ram_cmd_rd_en = read_en;
assign ram_cmd_addr = ram_cmd_rd_en ? ram_rd_cmd_addr : ram_wr_cmd_addr;
assign ram_cmd_last = ram_cmd_rd_en ? ram_rd_cmd_last : ram_wr_cmd_last;
assign ram_wr_cmd_ready = ram_cmd_ready && write_en;
assign ram_rd_cmd_ready = ram_cmd_ready && read_en;
always @* begin
write_en = 1'b0;
read_en = 1'b0;
last_read_next = last_read_reg;
transaction_next = transaction_reg;
write_eligible = ram_wr_cmd_en && ram_cmd_ready;
read_eligible = ram_rd_cmd_en && ram_cmd_ready;
if (write_eligible && (!read_eligible || last_read_reg || (!INTERLEAVE && transaction_reg)) && (INTERLEAVE || !transaction_reg || !last_read_reg)) begin
last_read_next = 1'b0;
transaction_next = !ram_wr_cmd_last;
write_en = 1'b1;
end else if (read_eligible && (INTERLEAVE || !transaction_reg || last_read_reg)) begin
last_read_next = 1'b1;
transaction_next = !ram_rd_cmd_last;
read_en = 1'b1;
end
end
always @(posedge clk) begin
if (rst) begin
last_read_reg <= 1'b0;
transaction_reg <= 1'b0;
end else begin
last_read_reg <= last_read_next;
transaction_reg <= transaction_next;
end
end
endmodule

541
tb/test_axi_dp_ram.py Executable file
View File

@ -0,0 +1,541 @@
#!/usr/bin/env python
"""
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import axi
module = 'axi_dp_ram'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/axi_ram_wr_if.v")
srcs.append("../rtl/axi_ram_rd_if.v")
srcs.append("../rtl/axi_ram_wr_rd_if.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
DATA_WIDTH = 32
ADDR_WIDTH = 16
STRB_WIDTH = (DATA_WIDTH/8)
ID_WIDTH = 8
A_PIPELINE_OUTPUT = 0
B_PIPELINE_OUTPUT = 0
A_INTERLEAVE = 0
B_INTERLEAVE = 1
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
a_clk = Signal(bool(0))
a_rst = Signal(bool(0))
b_clk = Signal(bool(0))
b_rst = Signal(bool(0))
s_axi_a_awid = Signal(intbv(0)[ID_WIDTH:])
s_axi_a_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axi_a_awlen = Signal(intbv(0)[8:])
s_axi_a_awsize = Signal(intbv(0)[3:])
s_axi_a_awburst = Signal(intbv(0)[2:])
s_axi_a_awlock = Signal(bool(0))
s_axi_a_awcache = Signal(intbv(0)[4:])
s_axi_a_awprot = Signal(intbv(0)[3:])
s_axi_a_awvalid = Signal(bool(0))
s_axi_a_wdata = Signal(intbv(0)[DATA_WIDTH:])
s_axi_a_wstrb = Signal(intbv(0)[STRB_WIDTH:])
s_axi_a_wlast = Signal(bool(0))
s_axi_a_wvalid = Signal(bool(0))
s_axi_a_bready = Signal(bool(0))
s_axi_a_arid = Signal(intbv(0)[ID_WIDTH:])
s_axi_a_araddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axi_a_arlen = Signal(intbv(0)[8:])
s_axi_a_arsize = Signal(intbv(0)[3:])
s_axi_a_arburst = Signal(intbv(0)[2:])
s_axi_a_arlock = Signal(bool(0))
s_axi_a_arcache = Signal(intbv(0)[4:])
s_axi_a_arprot = Signal(intbv(0)[3:])
s_axi_a_arvalid = Signal(bool(0))
s_axi_a_rready = Signal(bool(0))
s_axi_b_awid = Signal(intbv(0)[ID_WIDTH:])
s_axi_b_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axi_b_awlen = Signal(intbv(0)[8:])
s_axi_b_awsize = Signal(intbv(0)[3:])
s_axi_b_awburst = Signal(intbv(0)[2:])
s_axi_b_awlock = Signal(bool(0))
s_axi_b_awcache = Signal(intbv(0)[4:])
s_axi_b_awprot = Signal(intbv(0)[3:])
s_axi_b_awvalid = Signal(bool(0))
s_axi_b_wdata = Signal(intbv(0)[DATA_WIDTH:])
s_axi_b_wstrb = Signal(intbv(0)[STRB_WIDTH:])
s_axi_b_wlast = Signal(bool(0))
s_axi_b_wvalid = Signal(bool(0))
s_axi_b_bready = Signal(bool(0))
s_axi_b_arid = Signal(intbv(0)[ID_WIDTH:])
s_axi_b_araddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axi_b_arlen = Signal(intbv(0)[8:])
s_axi_b_arsize = Signal(intbv(0)[3:])
s_axi_b_arburst = Signal(intbv(0)[2:])
s_axi_b_arlock = Signal(bool(0))
s_axi_b_arcache = Signal(intbv(0)[4:])
s_axi_b_arprot = Signal(intbv(0)[3:])
s_axi_b_arvalid = Signal(bool(0))
s_axi_b_rready = Signal(bool(0))
# Outputs
s_axi_a_awready = Signal(bool(0))
s_axi_a_wready = Signal(bool(0))
s_axi_a_bid = Signal(intbv(0)[ID_WIDTH:])
s_axi_a_bresp = Signal(intbv(0)[2:])
s_axi_a_bvalid = Signal(bool(0))
s_axi_a_arready = Signal(bool(0))
s_axi_a_rid = Signal(intbv(0)[ID_WIDTH:])
s_axi_a_rdata = Signal(intbv(0)[DATA_WIDTH:])
s_axi_a_rresp = Signal(intbv(0)[2:])
s_axi_a_rlast = Signal(bool(0))
s_axi_a_rvalid = Signal(bool(0))
s_axi_b_awready = Signal(bool(0))
s_axi_b_wready = Signal(bool(0))
s_axi_b_bid = Signal(intbv(0)[ID_WIDTH:])
s_axi_b_bresp = Signal(intbv(0)[2:])
s_axi_b_bvalid = Signal(bool(0))
s_axi_b_arready = Signal(bool(0))
s_axi_b_rid = Signal(intbv(0)[ID_WIDTH:])
s_axi_b_rdata = Signal(intbv(0)[DATA_WIDTH:])
s_axi_b_rresp = Signal(intbv(0)[2:])
s_axi_b_rlast = Signal(bool(0))
s_axi_b_rvalid = Signal(bool(0))
# AXI4 master
axi_a_master_inst = axi.AXIMaster()
axi_a_master_pause = Signal(bool(False))
axi_a_master_logic = axi_a_master_inst.create_logic(
a_clk,
a_rst,
m_axi_awid=s_axi_a_awid,
m_axi_awaddr=s_axi_a_awaddr,
m_axi_awlen=s_axi_a_awlen,
m_axi_awsize=s_axi_a_awsize,
m_axi_awburst=s_axi_a_awburst,
m_axi_awlock=s_axi_a_awlock,
m_axi_awcache=s_axi_a_awcache,
m_axi_awprot=s_axi_a_awprot,
m_axi_awvalid=s_axi_a_awvalid,
m_axi_awready=s_axi_a_awready,
m_axi_wdata=s_axi_a_wdata,
m_axi_wstrb=s_axi_a_wstrb,
m_axi_wlast=s_axi_a_wlast,
m_axi_wvalid=s_axi_a_wvalid,
m_axi_wready=s_axi_a_wready,
m_axi_bid=s_axi_a_bid,
m_axi_bresp=s_axi_a_bresp,
m_axi_bvalid=s_axi_a_bvalid,
m_axi_bready=s_axi_a_bready,
m_axi_arid=s_axi_a_arid,
m_axi_araddr=s_axi_a_araddr,
m_axi_arlen=s_axi_a_arlen,
m_axi_arsize=s_axi_a_arsize,
m_axi_arburst=s_axi_a_arburst,
m_axi_arlock=s_axi_a_arlock,
m_axi_arcache=s_axi_a_arcache,
m_axi_arprot=s_axi_a_arprot,
m_axi_arvalid=s_axi_a_arvalid,
m_axi_arready=s_axi_a_arready,
m_axi_rid=s_axi_a_rid,
m_axi_rdata=s_axi_a_rdata,
m_axi_rresp=s_axi_a_rresp,
m_axi_rlast=s_axi_a_rlast,
m_axi_rvalid=s_axi_a_rvalid,
m_axi_rready=s_axi_a_rready,
pause=axi_a_master_pause,
name='master_a'
)
axi_b_master_inst = axi.AXIMaster()
axi_b_master_pause = Signal(bool(False))
axi_b_master_logic = axi_b_master_inst.create_logic(
b_clk,
b_rst,
m_axi_awid=s_axi_b_awid,
m_axi_awaddr=s_axi_b_awaddr,
m_axi_awlen=s_axi_b_awlen,
m_axi_awsize=s_axi_b_awsize,
m_axi_awburst=s_axi_b_awburst,
m_axi_awlock=s_axi_b_awlock,
m_axi_awcache=s_axi_b_awcache,
m_axi_awprot=s_axi_b_awprot,
m_axi_awvalid=s_axi_b_awvalid,
m_axi_awready=s_axi_b_awready,
m_axi_wdata=s_axi_b_wdata,
m_axi_wstrb=s_axi_b_wstrb,
m_axi_wlast=s_axi_b_wlast,
m_axi_wvalid=s_axi_b_wvalid,
m_axi_wready=s_axi_b_wready,
m_axi_bid=s_axi_b_bid,
m_axi_bresp=s_axi_b_bresp,
m_axi_bvalid=s_axi_b_bvalid,
m_axi_bready=s_axi_b_bready,
m_axi_arid=s_axi_b_arid,
m_axi_araddr=s_axi_b_araddr,
m_axi_arlen=s_axi_b_arlen,
m_axi_arsize=s_axi_b_arsize,
m_axi_arburst=s_axi_b_arburst,
m_axi_arlock=s_axi_b_arlock,
m_axi_arcache=s_axi_b_arcache,
m_axi_arprot=s_axi_b_arprot,
m_axi_arvalid=s_axi_b_arvalid,
m_axi_arready=s_axi_b_arready,
m_axi_rid=s_axi_b_rid,
m_axi_rdata=s_axi_b_rdata,
m_axi_rresp=s_axi_b_rresp,
m_axi_rlast=s_axi_b_rlast,
m_axi_rvalid=s_axi_b_rvalid,
m_axi_rready=s_axi_b_rready,
pause=axi_b_master_pause,
name='master_b'
)
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
a_clk=a_clk,
a_rst=a_rst,
b_clk=b_clk,
b_rst=b_rst,
s_axi_a_awid=s_axi_a_awid,
s_axi_a_awaddr=s_axi_a_awaddr,
s_axi_a_awlen=s_axi_a_awlen,
s_axi_a_awsize=s_axi_a_awsize,
s_axi_a_awburst=s_axi_a_awburst,
s_axi_a_awlock=s_axi_a_awlock,
s_axi_a_awcache=s_axi_a_awcache,
s_axi_a_awprot=s_axi_a_awprot,
s_axi_a_awvalid=s_axi_a_awvalid,
s_axi_a_awready=s_axi_a_awready,
s_axi_a_wdata=s_axi_a_wdata,
s_axi_a_wstrb=s_axi_a_wstrb,
s_axi_a_wlast=s_axi_a_wlast,
s_axi_a_wvalid=s_axi_a_wvalid,
s_axi_a_wready=s_axi_a_wready,
s_axi_a_bid=s_axi_a_bid,
s_axi_a_bresp=s_axi_a_bresp,
s_axi_a_bvalid=s_axi_a_bvalid,
s_axi_a_bready=s_axi_a_bready,
s_axi_a_arid=s_axi_a_arid,
s_axi_a_araddr=s_axi_a_araddr,
s_axi_a_arlen=s_axi_a_arlen,
s_axi_a_arsize=s_axi_a_arsize,
s_axi_a_arburst=s_axi_a_arburst,
s_axi_a_arlock=s_axi_a_arlock,
s_axi_a_arcache=s_axi_a_arcache,
s_axi_a_arprot=s_axi_a_arprot,
s_axi_a_arvalid=s_axi_a_arvalid,
s_axi_a_arready=s_axi_a_arready,
s_axi_a_rid=s_axi_a_rid,
s_axi_a_rdata=s_axi_a_rdata,
s_axi_a_rresp=s_axi_a_rresp,
s_axi_a_rlast=s_axi_a_rlast,
s_axi_a_rvalid=s_axi_a_rvalid,
s_axi_a_rready=s_axi_a_rready,
s_axi_b_awid=s_axi_b_awid,
s_axi_b_awaddr=s_axi_b_awaddr,
s_axi_b_awlen=s_axi_b_awlen,
s_axi_b_awsize=s_axi_b_awsize,
s_axi_b_awburst=s_axi_b_awburst,
s_axi_b_awlock=s_axi_b_awlock,
s_axi_b_awcache=s_axi_b_awcache,
s_axi_b_awprot=s_axi_b_awprot,
s_axi_b_awvalid=s_axi_b_awvalid,
s_axi_b_awready=s_axi_b_awready,
s_axi_b_wdata=s_axi_b_wdata,
s_axi_b_wstrb=s_axi_b_wstrb,
s_axi_b_wlast=s_axi_b_wlast,
s_axi_b_wvalid=s_axi_b_wvalid,
s_axi_b_wready=s_axi_b_wready,
s_axi_b_bid=s_axi_b_bid,
s_axi_b_bresp=s_axi_b_bresp,
s_axi_b_bvalid=s_axi_b_bvalid,
s_axi_b_bready=s_axi_b_bready,
s_axi_b_arid=s_axi_b_arid,
s_axi_b_araddr=s_axi_b_araddr,
s_axi_b_arlen=s_axi_b_arlen,
s_axi_b_arsize=s_axi_b_arsize,
s_axi_b_arburst=s_axi_b_arburst,
s_axi_b_arlock=s_axi_b_arlock,
s_axi_b_arcache=s_axi_b_arcache,
s_axi_b_arprot=s_axi_b_arprot,
s_axi_b_arvalid=s_axi_b_arvalid,
s_axi_b_arready=s_axi_b_arready,
s_axi_b_rid=s_axi_b_rid,
s_axi_b_rdata=s_axi_b_rdata,
s_axi_b_rresp=s_axi_b_rresp,
s_axi_b_rlast=s_axi_b_rlast,
s_axi_b_rvalid=s_axi_b_rvalid,
s_axi_b_rready=s_axi_b_rready
)
@always(delay(4))
def clkgen():
clk.next = not clk
a_clk.next = not a_clk
b_clk.next = not b_clk
def wait_normal():
while not axi_a_master_inst.idle() or not axi_b_master_inst.idle():
yield clk.posedge
def wait_pause_master():
while not axi_a_master_inst.idle() or not axi_b_master_inst.idle():
axi_a_master_pause.next = True
axi_b_master_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axi_a_master_pause.next = False
axi_b_master_pause.next = False
yield clk.posedge
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
a_rst.next = 1
b_rst.next = 1
yield clk.posedge
rst.next = 0
a_rst.next = 0
b_rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: read and write, port A")
current_test.next = 1
addr = 4
test_data = b'\x11\x22\x33\x44'
axi_a_master_inst.init_write(addr, test_data)
yield axi_a_master_inst.wait()
yield clk.posedge
axi_a_master_inst.init_read(addr, len(test_data))
yield axi_a_master_inst.wait()
yield clk.posedge
data = axi_a_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
yield clk.posedge
print("test 2: read and write, port B")
current_test.next = 2
addr = 4
test_data = b'\x11\x22\x33\x44'
axi_b_master_inst.init_write(addr, test_data)
yield axi_b_master_inst.wait()
yield clk.posedge
axi_b_master_inst.init_read(addr, len(test_data))
yield axi_b_master_inst.wait()
yield clk.posedge
data = axi_b_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
yield clk.posedge
print("test 3: various reads and writes, port A")
current_test.next = 3
for length in list(range(1,8))+[1024]:
for offset in list(range(4,8))+[4096-4]:
for size in (2, 1, 0):
for wait in wait_normal, wait_pause_master:
print("length %d, offset %d, size %d"% (length, offset, size))
#addr = 256*(16*offset+length)+offset
addr = offset
test_data = bytearray([x%256 for x in range(length)])
axi_a_master_inst.init_write(addr-4, b'\xAA'*(length+8))
yield axi_a_master_inst.wait()
axi_a_master_inst.init_write(addr, test_data, size=size)
yield wait()
axi_a_master_inst.init_read(addr-1, length+2)
yield axi_a_master_inst.wait()
data = axi_a_master_inst.get_read_data()
assert data[0] == addr-1
assert data[1] == b'\xAA'+test_data+b'\xAA'
for length in list(range(1,8))+[1024]:
for offset in list(range(4,8))+[4096-4]:
for size in (2, 1, 0):
for wait in wait_normal, wait_pause_master:
print("length %d, offset %d, size %d"% (length, offset, size))
#addr = 256*(16*offset+length)+offset
addr = offset
test_data = bytearray([x%256 for x in range(length)])
axi_a_master_inst.init_write(addr, test_data)
yield axi_a_master_inst.wait()
axi_a_master_inst.init_read(addr, length, size=size)
yield wait()
yield clk.posedge
data = axi_a_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
yield clk.posedge
print("test 4: various reads and writes, port B")
current_test.next = 4
for length in list(range(1,8))+[1024]:
for offset in list(range(4,8))+[4096-4]:
for size in (2, 1, 0):
for wait in wait_normal, wait_pause_master:
print("length %d, offset %d, size %d"% (length, offset, size))
#addr = 256*(16*offset+length)+offset
addr = offset
test_data = bytearray([x%256 for x in range(length)])
axi_b_master_inst.init_write(addr-4, b'\xAA'*(length+8))
yield axi_b_master_inst.wait()
axi_b_master_inst.init_write(addr, test_data, size=size)
yield wait()
axi_b_master_inst.init_read(addr-1, length+2)
yield axi_b_master_inst.wait()
data = axi_b_master_inst.get_read_data()
assert data[0] == addr-1
assert data[1] == b'\xAA'+test_data+b'\xAA'
for length in list(range(1,8))+[1024]:
for offset in list(range(4,8))+[4096-4]:
for size in (2, 1, 0):
for wait in wait_normal, wait_pause_master:
print("length %d, offset %d, size %d"% (length, offset, size))
#addr = 256*(16*offset+length)+offset
addr = offset
test_data = bytearray([x%256 for x in range(length)])
axi_b_master_inst.init_write(addr, test_data)
yield axi_b_master_inst.wait()
axi_b_master_inst.init_read(addr, length, size=size)
yield wait()
yield clk.posedge
data = axi_b_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
yield clk.posedge
print("test 5: arbitration test")
current_test.next = 5
for k in range(10):
axi_a_master_inst.init_write(k*256, b'\x11\x22\x33\x44')
axi_a_master_inst.init_read(k*256, 4)
axi_b_master_inst.init_write(k*256, b'\x11\x22\x33\x44')
axi_b_master_inst.init_read(k*256, 4)
for k in range(10):
axi_a_master_inst.init_write(k*256, bytearray(range(256)))
axi_a_master_inst.init_read(k*256, 256)
axi_b_master_inst.init_write(k*256, bytearray(range(256)))
axi_b_master_inst.init_read(k*256, 256)
yield wait_normal()
for k in range(20):
axi_a_master_inst.get_read_data()
axi_b_master_inst.get_read_data()
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

302
tb/test_axi_dp_ram.v Normal file
View File

@ -0,0 +1,302 @@
/*
Copyright (c) 2019 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for axi_dp_ram
*/
module test_axi_dp_ram;
// Parameters
parameter DATA_WIDTH = 32;
parameter ADDR_WIDTH = 16;
parameter STRB_WIDTH = (DATA_WIDTH/8);
parameter ID_WIDTH = 8;
parameter A_PIPELINE_OUTPUT = 0;
parameter B_PIPELINE_OUTPUT = 0;
parameter A_INTERLEAVE = 0;
parameter B_INTERLEAVE = 1;
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg a_clk = 0;
reg a_rst = 0;
reg b_clk = 0;
reg b_rst = 0;
reg [ID_WIDTH-1:0] s_axi_a_awid = 0;
reg [ADDR_WIDTH-1:0] s_axi_a_awaddr = 0;
reg [7:0] s_axi_a_awlen = 0;
reg [2:0] s_axi_a_awsize = 0;
reg [1:0] s_axi_a_awburst = 0;
reg s_axi_a_awlock = 0;
reg [3:0] s_axi_a_awcache = 0;
reg [2:0] s_axi_a_awprot = 0;
reg s_axi_a_awvalid = 0;
reg [DATA_WIDTH-1:0] s_axi_a_wdata = 0;
reg [STRB_WIDTH-1:0] s_axi_a_wstrb = 0;
reg s_axi_a_wlast = 0;
reg s_axi_a_wvalid = 0;
reg s_axi_a_bready = 0;
reg [ID_WIDTH-1:0] s_axi_a_arid = 0;
reg [ADDR_WIDTH-1:0] s_axi_a_araddr = 0;
reg [7:0] s_axi_a_arlen = 0;
reg [2:0] s_axi_a_arsize = 0;
reg [1:0] s_axi_a_arburst = 0;
reg s_axi_a_arlock = 0;
reg [3:0] s_axi_a_arcache = 0;
reg [2:0] s_axi_a_arprot = 0;
reg s_axi_a_arvalid = 0;
reg s_axi_a_rready = 0;
reg [ID_WIDTH-1:0] s_axi_b_awid = 0;
reg [ADDR_WIDTH-1:0] s_axi_b_awaddr = 0;
reg [7:0] s_axi_b_awlen = 0;
reg [2:0] s_axi_b_awsize = 0;
reg [1:0] s_axi_b_awburst = 0;
reg s_axi_b_awlock = 0;
reg [3:0] s_axi_b_awcache = 0;
reg [2:0] s_axi_b_awprot = 0;
reg s_axi_b_awvalid = 0;
reg [DATA_WIDTH-1:0] s_axi_b_wdata = 0;
reg [STRB_WIDTH-1:0] s_axi_b_wstrb = 0;
reg s_axi_b_wlast = 0;
reg s_axi_b_wvalid = 0;
reg s_axi_b_bready = 0;
reg [ID_WIDTH-1:0] s_axi_b_arid = 0;
reg [ADDR_WIDTH-1:0] s_axi_b_araddr = 0;
reg [7:0] s_axi_b_arlen = 0;
reg [2:0] s_axi_b_arsize = 0;
reg [1:0] s_axi_b_arburst = 0;
reg s_axi_b_arlock = 0;
reg [3:0] s_axi_b_arcache = 0;
reg [2:0] s_axi_b_arprot = 0;
reg s_axi_b_arvalid = 0;
reg s_axi_b_rready = 0;
// Outputs
wire s_axi_a_awready;
wire s_axi_a_wready;
wire [ID_WIDTH-1:0] s_axi_a_bid;
wire [1:0] s_axi_a_bresp;
wire s_axi_a_bvalid;
wire s_axi_a_arready;
wire [ID_WIDTH-1:0] s_axi_a_rid;
wire [DATA_WIDTH-1:0] s_axi_a_rdata;
wire [1:0] s_axi_a_rresp;
wire s_axi_a_rlast;
wire s_axi_a_rvalid;
wire s_axi_b_awready;
wire s_axi_b_wready;
wire [ID_WIDTH-1:0] s_axi_b_bid;
wire [1:0] s_axi_b_bresp;
wire s_axi_b_bvalid;
wire s_axi_b_arready;
wire [ID_WIDTH-1:0] s_axi_b_rid;
wire [DATA_WIDTH-1:0] s_axi_b_rdata;
wire [1:0] s_axi_b_rresp;
wire s_axi_b_rlast;
wire s_axi_b_rvalid;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
a_clk,
a_rst,
b_clk,
b_rst,
s_axi_a_awid,
s_axi_a_awaddr,
s_axi_a_awlen,
s_axi_a_awsize,
s_axi_a_awburst,
s_axi_a_awlock,
s_axi_a_awcache,
s_axi_a_awprot,
s_axi_a_awvalid,
s_axi_a_wdata,
s_axi_a_wstrb,
s_axi_a_wlast,
s_axi_a_wvalid,
s_axi_a_bready,
s_axi_a_arid,
s_axi_a_araddr,
s_axi_a_arlen,
s_axi_a_arsize,
s_axi_a_arburst,
s_axi_a_arlock,
s_axi_a_arcache,
s_axi_a_arprot,
s_axi_a_arvalid,
s_axi_a_rready,
s_axi_b_awid,
s_axi_b_awaddr,
s_axi_b_awlen,
s_axi_b_awsize,
s_axi_b_awburst,
s_axi_b_awlock,
s_axi_b_awcache,
s_axi_b_awprot,
s_axi_b_awvalid,
s_axi_b_wdata,
s_axi_b_wstrb,
s_axi_b_wlast,
s_axi_b_wvalid,
s_axi_b_bready,
s_axi_b_arid,
s_axi_b_araddr,
s_axi_b_arlen,
s_axi_b_arsize,
s_axi_b_arburst,
s_axi_b_arlock,
s_axi_b_arcache,
s_axi_b_arprot,
s_axi_b_arvalid,
s_axi_b_rready
);
$to_myhdl(
s_axi_a_awready,
s_axi_a_wready,
s_axi_a_bid,
s_axi_a_bresp,
s_axi_a_bvalid,
s_axi_a_arready,
s_axi_a_rid,
s_axi_a_rdata,
s_axi_a_rresp,
s_axi_a_rlast,
s_axi_a_rvalid,
s_axi_b_awready,
s_axi_b_wready,
s_axi_b_bid,
s_axi_b_bresp,
s_axi_b_bvalid,
s_axi_b_arready,
s_axi_b_rid,
s_axi_b_rdata,
s_axi_b_rresp,
s_axi_b_rlast,
s_axi_b_rvalid
);
// dump file
$dumpfile("test_axi_dp_ram.lxt");
$dumpvars(0, test_axi_dp_ram);
end
axi_dp_ram #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.ID_WIDTH(ID_WIDTH),
.A_PIPELINE_OUTPUT(A_PIPELINE_OUTPUT),
.B_PIPELINE_OUTPUT(B_PIPELINE_OUTPUT),
.A_INTERLEAVE(A_INTERLEAVE),
.B_INTERLEAVE(B_INTERLEAVE)
)
UUT (
.a_clk(a_clk),
.a_rst(a_rst),
.b_clk(b_clk),
.b_rst(b_rst),
.s_axi_a_awid(s_axi_a_awid),
.s_axi_a_awaddr(s_axi_a_awaddr),
.s_axi_a_awlen(s_axi_a_awlen),
.s_axi_a_awsize(s_axi_a_awsize),
.s_axi_a_awburst(s_axi_a_awburst),
.s_axi_a_awlock(s_axi_a_awlock),
.s_axi_a_awcache(s_axi_a_awcache),
.s_axi_a_awprot(s_axi_a_awprot),
.s_axi_a_awvalid(s_axi_a_awvalid),
.s_axi_a_awready(s_axi_a_awready),
.s_axi_a_wdata(s_axi_a_wdata),
.s_axi_a_wstrb(s_axi_a_wstrb),
.s_axi_a_wlast(s_axi_a_wlast),
.s_axi_a_wvalid(s_axi_a_wvalid),
.s_axi_a_wready(s_axi_a_wready),
.s_axi_a_bid(s_axi_a_bid),
.s_axi_a_bresp(s_axi_a_bresp),
.s_axi_a_bvalid(s_axi_a_bvalid),
.s_axi_a_bready(s_axi_a_bready),
.s_axi_a_arid(s_axi_a_arid),
.s_axi_a_araddr(s_axi_a_araddr),
.s_axi_a_arlen(s_axi_a_arlen),
.s_axi_a_arsize(s_axi_a_arsize),
.s_axi_a_arburst(s_axi_a_arburst),
.s_axi_a_arlock(s_axi_a_arlock),
.s_axi_a_arcache(s_axi_a_arcache),
.s_axi_a_arprot(s_axi_a_arprot),
.s_axi_a_arvalid(s_axi_a_arvalid),
.s_axi_a_arready(s_axi_a_arready),
.s_axi_a_rid(s_axi_a_rid),
.s_axi_a_rdata(s_axi_a_rdata),
.s_axi_a_rresp(s_axi_a_rresp),
.s_axi_a_rlast(s_axi_a_rlast),
.s_axi_a_rvalid(s_axi_a_rvalid),
.s_axi_a_rready(s_axi_a_rready),
.s_axi_b_awid(s_axi_b_awid),
.s_axi_b_awaddr(s_axi_b_awaddr),
.s_axi_b_awlen(s_axi_b_awlen),
.s_axi_b_awsize(s_axi_b_awsize),
.s_axi_b_awburst(s_axi_b_awburst),
.s_axi_b_awlock(s_axi_b_awlock),
.s_axi_b_awcache(s_axi_b_awcache),
.s_axi_b_awprot(s_axi_b_awprot),
.s_axi_b_awvalid(s_axi_b_awvalid),
.s_axi_b_awready(s_axi_b_awready),
.s_axi_b_wdata(s_axi_b_wdata),
.s_axi_b_wstrb(s_axi_b_wstrb),
.s_axi_b_wlast(s_axi_b_wlast),
.s_axi_b_wvalid(s_axi_b_wvalid),
.s_axi_b_wready(s_axi_b_wready),
.s_axi_b_bid(s_axi_b_bid),
.s_axi_b_bresp(s_axi_b_bresp),
.s_axi_b_bvalid(s_axi_b_bvalid),
.s_axi_b_bready(s_axi_b_bready),
.s_axi_b_arid(s_axi_b_arid),
.s_axi_b_araddr(s_axi_b_araddr),
.s_axi_b_arlen(s_axi_b_arlen),
.s_axi_b_arsize(s_axi_b_arsize),
.s_axi_b_arburst(s_axi_b_arburst),
.s_axi_b_arlock(s_axi_b_arlock),
.s_axi_b_arcache(s_axi_b_arcache),
.s_axi_b_arprot(s_axi_b_arprot),
.s_axi_b_arvalid(s_axi_b_arvalid),
.s_axi_b_arready(s_axi_b_arready),
.s_axi_b_rid(s_axi_b_rid),
.s_axi_b_rdata(s_axi_b_rdata),
.s_axi_b_rresp(s_axi_b_rresp),
.s_axi_b_rlast(s_axi_b_rlast),
.s_axi_b_rvalid(s_axi_b_rvalid),
.s_axi_b_rready(s_axi_b_rready)
);
endmodule