1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-30 08:32:52 +08:00

Add AXI lite width adapter and testbenches

This commit is contained in:
Alex Forencich 2018-08-16 16:37:11 -07:00
parent 48577f3a2d
commit e06d607b85
9 changed files with 2369 additions and 0 deletions

169
rtl/axil_adapter.v Normal file
View File

@ -0,0 +1,169 @@
/*
Copyright (c) 2018 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 lite width adapter
*/
module axil_adapter #
(
parameter ADDR_WIDTH = 16,
parameter S_DATA_WIDTH = 32,
parameter S_STRB_WIDTH = (S_DATA_WIDTH/8),
parameter M_DATA_WIDTH = 32,
parameter M_STRB_WIDTH = (M_DATA_WIDTH/8)
)
(
input wire clk,
input wire rst,
/*
* AXI lite slave interface
*/
input wire [ADDR_WIDTH-1:0] s_axil_awaddr,
input wire [2:0] s_axil_awprot,
input wire s_axil_awvalid,
output wire s_axil_awready,
input wire [S_DATA_WIDTH-1:0] s_axil_wdata,
input wire [S_STRB_WIDTH-1:0] s_axil_wstrb,
input wire s_axil_wvalid,
output wire s_axil_wready,
output wire [1:0] s_axil_bresp,
output wire s_axil_bvalid,
input wire s_axil_bready,
input wire [ADDR_WIDTH-1:0] s_axil_araddr,
input wire [2:0] s_axil_arprot,
input wire s_axil_arvalid,
output wire s_axil_arready,
output wire [S_DATA_WIDTH-1:0] s_axil_rdata,
output wire [1:0] s_axil_rresp,
output wire s_axil_rvalid,
input wire s_axil_rready,
/*
* AXI lite master interface
*/
output wire [ADDR_WIDTH-1:0] m_axil_awaddr,
output wire [2:0] m_axil_awprot,
output wire m_axil_awvalid,
input wire m_axil_awready,
output wire [M_DATA_WIDTH-1:0] m_axil_wdata,
output wire [M_STRB_WIDTH-1:0] m_axil_wstrb,
output wire m_axil_wvalid,
input wire m_axil_wready,
input wire [1:0] m_axil_bresp,
input wire m_axil_bvalid,
output wire m_axil_bready,
output wire [ADDR_WIDTH-1:0] m_axil_araddr,
output wire [2:0] m_axil_arprot,
output wire m_axil_arvalid,
input wire m_axil_arready,
input wire [M_DATA_WIDTH-1:0] m_axil_rdata,
input wire [1:0] m_axil_rresp,
input wire m_axil_rvalid,
output wire m_axil_rready
);
axil_adapter_wr #(
.ADDR_WIDTH(ADDR_WIDTH),
.S_DATA_WIDTH(S_DATA_WIDTH),
.S_STRB_WIDTH(S_STRB_WIDTH),
.M_DATA_WIDTH(M_DATA_WIDTH),
.M_STRB_WIDTH(M_STRB_WIDTH)
)
axil_adapter_wr_inst (
.clk(clk),
.rst(rst),
/*
* AXI lite slave interface
*/
.s_axil_awaddr(s_axil_awaddr),
.s_axil_awprot(s_axil_awprot),
.s_axil_awvalid(s_axil_awvalid),
.s_axil_awready(s_axil_awready),
.s_axil_wdata(s_axil_wdata),
.s_axil_wstrb(s_axil_wstrb),
.s_axil_wvalid(s_axil_wvalid),
.s_axil_wready(s_axil_wready),
.s_axil_bresp(s_axil_bresp),
.s_axil_bvalid(s_axil_bvalid),
.s_axil_bready(s_axil_bready),
/*
* AXI lite master interface
*/
.m_axil_awaddr(m_axil_awaddr),
.m_axil_awprot(m_axil_awprot),
.m_axil_awvalid(m_axil_awvalid),
.m_axil_awready(m_axil_awready),
.m_axil_wdata(m_axil_wdata),
.m_axil_wstrb(m_axil_wstrb),
.m_axil_wvalid(m_axil_wvalid),
.m_axil_wready(m_axil_wready),
.m_axil_bresp(m_axil_bresp),
.m_axil_bvalid(m_axil_bvalid),
.m_axil_bready(m_axil_bready)
);
axil_adapter_rd #(
.ADDR_WIDTH(ADDR_WIDTH),
.S_DATA_WIDTH(S_DATA_WIDTH),
.S_STRB_WIDTH(S_STRB_WIDTH),
.M_DATA_WIDTH(M_DATA_WIDTH),
.M_STRB_WIDTH(M_STRB_WIDTH)
)
axil_adapter_rd_inst (
.clk(clk),
.rst(rst),
/*
* AXI lite slave interface
*/
.s_axil_araddr(s_axil_araddr),
.s_axil_arprot(s_axil_arprot),
.s_axil_arvalid(s_axil_arvalid),
.s_axil_arready(s_axil_arready),
.s_axil_rdata(s_axil_rdata),
.s_axil_rresp(s_axil_rresp),
.s_axil_rvalid(s_axil_rvalid),
.s_axil_rready(s_axil_rready),
/*
* AXI lite master interface
*/
.m_axil_araddr(m_axil_araddr),
.m_axil_arprot(m_axil_arprot),
.m_axil_arvalid(m_axil_arvalid),
.m_axil_arready(m_axil_arready),
.m_axil_rdata(m_axil_rdata),
.m_axil_rresp(m_axil_rresp),
.m_axil_rvalid(m_axil_rvalid),
.m_axil_rready(m_axil_rready)
);
endmodule

262
rtl/axil_adapter_rd.v Normal file
View File

@ -0,0 +1,262 @@
/*
Copyright (c) 2018 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 lite width adapter (read)
*/
module axil_adapter_rd #
(
parameter ADDR_WIDTH = 16,
parameter S_DATA_WIDTH = 32,
parameter S_STRB_WIDTH = (S_DATA_WIDTH/8),
parameter M_DATA_WIDTH = 32,
parameter M_STRB_WIDTH = (M_DATA_WIDTH/8)
)
(
input wire clk,
input wire rst,
/*
* AXI lite slave interface
*/
input wire [ADDR_WIDTH-1:0] s_axil_araddr,
input wire [2:0] s_axil_arprot,
input wire s_axil_arvalid,
output wire s_axil_arready,
output wire [S_DATA_WIDTH-1:0] s_axil_rdata,
output wire [1:0] s_axil_rresp,
output wire s_axil_rvalid,
input wire s_axil_rready,
/*
* AXI lite master interface
*/
output wire [ADDR_WIDTH-1:0] m_axil_araddr,
output wire [2:0] m_axil_arprot,
output wire m_axil_arvalid,
input wire m_axil_arready,
input wire [M_DATA_WIDTH-1:0] m_axil_rdata,
input wire [1:0] m_axil_rresp,
input wire m_axil_rvalid,
output wire m_axil_rready
);
parameter S_ADDR_BIT_OFFSET = $clog2(S_STRB_WIDTH);
parameter M_ADDR_BIT_OFFSET = $clog2(M_STRB_WIDTH);
parameter S_VALID_ADDR_WIDTH = ADDR_WIDTH - S_ADDR_BIT_OFFSET;
parameter M_VALID_ADDR_WIDTH = ADDR_WIDTH - M_ADDR_BIT_OFFSET;
parameter S_WORD_WIDTH = S_STRB_WIDTH;
parameter M_WORD_WIDTH = M_STRB_WIDTH;
parameter S_WORD_SIZE = S_DATA_WIDTH/S_WORD_WIDTH;
parameter M_WORD_SIZE = M_DATA_WIDTH/M_WORD_WIDTH;
parameter EXPAND = M_STRB_WIDTH > S_STRB_WIDTH;
parameter DATA_WIDTH = EXPAND ? M_DATA_WIDTH : S_DATA_WIDTH;
parameter STRB_WIDTH = EXPAND ? M_STRB_WIDTH : S_STRB_WIDTH;
parameter CYCLE_COUNT = EXPAND ? (M_STRB_WIDTH / S_STRB_WIDTH) : (S_STRB_WIDTH / M_STRB_WIDTH);
parameter CYCLE_COUNT_WIDTH = CYCLE_COUNT == 1 ? 1 : $clog2(CYCLE_COUNT);
parameter CYCLE_DATA_WIDTH = DATA_WIDTH / CYCLE_COUNT;
parameter CYCLE_STRB_WIDTH = STRB_WIDTH / CYCLE_COUNT;
// bus width assertions
initial begin
if (S_WORD_SIZE * S_STRB_WIDTH != S_DATA_WIDTH) begin
$error("Error: AXI slave interface data width not evenly divisble");
$finish;
end
if (M_WORD_SIZE * M_STRB_WIDTH != M_DATA_WIDTH) begin
$error("Error: AXI master interface data width not evenly divisble");
$finish;
end
if (S_WORD_SIZE != M_WORD_SIZE) begin
$error("Error: word size mismatch");
$finish;
end
if (2**$clog2(S_WORD_WIDTH) != S_WORD_WIDTH) begin
$error("Error: AXI slave interface word width must be even power of two");
$finish;
end
if (2**$clog2(M_WORD_WIDTH) != M_WORD_WIDTH) begin
$error("Error: AXI master interface word width must be even power of two");
$finish;
end
end
localparam [0:0]
STATE_IDLE = 1'd0,
STATE_DATA = 1'd1;
reg [0:0] state_reg = STATE_IDLE, state_next;
reg [CYCLE_COUNT_WIDTH-1:0] current_cycle_reg = 0, current_cycle_next;
reg s_axil_arready_reg = 1'b0, s_axil_arready_next;
reg [S_DATA_WIDTH-1:0] s_axil_rdata_reg = {S_DATA_WIDTH{1'b0}}, s_axil_rdata_next;
reg [1:0] s_axil_rresp_reg = 2'd0, s_axil_rresp_next;
reg s_axil_rvalid_reg = 1'b0, s_axil_rvalid_next;
reg [ADDR_WIDTH-1:0] m_axil_araddr_reg = {ADDR_WIDTH{1'b0}}, m_axil_araddr_next;
reg [2:0] m_axil_arprot_reg = 3'd0, m_axil_arprot_next;
reg m_axil_arvalid_reg = 1'b0, m_axil_arvalid_next;
reg m_axil_rready_reg = 1'b0, m_axil_rready_next;
assign s_axil_arready = s_axil_arready_reg;
assign s_axil_rdata = s_axil_rdata_reg;
assign s_axil_rresp = s_axil_rresp_reg;
assign s_axil_rvalid = s_axil_rvalid_reg;
assign m_axil_araddr = m_axil_araddr_reg;
assign m_axil_arprot = m_axil_arprot_reg;
assign m_axil_arvalid = m_axil_arvalid_reg;
assign m_axil_rready = m_axil_rready_reg;
always @* begin
state_next = STATE_IDLE;
current_cycle_next = current_cycle_reg;
s_axil_arready_next = 1'b0;
s_axil_rdata_next = s_axil_rdata_reg;
s_axil_rresp_next = s_axil_rresp_reg;
s_axil_rvalid_next = s_axil_rvalid_reg && !s_axil_rready;
m_axil_araddr_next = m_axil_araddr_reg;
m_axil_arprot_next = m_axil_arprot_reg;
m_axil_arvalid_next = m_axil_arvalid_reg && !m_axil_arready;
m_axil_rready_next = 1'b0;
if (CYCLE_COUNT == 1 || EXPAND) begin
// master output is same width or wider; single cycle direct transfer
case (state_reg)
STATE_IDLE: begin
s_axil_arready_next = !m_axil_arvalid;
if (s_axil_arready && s_axil_arvalid) begin
s_axil_arready_next = 1'b0;
m_axil_araddr_next = s_axil_araddr;
m_axil_arprot_next = s_axil_arprot;
m_axil_arvalid_next = 1'b1;
m_axil_rready_next = !m_axil_rvalid;
state_next = STATE_DATA;
end else begin
state_next = STATE_IDLE;
end
end
STATE_DATA: begin
m_axil_rready_next = !s_axil_rvalid;
if (m_axil_rready && m_axil_rvalid) begin
m_axil_rready_next = 1'b0;
if (M_WORD_WIDTH == S_WORD_WIDTH) begin
s_axil_rdata_next = m_axil_rdata;
end else begin
s_axil_rdata_next = m_axil_rdata >> (m_axil_araddr_reg[M_ADDR_BIT_OFFSET - 1:S_ADDR_BIT_OFFSET] * S_DATA_WIDTH);
end
s_axil_rresp_next = m_axil_rresp;
s_axil_rvalid_next = 1'b1;
s_axil_arready_next = !m_axil_arvalid;
state_next = STATE_IDLE;
end else begin
state_next = STATE_DATA;
end
end
endcase
end else begin
// master output is narrower; may need several cycles
case (state_reg)
STATE_IDLE: begin
s_axil_arready_next = !m_axil_arvalid;
current_cycle_next = 0;
s_axil_rresp_next = 2'd0;
if (s_axil_arready && s_axil_arvalid) begin
s_axil_arready_next = 1'b0;
m_axil_araddr_next = s_axil_araddr & ({ADDR_WIDTH{1'b1}} << S_ADDR_BIT_OFFSET);
m_axil_arprot_next = s_axil_arprot;
m_axil_arvalid_next = 1'b1;
m_axil_rready_next = !m_axil_rvalid;
state_next = STATE_DATA;
end else begin
state_next = STATE_IDLE;
end
end
STATE_DATA: begin
m_axil_rready_next = !s_axil_rvalid;
if (m_axil_rready && m_axil_rvalid) begin
m_axil_rready_next = 1'b0;
s_axil_rdata_next[current_cycle_reg*CYCLE_DATA_WIDTH +: CYCLE_DATA_WIDTH] = m_axil_rdata;
if (m_axil_rresp) begin
s_axil_rresp_next = m_axil_rresp;
end
if (current_cycle_reg == CYCLE_COUNT-1) begin
s_axil_rvalid_next = 1'b1;
s_axil_arready_next = !m_axil_arvalid;
state_next = STATE_IDLE;
end else begin
current_cycle_next = current_cycle_reg + 1;
m_axil_araddr_next = m_axil_araddr_reg + CYCLE_STRB_WIDTH;
m_axil_arvalid_next = 1'b1;
state_next = STATE_DATA;
end
end else begin
state_next = STATE_DATA;
end
end
endcase
end
end
always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
s_axil_arready_reg <= 1'b0;
s_axil_rvalid_reg <= 1'b0;
m_axil_arvalid_reg <= 1'b0;
m_axil_rready_reg <= 1'b0;
end else begin
state_reg <= state_next;
s_axil_arready_reg <= s_axil_arready_next;
s_axil_rvalid_reg <= s_axil_rvalid_next;
m_axil_arvalid_reg <= m_axil_arvalid_next;
m_axil_rready_reg <= m_axil_rready_next;
end
current_cycle_reg <= current_cycle_next;
s_axil_rdata_reg <= s_axil_rdata_next;
s_axil_rresp_reg <= s_axil_rresp_next;
m_axil_araddr_reg <= m_axil_araddr_next;
m_axil_arprot_reg <= m_axil_arprot_next;
end
endmodule

324
rtl/axil_adapter_wr.v Normal file
View File

@ -0,0 +1,324 @@
/*
Copyright (c) 2018 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 lite width adapter (write)
*/
module axil_adapter_wr #
(
parameter ADDR_WIDTH = 16,
parameter S_DATA_WIDTH = 32,
parameter S_STRB_WIDTH = (S_DATA_WIDTH/8),
parameter M_DATA_WIDTH = 32,
parameter M_STRB_WIDTH = (M_DATA_WIDTH/8)
)
(
input wire clk,
input wire rst,
/*
* AXI lite slave interface
*/
input wire [ADDR_WIDTH-1:0] s_axil_awaddr,
input wire [2:0] s_axil_awprot,
input wire s_axil_awvalid,
output wire s_axil_awready,
input wire [S_DATA_WIDTH-1:0] s_axil_wdata,
input wire [S_STRB_WIDTH-1:0] s_axil_wstrb,
input wire s_axil_wvalid,
output wire s_axil_wready,
output wire [1:0] s_axil_bresp,
output wire s_axil_bvalid,
input wire s_axil_bready,
/*
* AXI lite master interface
*/
output wire [ADDR_WIDTH-1:0] m_axil_awaddr,
output wire [2:0] m_axil_awprot,
output wire m_axil_awvalid,
input wire m_axil_awready,
output wire [M_DATA_WIDTH-1:0] m_axil_wdata,
output wire [M_STRB_WIDTH-1:0] m_axil_wstrb,
output wire m_axil_wvalid,
input wire m_axil_wready,
input wire [1:0] m_axil_bresp,
input wire m_axil_bvalid,
output wire m_axil_bready
);
parameter S_ADDR_BIT_OFFSET = $clog2(S_STRB_WIDTH);
parameter M_ADDR_BIT_OFFSET = $clog2(M_STRB_WIDTH);
parameter S_VALID_ADDR_WIDTH = ADDR_WIDTH - S_ADDR_BIT_OFFSET;
parameter M_VALID_ADDR_WIDTH = ADDR_WIDTH - M_ADDR_BIT_OFFSET;
parameter S_WORD_WIDTH = S_STRB_WIDTH;
parameter M_WORD_WIDTH = M_STRB_WIDTH;
parameter S_WORD_SIZE = S_DATA_WIDTH/S_WORD_WIDTH;
parameter M_WORD_SIZE = M_DATA_WIDTH/M_WORD_WIDTH;
parameter EXPAND = M_STRB_WIDTH > S_STRB_WIDTH;
parameter DATA_WIDTH = EXPAND ? M_DATA_WIDTH : S_DATA_WIDTH;
parameter STRB_WIDTH = EXPAND ? M_STRB_WIDTH : S_STRB_WIDTH;
parameter CYCLE_COUNT = EXPAND ? (M_STRB_WIDTH / S_STRB_WIDTH) : (S_STRB_WIDTH / M_STRB_WIDTH);
parameter CYCLE_COUNT_WIDTH = CYCLE_COUNT == 1 ? 1 : $clog2(CYCLE_COUNT);
parameter CYCLE_DATA_WIDTH = DATA_WIDTH / CYCLE_COUNT;
parameter CYCLE_STRB_WIDTH = STRB_WIDTH / CYCLE_COUNT;
// bus width assertions
initial begin
if (S_WORD_SIZE * S_STRB_WIDTH != S_DATA_WIDTH) begin
$error("Error: AXI slave interface data width not evenly divisble");
$finish;
end
if (M_WORD_SIZE * M_STRB_WIDTH != M_DATA_WIDTH) begin
$error("Error: AXI master interface data width not evenly divisble");
$finish;
end
if (S_WORD_SIZE != M_WORD_SIZE) begin
$error("Error: word size mismatch");
$finish;
end
if (2**$clog2(S_WORD_WIDTH) != S_WORD_WIDTH) begin
$error("Error: AXI slave interface word width must be even power of two");
$finish;
end
if (2**$clog2(M_WORD_WIDTH) != M_WORD_WIDTH) begin
$error("Error: AXI master interface word width must be even power of two");
$finish;
end
end
localparam [1:0]
STATE_IDLE = 2'd0,
STATE_DATA = 2'd1,
STATE_RESP = 2'd3;
reg [1:0] state_reg = STATE_IDLE, state_next;
reg [DATA_WIDTH-1:0] data_reg = {DATA_WIDTH{1'b0}}, data_next;
reg [STRB_WIDTH-1:0] strb_reg = {STRB_WIDTH{1'b0}}, strb_next;
reg [CYCLE_COUNT_WIDTH-1:0] current_cycle_reg = 0, current_cycle_next;
reg s_axil_awready_reg = 1'b0, s_axil_awready_next;
reg s_axil_wready_reg = 1'b0, s_axil_wready_next;
reg [1:0] s_axil_bresp_reg = 2'd0, s_axil_bresp_next;
reg s_axil_bvalid_reg = 1'b0, s_axil_bvalid_next;
reg [ADDR_WIDTH-1:0] m_axil_awaddr_reg = {ADDR_WIDTH{1'b0}}, m_axil_awaddr_next;
reg [2:0] m_axil_awprot_reg = 3'd0, m_axil_awprot_next;
reg m_axil_awvalid_reg = 1'b0, m_axil_awvalid_next;
reg [M_DATA_WIDTH-1:0] m_axil_wdata_reg = {M_DATA_WIDTH{1'b0}}, m_axil_wdata_next;
reg [M_STRB_WIDTH-1:0] m_axil_wstrb_reg = {M_STRB_WIDTH{1'b0}}, m_axil_wstrb_next;
reg m_axil_wvalid_reg = 1'b0, m_axil_wvalid_next;
reg m_axil_bready_reg = 1'b0, m_axil_bready_next;
assign s_axil_awready = s_axil_awready_reg;
assign s_axil_wready = s_axil_wready_reg;
assign s_axil_bresp = s_axil_bresp_reg;
assign s_axil_bvalid = s_axil_bvalid_reg;
assign m_axil_awaddr = m_axil_awaddr_reg;
assign m_axil_awprot = m_axil_awprot_reg;
assign m_axil_awvalid = m_axil_awvalid_reg;
assign m_axil_wdata = m_axil_wdata_reg;
assign m_axil_wstrb = m_axil_wstrb_reg;
assign m_axil_wvalid = m_axil_wvalid_reg;
assign m_axil_bready = m_axil_bready_reg;
always @* begin
state_next = STATE_IDLE;
data_next = data_reg;
strb_next = strb_reg;
current_cycle_next = current_cycle_reg;
s_axil_awready_next = 1'b0;
s_axil_wready_next = 1'b0;
s_axil_bresp_next = s_axil_bresp_reg;
s_axil_bvalid_next = s_axil_bvalid_reg && !s_axil_bready;
m_axil_awaddr_next = m_axil_awaddr_reg;
m_axil_awprot_next = m_axil_awprot_reg;
m_axil_awvalid_next = m_axil_awvalid_reg && !m_axil_awready;
m_axil_wdata_next = m_axil_wdata_reg;
m_axil_wstrb_next = m_axil_wstrb_reg;
m_axil_wvalid_next = m_axil_wvalid_reg && !m_axil_wready;
m_axil_bready_next = 1'b0;
if (CYCLE_COUNT == 1 || EXPAND) begin
// master output is same width or wider; single cycle direct transfer
case (state_reg)
STATE_IDLE: begin
s_axil_awready_next = !m_axil_awvalid;
if (s_axil_awready && s_axil_awvalid) begin
s_axil_awready_next = 1'b0;
m_axil_awaddr_next = s_axil_awaddr;
m_axil_awprot_next = s_axil_awprot;
m_axil_awvalid_next = 1'b1;
s_axil_wready_next = !m_axil_wvalid;
state_next = STATE_DATA;
end else begin
state_next = STATE_IDLE;
end
end
STATE_DATA: begin
s_axil_wready_next = !m_axil_wvalid;
if (s_axil_wready && s_axil_wvalid) begin
s_axil_wready_next = 1'b0;
if (M_WORD_WIDTH == S_WORD_WIDTH) begin
m_axil_wdata_next = s_axil_wdata;
m_axil_wstrb_next = s_axil_wstrb;
end else begin
m_axil_wdata_next = {(M_WORD_WIDTH/S_WORD_WIDTH){s_axil_wdata}};
m_axil_wstrb_next = s_axil_wstrb << (m_axil_awaddr_reg[M_ADDR_BIT_OFFSET - 1:S_ADDR_BIT_OFFSET] * S_STRB_WIDTH);
end
m_axil_wvalid_next = 1'b1;
m_axil_bready_next = !s_axil_bvalid;
state_next = STATE_RESP;
end else begin
state_next = STATE_DATA;
end
end
STATE_RESP: begin
m_axil_bready_next = !s_axil_bvalid;
if (m_axil_bready && m_axil_bvalid) begin
m_axil_bready_next = 1'b0;
s_axil_bresp_next = m_axil_bresp;
s_axil_bvalid_next = 1'b1;
s_axil_awready_next = !m_axil_awvalid;
state_next = STATE_IDLE;
end else begin
state_next = STATE_RESP;
end
end
endcase
end else begin
// master output is narrower; may need several cycles
case (state_reg)
STATE_IDLE: begin
s_axil_awready_next = !m_axil_awvalid;
current_cycle_next = 0;
s_axil_bresp_next = 2'd0;
if (s_axil_awready && s_axil_awvalid) begin
s_axil_awready_next = 1'b0;
m_axil_awaddr_next = s_axil_awaddr & ({ADDR_WIDTH{1'b1}} << S_ADDR_BIT_OFFSET);
m_axil_awprot_next = s_axil_awprot;
m_axil_awvalid_next = 1'b1;
s_axil_wready_next = !m_axil_wvalid;
state_next = STATE_DATA;
end else begin
state_next = STATE_IDLE;
end
end
STATE_DATA: begin
s_axil_wready_next = !m_axil_wvalid;
if (s_axil_wready && s_axil_wvalid) begin
s_axil_wready_next = 1'b0;
data_next = s_axil_wdata;
strb_next = s_axil_wstrb;
m_axil_wdata_next = s_axil_wdata;
m_axil_wstrb_next = s_axil_wstrb;
m_axil_wvalid_next = 1'b1;
m_axil_bready_next = !s_axil_bvalid;
state_next = STATE_RESP;
end else begin
state_next = STATE_DATA;
end
end
STATE_RESP: begin
m_axil_bready_next = !s_axil_bvalid;
if (m_axil_bready && m_axil_bvalid) begin
m_axil_bready_next = 1'b0;
if (m_axil_bresp != 0) begin
s_axil_bresp_next = m_axil_bresp;
end
if (current_cycle_reg == CYCLE_COUNT-1) begin
s_axil_bvalid_next = 1'b1;
s_axil_awready_next = !m_axil_awvalid;
state_next = STATE_IDLE;
end else begin
current_cycle_next = current_cycle_reg + 1;
m_axil_awaddr_next = m_axil_awaddr_reg + CYCLE_STRB_WIDTH;
m_axil_awvalid_next = 1'b1;
m_axil_wdata_next = data_reg >> (current_cycle_reg+1)*CYCLE_DATA_WIDTH;
m_axil_wstrb_next = strb_reg >> (current_cycle_reg+1)*CYCLE_STRB_WIDTH;
m_axil_wvalid_next = 1'b1;
state_next = STATE_RESP;
end
end else begin
state_next = STATE_RESP;
end
end
endcase
end
end
always @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
s_axil_awready_reg <= 1'b0;
s_axil_wready_reg <= 1'b0;
s_axil_bvalid_reg <= 1'b0;
m_axil_awvalid_reg <= 1'b0;
m_axil_wvalid_reg <= 1'b0;
m_axil_bready_reg <= 1'b0;
end else begin
state_reg <= state_next;
s_axil_awready_reg <= s_axil_awready_next;
s_axil_wready_reg <= s_axil_wready_next;
s_axil_bvalid_reg <= s_axil_bvalid_next;
m_axil_awvalid_reg <= m_axil_awvalid_next;
m_axil_wvalid_reg <= m_axil_wvalid_next;
m_axil_bready_reg <= m_axil_bready_next;
end
data_reg <= data_next;
strb_reg <= strb_next;
current_cycle_reg <= current_cycle_next;
s_axil_bresp_reg <= s_axil_bresp_next;
m_axil_awaddr_reg <= m_axil_awaddr_next;
m_axil_awprot_reg <= m_axil_awprot_next;
m_axil_wdata_reg <= m_axil_wdata_next;
m_axil_wstrb_reg <= m_axil_wstrb_next;
end
endmodule

348
tb/test_axil_adapter_16_32.py Executable file
View File

@ -0,0 +1,348 @@
#!/usr/bin/env python
"""
Copyright (c) 2018 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 axil
module = 'axil_adapter'
testbench = 'test_%s_16_32' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/axil_adapter_rd.v")
srcs.append("../rtl/axil_adapter_wr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
ADDR_WIDTH = 16
S_DATA_WIDTH = 16
S_STRB_WIDTH = (S_DATA_WIDTH/8)
M_DATA_WIDTH = 32
M_STRB_WIDTH = (M_DATA_WIDTH/8)
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
s_axil_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axil_awprot = Signal(intbv(0)[3:])
s_axil_awvalid = Signal(bool(0))
s_axil_wdata = Signal(intbv(0)[S_DATA_WIDTH:])
s_axil_wstrb = Signal(intbv(0)[S_STRB_WIDTH:])
s_axil_wvalid = Signal(bool(0))
s_axil_bready = Signal(bool(0))
s_axil_araddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axil_arprot = Signal(intbv(0)[3:])
s_axil_arvalid = Signal(bool(0))
s_axil_rready = Signal(bool(0))
m_axil_awready = Signal(bool(0))
m_axil_wready = Signal(bool(0))
m_axil_bresp = Signal(intbv(0)[2:])
m_axil_bvalid = Signal(bool(0))
m_axil_arready = Signal(bool(0))
m_axil_rdata = Signal(intbv(0)[M_DATA_WIDTH:])
m_axil_rresp = Signal(intbv(0)[2:])
m_axil_rvalid = Signal(bool(0))
# Outputs
s_axil_awready = Signal(bool(0))
s_axil_wready = Signal(bool(0))
s_axil_bresp = Signal(intbv(0)[2:])
s_axil_bvalid = Signal(bool(0))
s_axil_arready = Signal(bool(0))
s_axil_rdata = Signal(intbv(0)[S_DATA_WIDTH:])
s_axil_rresp = Signal(intbv(0)[2:])
s_axil_rvalid = Signal(bool(0))
m_axil_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
m_axil_awprot = Signal(intbv(0)[3:])
m_axil_awvalid = Signal(bool(0))
m_axil_wdata = Signal(intbv(0)[M_DATA_WIDTH:])
m_axil_wstrb = Signal(intbv(0)[M_STRB_WIDTH:])
m_axil_wvalid = Signal(bool(0))
m_axil_bready = Signal(bool(0))
m_axil_araddr = Signal(intbv(0)[ADDR_WIDTH:])
m_axil_arprot = Signal(intbv(0)[3:])
m_axil_arvalid = Signal(bool(0))
m_axil_rready = Signal(bool(0))
# AXIl4 master
axil_master_inst = axil.AXILiteMaster()
axil_master_pause = Signal(bool(False))
axil_master_logic = axil_master_inst.create_logic(
clk,
rst,
m_axil_awaddr=s_axil_awaddr,
m_axil_awprot=s_axil_awprot,
m_axil_awvalid=s_axil_awvalid,
m_axil_awready=s_axil_awready,
m_axil_wdata=s_axil_wdata,
m_axil_wstrb=s_axil_wstrb,
m_axil_wvalid=s_axil_wvalid,
m_axil_wready=s_axil_wready,
m_axil_bresp=s_axil_bresp,
m_axil_bvalid=s_axil_bvalid,
m_axil_bready=s_axil_bready,
m_axil_araddr=s_axil_araddr,
m_axil_arprot=s_axil_arprot,
m_axil_arvalid=s_axil_arvalid,
m_axil_arready=s_axil_arready,
m_axil_rdata=s_axil_rdata,
m_axil_rresp=s_axil_rresp,
m_axil_rvalid=s_axil_rvalid,
m_axil_rready=s_axil_rready,
pause=axil_master_pause,
name='master'
)
# AXIl4 RAM model
axil_ram_inst = axil.AXILiteRam(2**16)
axil_ram_pause = Signal(bool(False))
axil_ram_port0 = axil_ram_inst.create_port(
clk,
s_axil_awaddr=m_axil_awaddr,
s_axil_awprot=m_axil_awprot,
s_axil_awvalid=m_axil_awvalid,
s_axil_awready=m_axil_awready,
s_axil_wdata=m_axil_wdata,
s_axil_wstrb=m_axil_wstrb,
s_axil_wvalid=m_axil_wvalid,
s_axil_wready=m_axil_wready,
s_axil_bresp=m_axil_bresp,
s_axil_bvalid=m_axil_bvalid,
s_axil_bready=m_axil_bready,
s_axil_araddr=m_axil_araddr,
s_axil_arprot=m_axil_arprot,
s_axil_arvalid=m_axil_arvalid,
s_axil_arready=m_axil_arready,
s_axil_rdata=m_axil_rdata,
s_axil_rresp=m_axil_rresp,
s_axil_rvalid=m_axil_rvalid,
s_axil_rready=m_axil_rready,
pause=axil_ram_pause,
name='port0'
)
# 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,
s_axil_awaddr=s_axil_awaddr,
s_axil_awprot=s_axil_awprot,
s_axil_awvalid=s_axil_awvalid,
s_axil_awready=s_axil_awready,
s_axil_wdata=s_axil_wdata,
s_axil_wstrb=s_axil_wstrb,
s_axil_wvalid=s_axil_wvalid,
s_axil_wready=s_axil_wready,
s_axil_bresp=s_axil_bresp,
s_axil_bvalid=s_axil_bvalid,
s_axil_bready=s_axil_bready,
s_axil_araddr=s_axil_araddr,
s_axil_arprot=s_axil_arprot,
s_axil_arvalid=s_axil_arvalid,
s_axil_arready=s_axil_arready,
s_axil_rdata=s_axil_rdata,
s_axil_rresp=s_axil_rresp,
s_axil_rvalid=s_axil_rvalid,
s_axil_rready=s_axil_rready,
m_axil_awaddr=m_axil_awaddr,
m_axil_awprot=m_axil_awprot,
m_axil_awvalid=m_axil_awvalid,
m_axil_awready=m_axil_awready,
m_axil_wdata=m_axil_wdata,
m_axil_wstrb=m_axil_wstrb,
m_axil_wvalid=m_axil_wvalid,
m_axil_wready=m_axil_wready,
m_axil_bresp=m_axil_bresp,
m_axil_bvalid=m_axil_bvalid,
m_axil_bready=m_axil_bready,
m_axil_araddr=m_axil_araddr,
m_axil_arprot=m_axil_arprot,
m_axil_arvalid=m_axil_arvalid,
m_axil_arready=m_axil_arready,
m_axil_rdata=m_axil_rdata,
m_axil_rresp=m_axil_rresp,
m_axil_rvalid=m_axil_rvalid,
m_axil_rready=m_axil_rready
)
@always(delay(4))
def clkgen():
clk.next = not clk
def wait_normal():
while not axil_master_inst.idle():
yield clk.posedge
def wait_pause_master():
while not axil_master_inst.idle():
axil_master_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axil_master_pause.next = False
yield clk.posedge
def wait_pause_slave():
while not axil_master_inst.idle():
axil_ram_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axil_ram_pause.next = False
yield clk.posedge
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: write")
current_test.next = 1
addr = 4
test_data = b'\x11\x22\x33\x44'
axil_master_inst.init_write(addr, test_data)
yield axil_master_inst.wait()
yield clk.posedge
data = axil_ram_inst.read_mem(addr&0xffffff80, 32)
for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert axil_ram_inst.read_mem(addr, len(test_data)) == test_data
yield delay(100)
yield clk.posedge
print("test 2: read")
current_test.next = 2
addr = 4
test_data = b'\x11\x22\x33\x44'
axil_ram_inst.write_mem(addr, test_data)
axil_master_inst.init_read(addr, len(test_data))
yield axil_master_inst.wait()
yield clk.posedge
data = axil_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
yield clk.posedge
print("test 3: various writes")
current_test.next = 3
for length in range(1,8):
for offset in range(4,8):
for wait in wait_normal, wait_pause_master, wait_pause_slave:
print("length %d, offset %d"% (length, offset))
addr = 256*(16*offset+length)+offset
test_data = bytearray([x%256 for x in range(length)])
axil_ram_inst.write_mem(addr&0xffffff80, b'\xAA'*(length+256))
axil_master_inst.init_write(addr, test_data)
yield wait()
yield clk.posedge
data = axil_ram_inst.read_mem(addr&0xffffff80, 32)
for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert axil_ram_inst.read_mem(addr, length) == test_data
assert axil_ram_inst.read_mem(addr-1, 1) == b'\xAA'
assert axil_ram_inst.read_mem(addr+length, 1) == b'\xAA'
yield delay(100)
yield clk.posedge
print("test 4: various reads")
current_test.next = 4
for length in range(1,8):
for offset in range(4,8):
for wait in wait_normal, wait_pause_master, wait_pause_slave:
print("length %d, offset %d"% (length, offset))
addr = 256*(16*offset+length)+offset
test_data = bytearray([x%256 for x in range(length)])
axil_ram_inst.write_mem(addr, test_data)
axil_master_inst.init_read(addr, length)
yield wait()
yield clk.posedge
data = axil_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,190 @@
/*
Copyright (c) 2018 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 axil_adapter
*/
module test_axil_adapter_16_32;
// Parameters
parameter ADDR_WIDTH = 16;
parameter S_DATA_WIDTH = 16;
parameter S_STRB_WIDTH = (S_DATA_WIDTH/8);
parameter M_DATA_WIDTH = 32;
parameter M_STRB_WIDTH = (M_DATA_WIDTH/8);
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [ADDR_WIDTH-1:0] s_axil_awaddr = 0;
reg [2:0] s_axil_awprot = 0;
reg s_axil_awvalid = 0;
reg [S_DATA_WIDTH-1:0] s_axil_wdata = 0;
reg [S_STRB_WIDTH-1:0] s_axil_wstrb = 0;
reg s_axil_wvalid = 0;
reg s_axil_bready = 0;
reg [ADDR_WIDTH-1:0] s_axil_araddr = 0;
reg [2:0] s_axil_arprot = 0;
reg s_axil_arvalid = 0;
reg s_axil_rready = 0;
reg m_axil_awready = 0;
reg m_axil_wready = 0;
reg [1:0] m_axil_bresp = 0;
reg m_axil_bvalid = 0;
reg m_axil_arready = 0;
reg [M_DATA_WIDTH-1:0] m_axil_rdata = 0;
reg [1:0] m_axil_rresp = 0;
reg m_axil_rvalid = 0;
// Outputs
wire s_axil_awready;
wire s_axil_wready;
wire [1:0] s_axil_bresp;
wire s_axil_bvalid;
wire s_axil_arready;
wire [S_DATA_WIDTH-1:0] s_axil_rdata;
wire [1:0] s_axil_rresp;
wire s_axil_rvalid;
wire [ADDR_WIDTH-1:0] m_axil_awaddr;
wire [2:0] m_axil_awprot;
wire m_axil_awvalid;
wire [M_DATA_WIDTH-1:0] m_axil_wdata;
wire [M_STRB_WIDTH-1:0] m_axil_wstrb;
wire m_axil_wvalid;
wire m_axil_bready;
wire [ADDR_WIDTH-1:0] m_axil_araddr;
wire [2:0] m_axil_arprot;
wire m_axil_arvalid;
wire m_axil_rready;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
s_axil_awaddr,
s_axil_awprot,
s_axil_awvalid,
s_axil_wdata,
s_axil_wstrb,
s_axil_wvalid,
s_axil_bready,
s_axil_araddr,
s_axil_arprot,
s_axil_arvalid,
s_axil_rready,
m_axil_awready,
m_axil_wready,
m_axil_bresp,
m_axil_bvalid,
m_axil_arready,
m_axil_rdata,
m_axil_rresp,
m_axil_rvalid
);
$to_myhdl(
s_axil_awready,
s_axil_wready,
s_axil_bresp,
s_axil_bvalid,
s_axil_arready,
s_axil_rdata,
s_axil_rresp,
s_axil_rvalid,
m_axil_awaddr,
m_axil_awprot,
m_axil_awvalid,
m_axil_wdata,
m_axil_wstrb,
m_axil_wvalid,
m_axil_bready,
m_axil_araddr,
m_axil_arprot,
m_axil_arvalid,
m_axil_rready
);
// dump file
$dumpfile("test_axil_adapter_16_32.lxt");
$dumpvars(0, test_axil_adapter_16_32);
end
axil_adapter #(
.ADDR_WIDTH(ADDR_WIDTH),
.S_DATA_WIDTH(S_DATA_WIDTH),
.S_STRB_WIDTH(S_STRB_WIDTH),
.M_DATA_WIDTH(M_DATA_WIDTH),
.M_STRB_WIDTH(M_STRB_WIDTH)
)
UUT (
.clk(clk),
.rst(rst),
.s_axil_awaddr(s_axil_awaddr),
.s_axil_awprot(s_axil_awprot),
.s_axil_awvalid(s_axil_awvalid),
.s_axil_awready(s_axil_awready),
.s_axil_wdata(s_axil_wdata),
.s_axil_wstrb(s_axil_wstrb),
.s_axil_wvalid(s_axil_wvalid),
.s_axil_wready(s_axil_wready),
.s_axil_bresp(s_axil_bresp),
.s_axil_bvalid(s_axil_bvalid),
.s_axil_bready(s_axil_bready),
.s_axil_araddr(s_axil_araddr),
.s_axil_arprot(s_axil_arprot),
.s_axil_arvalid(s_axil_arvalid),
.s_axil_arready(s_axil_arready),
.s_axil_rdata(s_axil_rdata),
.s_axil_rresp(s_axil_rresp),
.s_axil_rvalid(s_axil_rvalid),
.s_axil_rready(s_axil_rready),
.m_axil_awaddr(m_axil_awaddr),
.m_axil_awprot(m_axil_awprot),
.m_axil_awvalid(m_axil_awvalid),
.m_axil_awready(m_axil_awready),
.m_axil_wdata(m_axil_wdata),
.m_axil_wstrb(m_axil_wstrb),
.m_axil_wvalid(m_axil_wvalid),
.m_axil_wready(m_axil_wready),
.m_axil_bresp(m_axil_bresp),
.m_axil_bvalid(m_axil_bvalid),
.m_axil_bready(m_axil_bready),
.m_axil_araddr(m_axil_araddr),
.m_axil_arprot(m_axil_arprot),
.m_axil_arvalid(m_axil_arvalid),
.m_axil_arready(m_axil_arready),
.m_axil_rdata(m_axil_rdata),
.m_axil_rresp(m_axil_rresp),
.m_axil_rvalid(m_axil_rvalid),
.m_axil_rready(m_axil_rready)
);
endmodule

348
tb/test_axil_adapter_32_16.py Executable file
View File

@ -0,0 +1,348 @@
#!/usr/bin/env python
"""
Copyright (c) 2018 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 axil
module = 'axil_adapter'
testbench = 'test_%s_32_16' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/axil_adapter_rd.v")
srcs.append("../rtl/axil_adapter_wr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
ADDR_WIDTH = 16
S_DATA_WIDTH = 32
S_STRB_WIDTH = (S_DATA_WIDTH/8)
M_DATA_WIDTH = 16
M_STRB_WIDTH = (M_DATA_WIDTH/8)
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
s_axil_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axil_awprot = Signal(intbv(0)[3:])
s_axil_awvalid = Signal(bool(0))
s_axil_wdata = Signal(intbv(0)[S_DATA_WIDTH:])
s_axil_wstrb = Signal(intbv(0)[S_STRB_WIDTH:])
s_axil_wvalid = Signal(bool(0))
s_axil_bready = Signal(bool(0))
s_axil_araddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axil_arprot = Signal(intbv(0)[3:])
s_axil_arvalid = Signal(bool(0))
s_axil_rready = Signal(bool(0))
m_axil_awready = Signal(bool(0))
m_axil_wready = Signal(bool(0))
m_axil_bresp = Signal(intbv(0)[2:])
m_axil_bvalid = Signal(bool(0))
m_axil_arready = Signal(bool(0))
m_axil_rdata = Signal(intbv(0)[M_DATA_WIDTH:])
m_axil_rresp = Signal(intbv(0)[2:])
m_axil_rvalid = Signal(bool(0))
# Outputs
s_axil_awready = Signal(bool(0))
s_axil_wready = Signal(bool(0))
s_axil_bresp = Signal(intbv(0)[2:])
s_axil_bvalid = Signal(bool(0))
s_axil_arready = Signal(bool(0))
s_axil_rdata = Signal(intbv(0)[S_DATA_WIDTH:])
s_axil_rresp = Signal(intbv(0)[2:])
s_axil_rvalid = Signal(bool(0))
m_axil_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
m_axil_awprot = Signal(intbv(0)[3:])
m_axil_awvalid = Signal(bool(0))
m_axil_wdata = Signal(intbv(0)[M_DATA_WIDTH:])
m_axil_wstrb = Signal(intbv(0)[M_STRB_WIDTH:])
m_axil_wvalid = Signal(bool(0))
m_axil_bready = Signal(bool(0))
m_axil_araddr = Signal(intbv(0)[ADDR_WIDTH:])
m_axil_arprot = Signal(intbv(0)[3:])
m_axil_arvalid = Signal(bool(0))
m_axil_rready = Signal(bool(0))
# AXIl4 master
axil_master_inst = axil.AXILiteMaster()
axil_master_pause = Signal(bool(False))
axil_master_logic = axil_master_inst.create_logic(
clk,
rst,
m_axil_awaddr=s_axil_awaddr,
m_axil_awprot=s_axil_awprot,
m_axil_awvalid=s_axil_awvalid,
m_axil_awready=s_axil_awready,
m_axil_wdata=s_axil_wdata,
m_axil_wstrb=s_axil_wstrb,
m_axil_wvalid=s_axil_wvalid,
m_axil_wready=s_axil_wready,
m_axil_bresp=s_axil_bresp,
m_axil_bvalid=s_axil_bvalid,
m_axil_bready=s_axil_bready,
m_axil_araddr=s_axil_araddr,
m_axil_arprot=s_axil_arprot,
m_axil_arvalid=s_axil_arvalid,
m_axil_arready=s_axil_arready,
m_axil_rdata=s_axil_rdata,
m_axil_rresp=s_axil_rresp,
m_axil_rvalid=s_axil_rvalid,
m_axil_rready=s_axil_rready,
pause=axil_master_pause,
name='master'
)
# AXIl4 RAM model
axil_ram_inst = axil.AXILiteRam(2**16)
axil_ram_pause = Signal(bool(False))
axil_ram_port0 = axil_ram_inst.create_port(
clk,
s_axil_awaddr=m_axil_awaddr,
s_axil_awprot=m_axil_awprot,
s_axil_awvalid=m_axil_awvalid,
s_axil_awready=m_axil_awready,
s_axil_wdata=m_axil_wdata,
s_axil_wstrb=m_axil_wstrb,
s_axil_wvalid=m_axil_wvalid,
s_axil_wready=m_axil_wready,
s_axil_bresp=m_axil_bresp,
s_axil_bvalid=m_axil_bvalid,
s_axil_bready=m_axil_bready,
s_axil_araddr=m_axil_araddr,
s_axil_arprot=m_axil_arprot,
s_axil_arvalid=m_axil_arvalid,
s_axil_arready=m_axil_arready,
s_axil_rdata=m_axil_rdata,
s_axil_rresp=m_axil_rresp,
s_axil_rvalid=m_axil_rvalid,
s_axil_rready=m_axil_rready,
pause=axil_ram_pause,
name='port0'
)
# 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,
s_axil_awaddr=s_axil_awaddr,
s_axil_awprot=s_axil_awprot,
s_axil_awvalid=s_axil_awvalid,
s_axil_awready=s_axil_awready,
s_axil_wdata=s_axil_wdata,
s_axil_wstrb=s_axil_wstrb,
s_axil_wvalid=s_axil_wvalid,
s_axil_wready=s_axil_wready,
s_axil_bresp=s_axil_bresp,
s_axil_bvalid=s_axil_bvalid,
s_axil_bready=s_axil_bready,
s_axil_araddr=s_axil_araddr,
s_axil_arprot=s_axil_arprot,
s_axil_arvalid=s_axil_arvalid,
s_axil_arready=s_axil_arready,
s_axil_rdata=s_axil_rdata,
s_axil_rresp=s_axil_rresp,
s_axil_rvalid=s_axil_rvalid,
s_axil_rready=s_axil_rready,
m_axil_awaddr=m_axil_awaddr,
m_axil_awprot=m_axil_awprot,
m_axil_awvalid=m_axil_awvalid,
m_axil_awready=m_axil_awready,
m_axil_wdata=m_axil_wdata,
m_axil_wstrb=m_axil_wstrb,
m_axil_wvalid=m_axil_wvalid,
m_axil_wready=m_axil_wready,
m_axil_bresp=m_axil_bresp,
m_axil_bvalid=m_axil_bvalid,
m_axil_bready=m_axil_bready,
m_axil_araddr=m_axil_araddr,
m_axil_arprot=m_axil_arprot,
m_axil_arvalid=m_axil_arvalid,
m_axil_arready=m_axil_arready,
m_axil_rdata=m_axil_rdata,
m_axil_rresp=m_axil_rresp,
m_axil_rvalid=m_axil_rvalid,
m_axil_rready=m_axil_rready
)
@always(delay(4))
def clkgen():
clk.next = not clk
def wait_normal():
while not axil_master_inst.idle():
yield clk.posedge
def wait_pause_master():
while not axil_master_inst.idle():
axil_master_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axil_master_pause.next = False
yield clk.posedge
def wait_pause_slave():
while not axil_master_inst.idle():
axil_ram_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axil_ram_pause.next = False
yield clk.posedge
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: write")
current_test.next = 1
addr = 4
test_data = b'\x11\x22\x33\x44'
axil_master_inst.init_write(addr, test_data)
yield axil_master_inst.wait()
yield clk.posedge
data = axil_ram_inst.read_mem(addr&0xffffff80, 32)
for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert axil_ram_inst.read_mem(addr, len(test_data)) == test_data
yield delay(100)
yield clk.posedge
print("test 2: read")
current_test.next = 2
addr = 4
test_data = b'\x11\x22\x33\x44'
axil_ram_inst.write_mem(addr, test_data)
axil_master_inst.init_read(addr, len(test_data))
yield axil_master_inst.wait()
yield clk.posedge
data = axil_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
yield clk.posedge
print("test 3: various writes")
current_test.next = 3
for length in range(1,8):
for offset in range(4,8):
for wait in wait_normal, wait_pause_master, wait_pause_slave:
print("length %d, offset %d"% (length, offset))
addr = 256*(16*offset+length)+offset
test_data = bytearray([x%256 for x in range(length)])
axil_ram_inst.write_mem(addr&0xffffff80, b'\xAA'*(length+256))
axil_master_inst.init_write(addr, test_data)
yield wait()
yield clk.posedge
data = axil_ram_inst.read_mem(addr&0xffffff80, 32)
for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert axil_ram_inst.read_mem(addr, length) == test_data
assert axil_ram_inst.read_mem(addr-1, 1) == b'\xAA'
assert axil_ram_inst.read_mem(addr+length, 1) == b'\xAA'
yield delay(100)
yield clk.posedge
print("test 4: various reads")
current_test.next = 4
for length in range(1,8):
for offset in range(4,8):
for wait in wait_normal, wait_pause_master, wait_pause_slave:
print("length %d, offset %d"% (length, offset))
addr = 256*(16*offset+length)+offset
test_data = bytearray([x%256 for x in range(length)])
axil_ram_inst.write_mem(addr, test_data)
axil_master_inst.init_read(addr, length)
yield wait()
yield clk.posedge
data = axil_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,190 @@
/*
Copyright (c) 2018 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 axil_adapter
*/
module test_axil_adapter_32_16;
// Parameters
parameter ADDR_WIDTH = 16;
parameter S_DATA_WIDTH = 32;
parameter S_STRB_WIDTH = (S_DATA_WIDTH/8);
parameter M_DATA_WIDTH = 16;
parameter M_STRB_WIDTH = (M_DATA_WIDTH/8);
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [ADDR_WIDTH-1:0] s_axil_awaddr = 0;
reg [2:0] s_axil_awprot = 0;
reg s_axil_awvalid = 0;
reg [S_DATA_WIDTH-1:0] s_axil_wdata = 0;
reg [S_STRB_WIDTH-1:0] s_axil_wstrb = 0;
reg s_axil_wvalid = 0;
reg s_axil_bready = 0;
reg [ADDR_WIDTH-1:0] s_axil_araddr = 0;
reg [2:0] s_axil_arprot = 0;
reg s_axil_arvalid = 0;
reg s_axil_rready = 0;
reg m_axil_awready = 0;
reg m_axil_wready = 0;
reg [1:0] m_axil_bresp = 0;
reg m_axil_bvalid = 0;
reg m_axil_arready = 0;
reg [M_DATA_WIDTH-1:0] m_axil_rdata = 0;
reg [1:0] m_axil_rresp = 0;
reg m_axil_rvalid = 0;
// Outputs
wire s_axil_awready;
wire s_axil_wready;
wire [1:0] s_axil_bresp;
wire s_axil_bvalid;
wire s_axil_arready;
wire [S_DATA_WIDTH-1:0] s_axil_rdata;
wire [1:0] s_axil_rresp;
wire s_axil_rvalid;
wire [ADDR_WIDTH-1:0] m_axil_awaddr;
wire [2:0] m_axil_awprot;
wire m_axil_awvalid;
wire [M_DATA_WIDTH-1:0] m_axil_wdata;
wire [M_STRB_WIDTH-1:0] m_axil_wstrb;
wire m_axil_wvalid;
wire m_axil_bready;
wire [ADDR_WIDTH-1:0] m_axil_araddr;
wire [2:0] m_axil_arprot;
wire m_axil_arvalid;
wire m_axil_rready;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
s_axil_awaddr,
s_axil_awprot,
s_axil_awvalid,
s_axil_wdata,
s_axil_wstrb,
s_axil_wvalid,
s_axil_bready,
s_axil_araddr,
s_axil_arprot,
s_axil_arvalid,
s_axil_rready,
m_axil_awready,
m_axil_wready,
m_axil_bresp,
m_axil_bvalid,
m_axil_arready,
m_axil_rdata,
m_axil_rresp,
m_axil_rvalid
);
$to_myhdl(
s_axil_awready,
s_axil_wready,
s_axil_bresp,
s_axil_bvalid,
s_axil_arready,
s_axil_rdata,
s_axil_rresp,
s_axil_rvalid,
m_axil_awaddr,
m_axil_awprot,
m_axil_awvalid,
m_axil_wdata,
m_axil_wstrb,
m_axil_wvalid,
m_axil_bready,
m_axil_araddr,
m_axil_arprot,
m_axil_arvalid,
m_axil_rready
);
// dump file
$dumpfile("test_axil_adapter_32_16.lxt");
$dumpvars(0, test_axil_adapter_32_16);
end
axil_adapter #(
.ADDR_WIDTH(ADDR_WIDTH),
.S_DATA_WIDTH(S_DATA_WIDTH),
.S_STRB_WIDTH(S_STRB_WIDTH),
.M_DATA_WIDTH(M_DATA_WIDTH),
.M_STRB_WIDTH(M_STRB_WIDTH)
)
UUT (
.clk(clk),
.rst(rst),
.s_axil_awaddr(s_axil_awaddr),
.s_axil_awprot(s_axil_awprot),
.s_axil_awvalid(s_axil_awvalid),
.s_axil_awready(s_axil_awready),
.s_axil_wdata(s_axil_wdata),
.s_axil_wstrb(s_axil_wstrb),
.s_axil_wvalid(s_axil_wvalid),
.s_axil_wready(s_axil_wready),
.s_axil_bresp(s_axil_bresp),
.s_axil_bvalid(s_axil_bvalid),
.s_axil_bready(s_axil_bready),
.s_axil_araddr(s_axil_araddr),
.s_axil_arprot(s_axil_arprot),
.s_axil_arvalid(s_axil_arvalid),
.s_axil_arready(s_axil_arready),
.s_axil_rdata(s_axil_rdata),
.s_axil_rresp(s_axil_rresp),
.s_axil_rvalid(s_axil_rvalid),
.s_axil_rready(s_axil_rready),
.m_axil_awaddr(m_axil_awaddr),
.m_axil_awprot(m_axil_awprot),
.m_axil_awvalid(m_axil_awvalid),
.m_axil_awready(m_axil_awready),
.m_axil_wdata(m_axil_wdata),
.m_axil_wstrb(m_axil_wstrb),
.m_axil_wvalid(m_axil_wvalid),
.m_axil_wready(m_axil_wready),
.m_axil_bresp(m_axil_bresp),
.m_axil_bvalid(m_axil_bvalid),
.m_axil_bready(m_axil_bready),
.m_axil_araddr(m_axil_araddr),
.m_axil_arprot(m_axil_arprot),
.m_axil_arvalid(m_axil_arvalid),
.m_axil_arready(m_axil_arready),
.m_axil_rdata(m_axil_rdata),
.m_axil_rresp(m_axil_rresp),
.m_axil_rvalid(m_axil_rvalid),
.m_axil_rready(m_axil_rready)
);
endmodule

348
tb/test_axil_adapter_32_32.py Executable file
View File

@ -0,0 +1,348 @@
#!/usr/bin/env python
"""
Copyright (c) 2018 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 axil
module = 'axil_adapter'
testbench = 'test_%s_32_32' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/axil_adapter_rd.v")
srcs.append("../rtl/axil_adapter_wr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
ADDR_WIDTH = 16
S_DATA_WIDTH = 32
S_STRB_WIDTH = (S_DATA_WIDTH/8)
M_DATA_WIDTH = 32
M_STRB_WIDTH = (M_DATA_WIDTH/8)
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
s_axil_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axil_awprot = Signal(intbv(0)[3:])
s_axil_awvalid = Signal(bool(0))
s_axil_wdata = Signal(intbv(0)[S_DATA_WIDTH:])
s_axil_wstrb = Signal(intbv(0)[S_STRB_WIDTH:])
s_axil_wvalid = Signal(bool(0))
s_axil_bready = Signal(bool(0))
s_axil_araddr = Signal(intbv(0)[ADDR_WIDTH:])
s_axil_arprot = Signal(intbv(0)[3:])
s_axil_arvalid = Signal(bool(0))
s_axil_rready = Signal(bool(0))
m_axil_awready = Signal(bool(0))
m_axil_wready = Signal(bool(0))
m_axil_bresp = Signal(intbv(0)[2:])
m_axil_bvalid = Signal(bool(0))
m_axil_arready = Signal(bool(0))
m_axil_rdata = Signal(intbv(0)[M_DATA_WIDTH:])
m_axil_rresp = Signal(intbv(0)[2:])
m_axil_rvalid = Signal(bool(0))
# Outputs
s_axil_awready = Signal(bool(0))
s_axil_wready = Signal(bool(0))
s_axil_bresp = Signal(intbv(0)[2:])
s_axil_bvalid = Signal(bool(0))
s_axil_arready = Signal(bool(0))
s_axil_rdata = Signal(intbv(0)[S_DATA_WIDTH:])
s_axil_rresp = Signal(intbv(0)[2:])
s_axil_rvalid = Signal(bool(0))
m_axil_awaddr = Signal(intbv(0)[ADDR_WIDTH:])
m_axil_awprot = Signal(intbv(0)[3:])
m_axil_awvalid = Signal(bool(0))
m_axil_wdata = Signal(intbv(0)[M_DATA_WIDTH:])
m_axil_wstrb = Signal(intbv(0)[M_STRB_WIDTH:])
m_axil_wvalid = Signal(bool(0))
m_axil_bready = Signal(bool(0))
m_axil_araddr = Signal(intbv(0)[ADDR_WIDTH:])
m_axil_arprot = Signal(intbv(0)[3:])
m_axil_arvalid = Signal(bool(0))
m_axil_rready = Signal(bool(0))
# AXIl4 master
axil_master_inst = axil.AXILiteMaster()
axil_master_pause = Signal(bool(False))
axil_master_logic = axil_master_inst.create_logic(
clk,
rst,
m_axil_awaddr=s_axil_awaddr,
m_axil_awprot=s_axil_awprot,
m_axil_awvalid=s_axil_awvalid,
m_axil_awready=s_axil_awready,
m_axil_wdata=s_axil_wdata,
m_axil_wstrb=s_axil_wstrb,
m_axil_wvalid=s_axil_wvalid,
m_axil_wready=s_axil_wready,
m_axil_bresp=s_axil_bresp,
m_axil_bvalid=s_axil_bvalid,
m_axil_bready=s_axil_bready,
m_axil_araddr=s_axil_araddr,
m_axil_arprot=s_axil_arprot,
m_axil_arvalid=s_axil_arvalid,
m_axil_arready=s_axil_arready,
m_axil_rdata=s_axil_rdata,
m_axil_rresp=s_axil_rresp,
m_axil_rvalid=s_axil_rvalid,
m_axil_rready=s_axil_rready,
pause=axil_master_pause,
name='master'
)
# AXIl4 RAM model
axil_ram_inst = axil.AXILiteRam(2**16)
axil_ram_pause = Signal(bool(False))
axil_ram_port0 = axil_ram_inst.create_port(
clk,
s_axil_awaddr=m_axil_awaddr,
s_axil_awprot=m_axil_awprot,
s_axil_awvalid=m_axil_awvalid,
s_axil_awready=m_axil_awready,
s_axil_wdata=m_axil_wdata,
s_axil_wstrb=m_axil_wstrb,
s_axil_wvalid=m_axil_wvalid,
s_axil_wready=m_axil_wready,
s_axil_bresp=m_axil_bresp,
s_axil_bvalid=m_axil_bvalid,
s_axil_bready=m_axil_bready,
s_axil_araddr=m_axil_araddr,
s_axil_arprot=m_axil_arprot,
s_axil_arvalid=m_axil_arvalid,
s_axil_arready=m_axil_arready,
s_axil_rdata=m_axil_rdata,
s_axil_rresp=m_axil_rresp,
s_axil_rvalid=m_axil_rvalid,
s_axil_rready=m_axil_rready,
pause=axil_ram_pause,
name='port0'
)
# 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,
s_axil_awaddr=s_axil_awaddr,
s_axil_awprot=s_axil_awprot,
s_axil_awvalid=s_axil_awvalid,
s_axil_awready=s_axil_awready,
s_axil_wdata=s_axil_wdata,
s_axil_wstrb=s_axil_wstrb,
s_axil_wvalid=s_axil_wvalid,
s_axil_wready=s_axil_wready,
s_axil_bresp=s_axil_bresp,
s_axil_bvalid=s_axil_bvalid,
s_axil_bready=s_axil_bready,
s_axil_araddr=s_axil_araddr,
s_axil_arprot=s_axil_arprot,
s_axil_arvalid=s_axil_arvalid,
s_axil_arready=s_axil_arready,
s_axil_rdata=s_axil_rdata,
s_axil_rresp=s_axil_rresp,
s_axil_rvalid=s_axil_rvalid,
s_axil_rready=s_axil_rready,
m_axil_awaddr=m_axil_awaddr,
m_axil_awprot=m_axil_awprot,
m_axil_awvalid=m_axil_awvalid,
m_axil_awready=m_axil_awready,
m_axil_wdata=m_axil_wdata,
m_axil_wstrb=m_axil_wstrb,
m_axil_wvalid=m_axil_wvalid,
m_axil_wready=m_axil_wready,
m_axil_bresp=m_axil_bresp,
m_axil_bvalid=m_axil_bvalid,
m_axil_bready=m_axil_bready,
m_axil_araddr=m_axil_araddr,
m_axil_arprot=m_axil_arprot,
m_axil_arvalid=m_axil_arvalid,
m_axil_arready=m_axil_arready,
m_axil_rdata=m_axil_rdata,
m_axil_rresp=m_axil_rresp,
m_axil_rvalid=m_axil_rvalid,
m_axil_rready=m_axil_rready
)
@always(delay(4))
def clkgen():
clk.next = not clk
def wait_normal():
while not axil_master_inst.idle():
yield clk.posedge
def wait_pause_master():
while not axil_master_inst.idle():
axil_master_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axil_master_pause.next = False
yield clk.posedge
def wait_pause_slave():
while not axil_master_inst.idle():
axil_ram_pause.next = True
yield clk.posedge
yield clk.posedge
yield clk.posedge
axil_ram_pause.next = False
yield clk.posedge
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: write")
current_test.next = 1
addr = 4
test_data = b'\x11\x22\x33\x44'
axil_master_inst.init_write(addr, test_data)
yield axil_master_inst.wait()
yield clk.posedge
data = axil_ram_inst.read_mem(addr&0xffffff80, 32)
for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert axil_ram_inst.read_mem(addr, len(test_data)) == test_data
yield delay(100)
yield clk.posedge
print("test 2: read")
current_test.next = 2
addr = 4
test_data = b'\x11\x22\x33\x44'
axil_ram_inst.write_mem(addr, test_data)
axil_master_inst.init_read(addr, len(test_data))
yield axil_master_inst.wait()
yield clk.posedge
data = axil_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
yield clk.posedge
print("test 3: various writes")
current_test.next = 3
for length in range(1,8):
for offset in range(4,8):
for wait in wait_normal, wait_pause_master, wait_pause_slave:
print("length %d, offset %d"% (length, offset))
addr = 256*(16*offset+length)+offset
test_data = bytearray([x%256 for x in range(length)])
axil_ram_inst.write_mem(addr&0xffffff80, b'\xAA'*(length+256))
axil_master_inst.init_write(addr, test_data)
yield wait()
yield clk.posedge
data = axil_ram_inst.read_mem(addr&0xffffff80, 32)
for i in range(0, len(data), 16):
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
assert axil_ram_inst.read_mem(addr, length) == test_data
assert axil_ram_inst.read_mem(addr-1, 1) == b'\xAA'
assert axil_ram_inst.read_mem(addr+length, 1) == b'\xAA'
yield delay(100)
yield clk.posedge
print("test 4: various reads")
current_test.next = 4
for length in range(1,8):
for offset in range(4,8):
for wait in wait_normal, wait_pause_master, wait_pause_slave:
print("length %d, offset %d"% (length, offset))
addr = 256*(16*offset+length)+offset
test_data = bytearray([x%256 for x in range(length)])
axil_ram_inst.write_mem(addr, test_data)
axil_master_inst.init_read(addr, length)
yield wait()
yield clk.posedge
data = axil_master_inst.get_read_data()
assert data[0] == addr
assert data[1] == test_data
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

View File

@ -0,0 +1,190 @@
/*
Copyright (c) 2018 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 axil_adapter
*/
module test_axil_adapter_32_32;
// Parameters
parameter ADDR_WIDTH = 16;
parameter S_DATA_WIDTH = 32;
parameter S_STRB_WIDTH = (S_DATA_WIDTH/8);
parameter M_DATA_WIDTH = 32;
parameter M_STRB_WIDTH = (M_DATA_WIDTH/8);
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [ADDR_WIDTH-1:0] s_axil_awaddr = 0;
reg [2:0] s_axil_awprot = 0;
reg s_axil_awvalid = 0;
reg [S_DATA_WIDTH-1:0] s_axil_wdata = 0;
reg [S_STRB_WIDTH-1:0] s_axil_wstrb = 0;
reg s_axil_wvalid = 0;
reg s_axil_bready = 0;
reg [ADDR_WIDTH-1:0] s_axil_araddr = 0;
reg [2:0] s_axil_arprot = 0;
reg s_axil_arvalid = 0;
reg s_axil_rready = 0;
reg m_axil_awready = 0;
reg m_axil_wready = 0;
reg [1:0] m_axil_bresp = 0;
reg m_axil_bvalid = 0;
reg m_axil_arready = 0;
reg [M_DATA_WIDTH-1:0] m_axil_rdata = 0;
reg [1:0] m_axil_rresp = 0;
reg m_axil_rvalid = 0;
// Outputs
wire s_axil_awready;
wire s_axil_wready;
wire [1:0] s_axil_bresp;
wire s_axil_bvalid;
wire s_axil_arready;
wire [S_DATA_WIDTH-1:0] s_axil_rdata;
wire [1:0] s_axil_rresp;
wire s_axil_rvalid;
wire [ADDR_WIDTH-1:0] m_axil_awaddr;
wire [2:0] m_axil_awprot;
wire m_axil_awvalid;
wire [M_DATA_WIDTH-1:0] m_axil_wdata;
wire [M_STRB_WIDTH-1:0] m_axil_wstrb;
wire m_axil_wvalid;
wire m_axil_bready;
wire [ADDR_WIDTH-1:0] m_axil_araddr;
wire [2:0] m_axil_arprot;
wire m_axil_arvalid;
wire m_axil_rready;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
s_axil_awaddr,
s_axil_awprot,
s_axil_awvalid,
s_axil_wdata,
s_axil_wstrb,
s_axil_wvalid,
s_axil_bready,
s_axil_araddr,
s_axil_arprot,
s_axil_arvalid,
s_axil_rready,
m_axil_awready,
m_axil_wready,
m_axil_bresp,
m_axil_bvalid,
m_axil_arready,
m_axil_rdata,
m_axil_rresp,
m_axil_rvalid
);
$to_myhdl(
s_axil_awready,
s_axil_wready,
s_axil_bresp,
s_axil_bvalid,
s_axil_arready,
s_axil_rdata,
s_axil_rresp,
s_axil_rvalid,
m_axil_awaddr,
m_axil_awprot,
m_axil_awvalid,
m_axil_wdata,
m_axil_wstrb,
m_axil_wvalid,
m_axil_bready,
m_axil_araddr,
m_axil_arprot,
m_axil_arvalid,
m_axil_rready
);
// dump file
$dumpfile("test_axil_adapter_32_32.lxt");
$dumpvars(0, test_axil_adapter_32_32);
end
axil_adapter #(
.ADDR_WIDTH(ADDR_WIDTH),
.S_DATA_WIDTH(S_DATA_WIDTH),
.S_STRB_WIDTH(S_STRB_WIDTH),
.M_DATA_WIDTH(M_DATA_WIDTH),
.M_STRB_WIDTH(M_STRB_WIDTH)
)
UUT (
.clk(clk),
.rst(rst),
.s_axil_awaddr(s_axil_awaddr),
.s_axil_awprot(s_axil_awprot),
.s_axil_awvalid(s_axil_awvalid),
.s_axil_awready(s_axil_awready),
.s_axil_wdata(s_axil_wdata),
.s_axil_wstrb(s_axil_wstrb),
.s_axil_wvalid(s_axil_wvalid),
.s_axil_wready(s_axil_wready),
.s_axil_bresp(s_axil_bresp),
.s_axil_bvalid(s_axil_bvalid),
.s_axil_bready(s_axil_bready),
.s_axil_araddr(s_axil_araddr),
.s_axil_arprot(s_axil_arprot),
.s_axil_arvalid(s_axil_arvalid),
.s_axil_arready(s_axil_arready),
.s_axil_rdata(s_axil_rdata),
.s_axil_rresp(s_axil_rresp),
.s_axil_rvalid(s_axil_rvalid),
.s_axil_rready(s_axil_rready),
.m_axil_awaddr(m_axil_awaddr),
.m_axil_awprot(m_axil_awprot),
.m_axil_awvalid(m_axil_awvalid),
.m_axil_awready(m_axil_awready),
.m_axil_wdata(m_axil_wdata),
.m_axil_wstrb(m_axil_wstrb),
.m_axil_wvalid(m_axil_wvalid),
.m_axil_wready(m_axil_wready),
.m_axil_bresp(m_axil_bresp),
.m_axil_bvalid(m_axil_bvalid),
.m_axil_bready(m_axil_bready),
.m_axil_araddr(m_axil_araddr),
.m_axil_arprot(m_axil_arprot),
.m_axil_arvalid(m_axil_arvalid),
.m_axil_arready(m_axil_arready),
.m_axil_rdata(m_axil_rdata),
.m_axil_rresp(m_axil_rresp),
.m_axil_rvalid(m_axil_rvalid),
.m_axil_rready(m_axil_rready)
);
endmodule