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

Add AXI lite registers and testbenches

This commit is contained in:
Alex Forencich 2018-08-16 13:01:45 -07:00
parent 97cbbd1781
commit d541c64bc0
9 changed files with 2350 additions and 0 deletions

173
rtl/axil_register.v Normal file
View File

@ -0,0 +1,173 @@
/*
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 register
*/
module axil_register #
(
parameter DATA_WIDTH = 32,
parameter ADDR_WIDTH = 16,
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter AW_REG_TYPE = 1,
parameter W_REG_TYPE = 1,
parameter B_REG_TYPE = 1,
parameter AR_REG_TYPE = 1,
parameter R_REG_TYPE = 1
)
(
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 [DATA_WIDTH-1:0] s_axil_wdata,
input wire [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 [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 [DATA_WIDTH-1:0] m_axil_wdata,
output wire [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 [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_register_wr #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.AW_REG_TYPE(AW_REG_TYPE),
.W_REG_TYPE(W_REG_TYPE),
.B_REG_TYPE(B_REG_TYPE)
)
axil_register_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_register_rd #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.AR_REG_TYPE(AR_REG_TYPE),
.R_REG_TYPE(R_REG_TYPE)
)
axil_register_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

365
rtl/axil_register_rd.v Normal file
View File

@ -0,0 +1,365 @@
/*
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 register (read)
*/
module axil_register_rd #
(
parameter DATA_WIDTH = 32,
parameter ADDR_WIDTH = 16,
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter AR_REG_TYPE = 1,
parameter R_REG_TYPE = 1
)
(
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 [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 [DATA_WIDTH-1:0] m_axil_rdata,
input wire [1:0] m_axil_rresp,
input wire m_axil_rvalid,
output wire m_axil_rready
);
generate
// AR channel
if (AR_REG_TYPE > 1) begin
// skid buffer, no bubble cycles
// datapath registers
reg s_axil_arready_reg = 1'b0;
reg [ADDR_WIDTH-1:0] m_axil_araddr_reg = {ADDR_WIDTH{1'b0}};
reg [2:0] m_axil_arprot_reg = 3'd0;
reg m_axil_arvalid_reg = 1'b0, m_axil_arvalid_next;
reg [ADDR_WIDTH-1:0] temp_m_axil_araddr_reg = {ADDR_WIDTH{1'b0}};
reg [2:0] temp_m_axil_arprot_reg = 3'd0;
reg temp_m_axil_arvalid_reg = 1'b0, temp_m_axil_arvalid_next;
// datapath control
reg store_axil_ar_input_to_output;
reg store_axil_ar_input_to_temp;
reg store_axil_ar_temp_to_output;
assign s_axil_arready = s_axil_arready_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;
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
wire s_axil_arready_early = m_axil_arready | (~temp_m_axil_arvalid_reg & (~m_axil_arvalid_reg | ~s_axil_arvalid));
always @* begin
// transfer sink ready state to source
m_axil_arvalid_next = m_axil_arvalid_reg;
temp_m_axil_arvalid_next = temp_m_axil_arvalid_reg;
store_axil_ar_input_to_output = 1'b0;
store_axil_ar_input_to_temp = 1'b0;
store_axil_ar_temp_to_output = 1'b0;
if (s_axil_arready_reg) begin
// input is ready
if (m_axil_arready | ~m_axil_arvalid_reg) begin
// output is ready or currently not valid, transfer data to output
m_axil_arvalid_next = s_axil_arvalid;
store_axil_ar_input_to_output = 1'b1;
end else begin
// output is not ready, store input in temp
temp_m_axil_arvalid_next = s_axil_arvalid;
store_axil_ar_input_to_temp = 1'b1;
end
end else if (m_axil_arready) begin
// input is not ready, but output is ready
m_axil_arvalid_next = temp_m_axil_arvalid_reg;
temp_m_axil_arvalid_next = 1'b0;
store_axil_ar_temp_to_output = 1'b1;
end
end
always @(posedge clk) begin
if (rst) begin
s_axil_arready_reg <= 1'b0;
m_axil_arvalid_reg <= 1'b0;
temp_m_axil_arvalid_reg <= 1'b0;
end else begin
s_axil_arready_reg <= s_axil_arready_early;
m_axil_arvalid_reg <= m_axil_arvalid_next;
temp_m_axil_arvalid_reg <= temp_m_axil_arvalid_next;
end
// datapath
if (store_axil_ar_input_to_output) begin
m_axil_araddr_reg <= s_axil_araddr;
m_axil_arprot_reg <= s_axil_arprot;
end else if (store_axil_ar_temp_to_output) begin
m_axil_araddr_reg <= temp_m_axil_araddr_reg;
m_axil_arprot_reg <= temp_m_axil_arprot_reg;
end
if (store_axil_ar_input_to_temp) begin
temp_m_axil_araddr_reg <= s_axil_araddr;
temp_m_axil_arprot_reg <= s_axil_arprot;
end
end
end else if (AR_REG_TYPE == 1) begin
// simple register, inserts bubble cycles
// datapath registers
reg s_axil_arready_reg = 1'b0;
reg [ADDR_WIDTH-1:0] m_axil_araddr_reg = {ADDR_WIDTH{1'b0}};
reg [2:0] m_axil_arprot_reg = 3'd0;
reg m_axil_arvalid_reg = 1'b0, m_axil_arvalid_next;
// datapath control
reg store_axil_ar_input_to_output;
assign s_axil_arready = s_axil_arready_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;
// enable ready input next cycle if output buffer will be empty
wire s_axil_arready_early = !m_axil_arvalid_next;
always @* begin
// transfer sink ready state to source
m_axil_arvalid_next = m_axil_arvalid_reg;
store_axil_ar_input_to_output = 1'b0;
if (s_axil_arready_reg) begin
m_axil_arvalid_next = s_axil_arvalid;
store_axil_ar_input_to_output = 1'b1;
end else if (m_axil_arready) begin
m_axil_arvalid_next = 1'b0;
end
end
always @(posedge clk) begin
if (rst) begin
s_axil_arready_reg <= 1'b0;
m_axil_arvalid_reg <= 1'b0;
end else begin
s_axil_arready_reg <= s_axil_arready_early;
m_axil_arvalid_reg <= m_axil_arvalid_next;
end
// datapath
if (store_axil_ar_input_to_output) begin
m_axil_araddr_reg <= s_axil_araddr;
m_axil_arprot_reg <= s_axil_arprot;
end
end
end else begin
// bypass AR channel
assign m_axil_araddr = s_axil_araddr;
assign m_axil_arprot = s_axil_arprot;
assign m_axil_arvalid = s_axil_arvalid;
assign s_axil_arready = m_axil_arready;
end
// R channel
if (R_REG_TYPE > 1) begin
// skid buffer, no bubble cycles
// datapath registers
reg m_axil_rready_reg = 1'b0;
reg [DATA_WIDTH-1:0] s_axil_rdata_reg = {DATA_WIDTH{1'b0}};
reg [1:0] s_axil_rresp_reg = 2'b0;
reg s_axil_rvalid_reg = 1'b0, s_axil_rvalid_next;
reg [DATA_WIDTH-1:0] temp_s_axil_rdata_reg = {DATA_WIDTH{1'b0}};
reg [1:0] temp_s_axil_rresp_reg = 2'b0;
reg temp_s_axil_rvalid_reg = 1'b0, temp_s_axil_rvalid_next;
// datapath control
reg store_axil_r_input_to_output;
reg store_axil_r_input_to_temp;
reg store_axil_r_temp_to_output;
assign m_axil_rready = m_axil_rready_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;
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
wire m_axil_rready_early = s_axil_rready | (~temp_s_axil_rvalid_reg & (~s_axil_rvalid_reg | ~m_axil_rvalid));
always @* begin
// transfer sink ready state to source
s_axil_rvalid_next = s_axil_rvalid_reg;
temp_s_axil_rvalid_next = temp_s_axil_rvalid_reg;
store_axil_r_input_to_output = 1'b0;
store_axil_r_input_to_temp = 1'b0;
store_axil_r_temp_to_output = 1'b0;
if (m_axil_rready_reg) begin
// input is ready
if (s_axil_rready | ~s_axil_rvalid_reg) begin
// output is ready or currently not valid, transfer data to output
s_axil_rvalid_next = m_axil_rvalid;
store_axil_r_input_to_output = 1'b1;
end else begin
// output is not ready, store input in temp
temp_s_axil_rvalid_next = m_axil_rvalid;
store_axil_r_input_to_temp = 1'b1;
end
end else if (s_axil_rready) begin
// input is not ready, but output is ready
s_axil_rvalid_next = temp_s_axil_rvalid_reg;
temp_s_axil_rvalid_next = 1'b0;
store_axil_r_temp_to_output = 1'b1;
end
end
always @(posedge clk) begin
if (rst) begin
m_axil_rready_reg <= 1'b0;
s_axil_rvalid_reg <= 1'b0;
temp_s_axil_rvalid_reg <= 1'b0;
end else begin
m_axil_rready_reg <= m_axil_rready_early;
s_axil_rvalid_reg <= s_axil_rvalid_next;
temp_s_axil_rvalid_reg <= temp_s_axil_rvalid_next;
end
// datapath
if (store_axil_r_input_to_output) begin
s_axil_rdata_reg <= m_axil_rdata;
s_axil_rresp_reg <= m_axil_rresp;
end else if (store_axil_r_temp_to_output) begin
s_axil_rdata_reg <= temp_s_axil_rdata_reg;
s_axil_rresp_reg <= temp_s_axil_rresp_reg;
end
if (store_axil_r_input_to_temp) begin
temp_s_axil_rdata_reg <= m_axil_rdata;
temp_s_axil_rresp_reg <= m_axil_rresp;
end
end
end else if (R_REG_TYPE == 1) begin
// simple register, inserts bubble cycles
// datapath registers
reg m_axil_rready_reg = 1'b0;
reg [DATA_WIDTH-1:0] s_axil_rdata_reg = {DATA_WIDTH{1'b0}};
reg [1:0] s_axil_rresp_reg = 2'b0;
reg s_axil_rvalid_reg = 1'b0, s_axil_rvalid_next;
// datapath control
reg store_axil_r_input_to_output;
assign m_axil_rready = m_axil_rready_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;
// enable ready input next cycle if output buffer will be empty
wire m_axil_rready_early = !s_axil_rvalid_next;
always @* begin
// transfer sink ready state to source
s_axil_rvalid_next = s_axil_rvalid_reg;
store_axil_r_input_to_output = 1'b0;
if (m_axil_rready_reg) begin
s_axil_rvalid_next = m_axil_rvalid;
store_axil_r_input_to_output = 1'b1;
end else if (s_axil_rready) begin
s_axil_rvalid_next = 1'b0;
end
end
always @(posedge clk) begin
if (rst) begin
m_axil_rready_reg <= 1'b0;
s_axil_rvalid_reg <= 1'b0;
end else begin
m_axil_rready_reg <= m_axil_rready_early;
s_axil_rvalid_reg <= s_axil_rvalid_next;
end
// datapath
if (store_axil_r_input_to_output) begin
s_axil_rdata_reg <= m_axil_rdata;
s_axil_rresp_reg <= m_axil_rresp;
end
end
end else begin
// bypass R channel
assign s_axil_rdata = m_axil_rdata;
assign s_axil_rresp = m_axil_rresp;
assign s_axil_rvalid = m_axil_rvalid;
assign m_axil_rready = s_axil_rready;
end
endgenerate
endmodule

509
rtl/axil_register_wr.v Normal file
View File

@ -0,0 +1,509 @@
/*
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 register (write)
*/
module axil_register_wr #
(
parameter DATA_WIDTH = 32,
parameter ADDR_WIDTH = 16,
parameter STRB_WIDTH = (DATA_WIDTH/8),
parameter ID_WIDTH = 8,
parameter AW_REG_TYPE = 1,
parameter W_REG_TYPE = 1,
parameter B_REG_TYPE = 1
)
(
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 [DATA_WIDTH-1:0] s_axil_wdata,
input wire [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 [DATA_WIDTH-1:0] m_axil_wdata,
output wire [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
);
generate
// AW channel
if (AW_REG_TYPE > 1) begin
// skid buffer, no bubble cycles
// datapath registers
reg s_axil_awready_reg = 1'b0;
reg [ADDR_WIDTH-1:0] m_axil_awaddr_reg = {ADDR_WIDTH{1'b0}};
reg [2:0] m_axil_awprot_reg = 3'd0;
reg m_axil_awvalid_reg = 1'b0, m_axil_awvalid_next;
reg [ADDR_WIDTH-1:0] temp_m_axil_awaddr_reg = {ADDR_WIDTH{1'b0}};
reg [2:0] temp_m_axil_awprot_reg = 3'd0;
reg temp_m_axil_awvalid_reg = 1'b0, temp_m_axil_awvalid_next;
// datapath control
reg store_axil_aw_input_to_output;
reg store_axil_aw_input_to_temp;
reg store_axil_aw_temp_to_output;
assign s_axil_awready = s_axil_awready_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;
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
wire s_axil_awready_early = m_axil_awready | (~temp_m_axil_awvalid_reg & (~m_axil_awvalid_reg | ~s_axil_awvalid));
always @* begin
// transfer sink ready state to source
m_axil_awvalid_next = m_axil_awvalid_reg;
temp_m_axil_awvalid_next = temp_m_axil_awvalid_reg;
store_axil_aw_input_to_output = 1'b0;
store_axil_aw_input_to_temp = 1'b0;
store_axil_aw_temp_to_output = 1'b0;
if (s_axil_awready_reg) begin
// input is ready
if (m_axil_awready | ~m_axil_awvalid_reg) begin
// output is ready or currently not valid, transfer data to output
m_axil_awvalid_next = s_axil_awvalid;
store_axil_aw_input_to_output = 1'b1;
end else begin
// output is not ready, store input in temp
temp_m_axil_awvalid_next = s_axil_awvalid;
store_axil_aw_input_to_temp = 1'b1;
end
end else if (m_axil_awready) begin
// input is not ready, but output is ready
m_axil_awvalid_next = temp_m_axil_awvalid_reg;
temp_m_axil_awvalid_next = 1'b0;
store_axil_aw_temp_to_output = 1'b1;
end
end
always @(posedge clk) begin
if (rst) begin
s_axil_awready_reg <= 1'b0;
m_axil_awvalid_reg <= 1'b0;
temp_m_axil_awvalid_reg <= 1'b0;
end else begin
s_axil_awready_reg <= s_axil_awready_early;
m_axil_awvalid_reg <= m_axil_awvalid_next;
temp_m_axil_awvalid_reg <= temp_m_axil_awvalid_next;
end
// datapath
if (store_axil_aw_input_to_output) begin
m_axil_awaddr_reg <= s_axil_awaddr;
m_axil_awprot_reg <= s_axil_awprot;
end else if (store_axil_aw_temp_to_output) begin
m_axil_awaddr_reg <= temp_m_axil_awaddr_reg;
m_axil_awprot_reg <= temp_m_axil_awprot_reg;
end
if (store_axil_aw_input_to_temp) begin
temp_m_axil_awaddr_reg <= s_axil_awaddr;
temp_m_axil_awprot_reg <= s_axil_awprot;
end
end
end else if (AW_REG_TYPE == 1) begin
// simple register, inserts bubble cycles
// datapath registers
reg s_axil_awready_reg = 1'b0;
reg [ADDR_WIDTH-1:0] m_axil_awaddr_reg = {ADDR_WIDTH{1'b0}};
reg [2:0] m_axil_awprot_reg = 3'd0;
reg m_axil_awvalid_reg = 1'b0, m_axil_awvalid_next;
// datapath control
reg store_axil_aw_input_to_output;
assign s_axil_awready = s_axil_awready_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;
// enable ready input next cycle if output buffer will be empty
wire s_axil_awready_eawly = !m_axil_awvalid_next;
always @* begin
// transfer sink ready state to source
m_axil_awvalid_next = m_axil_awvalid_reg;
store_axil_aw_input_to_output = 1'b0;
if (s_axil_awready_reg) begin
m_axil_awvalid_next = s_axil_awvalid;
store_axil_aw_input_to_output = 1'b1;
end else if (m_axil_awready) begin
m_axil_awvalid_next = 1'b0;
end
end
always @(posedge clk) begin
if (rst) begin
s_axil_awready_reg <= 1'b0;
m_axil_awvalid_reg <= 1'b0;
end else begin
s_axil_awready_reg <= s_axil_awready_eawly;
m_axil_awvalid_reg <= m_axil_awvalid_next;
end
// datapath
if (store_axil_aw_input_to_output) begin
m_axil_awaddr_reg <= s_axil_awaddr;
m_axil_awprot_reg <= s_axil_awprot;
end
end
end else begin
// bypass AW channel
assign m_axil_awaddr = s_axil_awaddr;
assign m_axil_awprot = s_axil_awprot;
assign m_axil_awvalid = s_axil_awvalid;
assign s_axil_awready = m_axil_awready;
end
// W channel
if (W_REG_TYPE > 1) begin
// skid buffer, no bubble cycles
// datapath registers
reg s_axil_wready_reg = 1'b0;
reg [DATA_WIDTH-1:0] m_axil_wdata_reg = {DATA_WIDTH{1'b0}};
reg [STRB_WIDTH-1:0] m_axil_wstrb_reg = {STRB_WIDTH{1'b0}};
reg m_axil_wvalid_reg = 1'b0, m_axil_wvalid_next;
reg [DATA_WIDTH-1:0] temp_m_axil_wdata_reg = {DATA_WIDTH{1'b0}};
reg [STRB_WIDTH-1:0] temp_m_axil_wstrb_reg = {STRB_WIDTH{1'b0}};
reg temp_m_axil_wvalid_reg = 1'b0, temp_m_axil_wvalid_next;
// datapath control
reg store_axil_w_input_to_output;
reg store_axil_w_input_to_temp;
reg store_axil_w_temp_to_output;
assign s_axil_wready = s_axil_wready_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;
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
wire s_axil_wready_early = m_axil_wready | (~temp_m_axil_wvalid_reg & (~m_axil_wvalid_reg | ~s_axil_wvalid));
always @* begin
// transfer sink ready state to source
m_axil_wvalid_next = m_axil_wvalid_reg;
temp_m_axil_wvalid_next = temp_m_axil_wvalid_reg;
store_axil_w_input_to_output = 1'b0;
store_axil_w_input_to_temp = 1'b0;
store_axil_w_temp_to_output = 1'b0;
if (s_axil_wready_reg) begin
// input is ready
if (m_axil_wready | ~m_axil_wvalid_reg) begin
// output is ready or currently not valid, transfer data to output
m_axil_wvalid_next = s_axil_wvalid;
store_axil_w_input_to_output = 1'b1;
end else begin
// output is not ready, store input in temp
temp_m_axil_wvalid_next = s_axil_wvalid;
store_axil_w_input_to_temp = 1'b1;
end
end else if (m_axil_wready) begin
// input is not ready, but output is ready
m_axil_wvalid_next = temp_m_axil_wvalid_reg;
temp_m_axil_wvalid_next = 1'b0;
store_axil_w_temp_to_output = 1'b1;
end
end
always @(posedge clk) begin
if (rst) begin
s_axil_wready_reg <= 1'b0;
m_axil_wvalid_reg <= 1'b0;
temp_m_axil_wvalid_reg <= 1'b0;
end else begin
s_axil_wready_reg <= s_axil_wready_early;
m_axil_wvalid_reg <= m_axil_wvalid_next;
temp_m_axil_wvalid_reg <= temp_m_axil_wvalid_next;
end
// datapath
if (store_axil_w_input_to_output) begin
m_axil_wdata_reg <= s_axil_wdata;
m_axil_wstrb_reg <= s_axil_wstrb;
end else if (store_axil_w_temp_to_output) begin
m_axil_wdata_reg <= temp_m_axil_wdata_reg;
m_axil_wstrb_reg <= temp_m_axil_wstrb_reg;
end
if (store_axil_w_input_to_temp) begin
temp_m_axil_wdata_reg <= s_axil_wdata;
temp_m_axil_wstrb_reg <= s_axil_wstrb;
end
end
end else if (W_REG_TYPE == 1) begin
// simple register, inserts bubble cycles
// datapath registers
reg s_axil_wready_reg = 1'b0;
reg [DATA_WIDTH-1:0] m_axil_wdata_reg = {DATA_WIDTH{1'b0}};
reg [STRB_WIDTH-1:0] m_axil_wstrb_reg = {STRB_WIDTH{1'b0}};
reg m_axil_wvalid_reg = 1'b0, m_axil_wvalid_next;
// datapath control
reg store_axil_w_input_to_output;
assign s_axil_wready = s_axil_wready_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;
// enable ready input next cycle if output buffer will be empty
wire s_axil_wready_ewly = !m_axil_wvalid_next;
always @* begin
// transfer sink ready state to source
m_axil_wvalid_next = m_axil_wvalid_reg;
store_axil_w_input_to_output = 1'b0;
if (s_axil_wready_reg) begin
m_axil_wvalid_next = s_axil_wvalid;
store_axil_w_input_to_output = 1'b1;
end else if (m_axil_wready) begin
m_axil_wvalid_next = 1'b0;
end
end
always @(posedge clk) begin
if (rst) begin
s_axil_wready_reg <= 1'b0;
m_axil_wvalid_reg <= 1'b0;
end else begin
s_axil_wready_reg <= s_axil_wready_ewly;
m_axil_wvalid_reg <= m_axil_wvalid_next;
end
// datapath
if (store_axil_w_input_to_output) begin
m_axil_wdata_reg <= s_axil_wdata;
m_axil_wstrb_reg <= s_axil_wstrb;
end
end
end else begin
// bypass W channel
assign m_axil_wdata = s_axil_wdata;
assign m_axil_wstrb = s_axil_wstrb;
assign m_axil_wvalid = s_axil_wvalid;
assign s_axil_wready = m_axil_wready;
end
// B channel
if (B_REG_TYPE > 1) begin
// skid buffer, no bubble cycles
// datapath registers
reg m_axil_bready_reg = 1'b0;
reg [1:0] s_axil_bresp_reg = 2'b0;
reg s_axil_bvalid_reg = 1'b0, s_axil_bvalid_next;
reg [1:0] temp_s_axil_bresp_reg = 2'b0;
reg temp_s_axil_bvalid_reg = 1'b0, temp_s_axil_bvalid_next;
// datapath control
reg store_axil_b_input_to_output;
reg store_axil_b_input_to_temp;
reg store_axil_b_temp_to_output;
assign m_axil_bready = m_axil_bready_reg;
assign s_axil_bresp = s_axil_bresp_reg;
assign s_axil_bvalid = s_axil_bvalid_reg;
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
wire m_axil_bready_early = s_axil_bready | (~temp_s_axil_bvalid_reg & (~s_axil_bvalid_reg | ~m_axil_bvalid));
always @* begin
// transfer sink ready state to source
s_axil_bvalid_next = s_axil_bvalid_reg;
temp_s_axil_bvalid_next = temp_s_axil_bvalid_reg;
store_axil_b_input_to_output = 1'b0;
store_axil_b_input_to_temp = 1'b0;
store_axil_b_temp_to_output = 1'b0;
if (m_axil_bready_reg) begin
// input is ready
if (s_axil_bready | ~s_axil_bvalid_reg) begin
// output is ready or currently not valid, transfer data to output
s_axil_bvalid_next = m_axil_bvalid;
store_axil_b_input_to_output = 1'b1;
end else begin
// output is not ready, store input in temp
temp_s_axil_bvalid_next = m_axil_bvalid;
store_axil_b_input_to_temp = 1'b1;
end
end else if (s_axil_bready) begin
// input is not ready, but output is ready
s_axil_bvalid_next = temp_s_axil_bvalid_reg;
temp_s_axil_bvalid_next = 1'b0;
store_axil_b_temp_to_output = 1'b1;
end
end
always @(posedge clk) begin
if (rst) begin
m_axil_bready_reg <= 1'b0;
s_axil_bvalid_reg <= 1'b0;
temp_s_axil_bvalid_reg <= 1'b0;
end else begin
m_axil_bready_reg <= m_axil_bready_early;
s_axil_bvalid_reg <= s_axil_bvalid_next;
temp_s_axil_bvalid_reg <= temp_s_axil_bvalid_next;
end
// datapath
if (store_axil_b_input_to_output) begin
s_axil_bresp_reg <= m_axil_bresp;
end else if (store_axil_b_temp_to_output) begin
s_axil_bresp_reg <= temp_s_axil_bresp_reg;
end
if (store_axil_b_input_to_temp) begin
temp_s_axil_bresp_reg <= m_axil_bresp;
end
end
end else if (B_REG_TYPE == 1) begin
// simple register, inserts bubble cycles
// datapath registers
reg m_axil_bready_reg = 1'b0;
reg [1:0] s_axil_bresp_reg = 2'b0;
reg s_axil_bvalid_reg = 1'b0, s_axil_bvalid_next;
// datapath control
reg store_axil_b_input_to_output;
assign m_axil_bready = m_axil_bready_reg;
assign s_axil_bresp = s_axil_bresp_reg;
assign s_axil_bvalid = s_axil_bvalid_reg;
// enable ready input next cycle if output buffer will be empty
wire m_axil_bready_early = !s_axil_bvalid_next;
always @* begin
// transfer sink ready state to source
s_axil_bvalid_next = s_axil_bvalid_reg;
store_axil_b_input_to_output = 1'b0;
if (m_axil_bready_reg) begin
s_axil_bvalid_next = m_axil_bvalid;
store_axil_b_input_to_output = 1'b1;
end else if (s_axil_bready) begin
s_axil_bvalid_next = 1'b0;
end
end
always @(posedge clk) begin
if (rst) begin
m_axil_bready_reg <= 1'b0;
s_axil_bvalid_reg <= 1'b0;
end else begin
m_axil_bready_reg <= m_axil_bready_early;
s_axil_bvalid_reg <= s_axil_bvalid_next;
end
// datapath
if (store_axil_b_input_to_output) begin
s_axil_bresp_reg <= m_axil_bresp;
end
end
end else begin
// bypass B channel
assign s_axil_bresp = m_axil_bresp;
assign s_axil_bvalid = m_axil_bvalid;
assign m_axil_bready = s_axil_bready;
end
endgenerate
endmodule

351
tb/test_axil_register.py Executable file
View File

@ -0,0 +1,351 @@
#!/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_register'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/axil_register_rd.v")
srcs.append("../rtl/axil_register_wr.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)
AW_REG_TYPE = 1
W_REG_TYPE = 1
B_REG_TYPE = 1
AR_REG_TYPE = 1
R_REG_TYPE = 1
# 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)[DATA_WIDTH:])
s_axil_wstrb = Signal(intbv(0)[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)[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)[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)[DATA_WIDTH:])
m_axil_wstrb = Signal(intbv(0)[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()

196
tb/test_axil_register.v Normal file
View File

@ -0,0 +1,196 @@
/*
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_register
*/
module test_axil_register;
// Parameters
parameter DATA_WIDTH = 32;
parameter ADDR_WIDTH = 16;
parameter STRB_WIDTH = (DATA_WIDTH/8);
parameter AW_REG_TYPE = 1;
parameter W_REG_TYPE = 1;
parameter B_REG_TYPE = 1;
parameter AR_REG_TYPE = 1;
parameter R_REG_TYPE = 1;
// 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 [DATA_WIDTH-1:0] s_axil_wdata = 0;
reg [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 [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 [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 [DATA_WIDTH-1:0] m_axil_wdata;
wire [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_register.lxt");
$dumpvars(0, test_axil_register);
end
axil_register #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.AW_REG_TYPE(AW_REG_TYPE),
.W_REG_TYPE(W_REG_TYPE),
.B_REG_TYPE(B_REG_TYPE),
.AR_REG_TYPE(AR_REG_TYPE),
.R_REG_TYPE(R_REG_TYPE)
)
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

233
tb/test_axil_register_rd.py Executable file
View File

@ -0,0 +1,233 @@
#!/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_register_rd'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
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)
AR_REG_TYPE = 1
R_REG_TYPE = 1
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
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_arready = Signal(bool(0))
m_axil_rdata = Signal(intbv(0)[DATA_WIDTH:])
m_axil_rresp = Signal(intbv(0)[2:])
m_axil_rvalid = Signal(bool(0))
# Outputs
s_axil_arready = Signal(bool(0))
s_axil_rdata = Signal(intbv(0)[DATA_WIDTH:])
s_axil_rresp = Signal(intbv(0)[2:])
s_axil_rvalid = 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_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_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_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_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: read")
current_test.next = 1
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 2: various reads")
current_test.next = 2
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()

124
tb/test_axil_register_rd.v Normal file
View File

@ -0,0 +1,124 @@
/*
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_register_rd
*/
module test_axil_register_rd;
// Parameters
parameter DATA_WIDTH = 32;
parameter ADDR_WIDTH = 16;
parameter STRB_WIDTH = (DATA_WIDTH/8);
parameter AR_REG_TYPE = 1;
parameter R_REG_TYPE = 1;
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 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_arready = 0;
reg [DATA_WIDTH-1:0] m_axil_rdata = 0;
reg [1:0] m_axil_rresp = 0;
reg m_axil_rvalid = 0;
// Outputs
wire s_axil_arready;
wire [DATA_WIDTH-1:0] s_axil_rdata;
wire [1:0] s_axil_rresp;
wire s_axil_rvalid;
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_araddr,
s_axil_arprot,
s_axil_arvalid,
s_axil_rready,
m_axil_arready,
m_axil_rdata,
m_axil_rresp,
m_axil_rvalid
);
$to_myhdl(
s_axil_arready,
s_axil_rdata,
s_axil_rresp,
s_axil_rvalid,
m_axil_araddr,
m_axil_arprot,
m_axil_arvalid,
m_axil_rready
);
// dump file
$dumpfile("test_axil_register_rd.lxt");
$dumpvars(0, test_axil_register_rd);
end
axil_register_rd #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.AR_REG_TYPE(AR_REG_TYPE),
.R_REG_TYPE(R_REG_TYPE)
)
UUT (
.clk(clk),
.rst(rst),
.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_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

255
tb/test_axil_register_wr.py Executable file
View File

@ -0,0 +1,255 @@
#!/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_register_wr'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
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)
AW_REG_TYPE = 1
W_REG_TYPE = 1
B_REG_TYPE = 1
# 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)[DATA_WIDTH:])
s_axil_wstrb = Signal(intbv(0)[STRB_WIDTH:])
s_axil_wvalid = Signal(bool(0))
s_axil_bready = 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))
# 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))
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)[DATA_WIDTH:])
m_axil_wstrb = Signal(intbv(0)[STRB_WIDTH:])
m_axil_wvalid = Signal(bool(0))
m_axil_bready = 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,
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,
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,
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
)
@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 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)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()

144
tb/test_axil_register_wr.v Normal file
View File

@ -0,0 +1,144 @@
/*
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_register_wr
*/
module test_axil_register_wr;
// Parameters
parameter DATA_WIDTH = 32;
parameter ADDR_WIDTH = 16;
parameter STRB_WIDTH = (DATA_WIDTH/8);
parameter AW_REG_TYPE = 1;
parameter W_REG_TYPE = 1;
parameter B_REG_TYPE = 1;
// 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 [DATA_WIDTH-1:0] s_axil_wdata = 0;
reg [STRB_WIDTH-1:0] s_axil_wstrb = 0;
reg s_axil_wvalid = 0;
reg s_axil_bready = 0;
reg m_axil_awready = 0;
reg m_axil_wready = 0;
reg [1:0] m_axil_bresp = 0;
reg m_axil_bvalid = 0;
// Outputs
wire s_axil_awready;
wire s_axil_wready;
wire [1:0] s_axil_bresp;
wire s_axil_bvalid;
wire [ADDR_WIDTH-1:0] m_axil_awaddr;
wire [2:0] m_axil_awprot;
wire m_axil_awvalid;
wire [DATA_WIDTH-1:0] m_axil_wdata;
wire [STRB_WIDTH-1:0] m_axil_wstrb;
wire m_axil_wvalid;
wire m_axil_bready;
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,
m_axil_awready,
m_axil_wready,
m_axil_bresp,
m_axil_bvalid
);
$to_myhdl(
s_axil_awready,
s_axil_wready,
s_axil_bresp,
s_axil_bvalid,
m_axil_awaddr,
m_axil_awprot,
m_axil_awvalid,
m_axil_wdata,
m_axil_wstrb,
m_axil_wvalid,
m_axil_bready
);
// dump file
$dumpfile("test_axil_register_wr.lxt");
$dumpvars(0, test_axil_register_wr);
end
axil_register_wr #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH),
.STRB_WIDTH(STRB_WIDTH),
.AW_REG_TYPE(AW_REG_TYPE),
.W_REG_TYPE(W_REG_TYPE),
.B_REG_TYPE(B_REG_TYPE)
)
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),
.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)
);
endmodule