commit df2453b0daf06aa5e470309269315876566e1e31
parent f36bd94cb922823b9ae840fa08d1f66800729d8a
Author: Brian Swetland <swetland@frotz.net>
Date: Tue, 29 Jul 2014 23:00:50 -0700
axi-registers: add testcase, move to more conservative read cycle
do not depend on register to maintain value beyond the clock after rd
Diffstat:
3 files changed, 250 insertions(+), 12 deletions(-)
diff --git a/Makefile b/Makefile
@@ -61,6 +61,12 @@ MODULE_SRCS += hdl/eth_rmii_tx.sv
MODULE_SRCS += hdl/eth_rmii_rx.sv
include build/verilator-sim.mk
+MODULE_NAME := axi-regs-test
+MODULE_SRCS := hdl/test/axi_registers_test.sv
+MODULE_SRCS += hdl/axi_ifc.sv
+MODULE_SRCS += hdl/axi_registers.sv
+include build/verilator-sim.mk
+
MODULE_NAME := eth-capture-test
MODULE_SRCS := hdl/test/eth_capture_test.sv
MODULE_SRCS += hdl/test/eth_packet_gen.sv
diff --git a/hdl/axi_registers.sv b/hdl/axi_registers.sv
@@ -33,12 +33,12 @@ module axi_registers (
axi_ifc.slave s,
// Register File Interface
- output reg [R_ADDR_WIDTH-1:0]o_rreg,
- output reg [R_ADDR_WIDTH-1:0]o_wreg,
+ output reg [R_ADDR_WIDTH-1:0]o_rreg = 0,
+ output reg [R_ADDR_WIDTH-1:0]o_wreg = 0,
input wire [31:0]i_rdata,
- output reg [31:0]o_wdata,
- output reg o_rd,
- output reg o_wr
+ output reg [31:0]o_wdata = 0,
+ output wire o_rd,
+ output wire o_wr
);
parameter integer R_ADDR_WIDTH = 2;
@@ -103,7 +103,7 @@ always_comb begin
endcase
end
-typedef enum { R_ADDR, R_CAPTURE, R_DATA } rstate_t;
+typedef enum { R_ADDR, R_CAPTURE, R_CAPTURE2, R_DATA } rstate_t;
rstate_t rstate = R_ADDR;
rstate_t rstate_next;
@@ -112,9 +112,9 @@ reg arready_next;
reg rvalid_next;
reg rlast_next;
-//reg [31:0]rdata;
-//reg [31:0]rdata_next;
-assign s.rdata = i_rdata;
+reg [31:0]rdata = 0;
+reg [31:0]rdata_next;
+assign s.rdata = rdata;
reg rd_next;
@@ -124,7 +124,7 @@ assign s.rid = trid;
always_comb begin
rstate_next = rstate;
- //rdata_next = rdata;
+ rdata_next = rdata;
rreg_next = o_rreg;
trid_next = trid;
arready_next = 0;
@@ -143,10 +143,14 @@ always_comb begin
end
R_CAPTURE: begin
// present address and rd to register file
+ rstate_next = R_CAPTURE2;
+ end
+ R_CAPTURE2: begin
+ // capture register file output
rstate_next = R_DATA;
rvalid_next = 1;
rlast_next = 1;
- //rdata_next = i_rdata;
+ rdata_next = i_rdata;
end
R_DATA: if (s.rready) begin
// present register data to AXI
@@ -169,7 +173,7 @@ always_ff @(posedge clk) begin
o_wreg <= wreg_next;
rstate <= rstate_next;
- //rdata <= rdata_next;
+ rdata <= rdata_next;
trid <= trid_next;
s.arready <= arready_next;
s.rvalid <= rvalid_next;
diff --git a/hdl/test/axi_registers_test.sv b/hdl/test/axi_registers_test.sv
@@ -0,0 +1,228 @@
+
+module testbench(input clk);
+
+
+axi_ifc axi0();
+
+
+wire [1:0]rreg;
+wire [1:0]wreg;
+reg [31:0]rdata = 32'hdeadbeef;
+wire [31:0]wdata;
+wire rrd;
+wire rwr;
+
+axi_registers regs(
+ .clk(clk),
+ .s(axi0),
+ .o_rreg(rreg),
+ .o_wreg(wreg),
+ .i_rdata(rdata),
+ .o_wdata(wdata),
+ .o_rd(rrd),
+ .o_wr(rwr)
+ );
+
+wire [31:0]tmp;
+
+always_ff @(posedge clk) begin
+ if (rrd) case(rreg)
+ 0: rdata <= 32'h10101010;
+ 1: rdata <= 32'h20202020;
+ 2: rdata <= 32'h30303030;
+ 3: rdata <= tmp;
+ endcase
+ if (rwr & (wreg == 3))
+ tmp <= wdata;
+end
+
+
+integer tick = 0;
+reg [31:0]addr = 32'hffffffff;
+reg [31:0]next_addr;
+reg [31:0]data = 32'hffffffff;
+reg [31:0]next_data;
+reg do_rd = 0;
+reg next_do_rd;
+reg do_wr = 0;
+reg next_do_wr;
+
+axi_rw_engine engine0(
+ .clk(clk),
+ .m(axi0),
+ .rd(do_rd),
+ .wr(do_wr),
+ .addr(addr),
+ .data(data)
+ );
+
+always_comb begin
+ next_do_rd = 0;
+ next_do_wr = 0;
+ next_addr = 32'hffffffff;
+ next_data = 32'hffffffff;
+ if (tick == 10) begin
+ next_do_rd = 1;
+ next_addr = 4;
+ end else if (tick == 20) begin
+ next_do_rd = 1;
+ next_addr = 0;
+ end else if (tick == 30) begin
+ next_do_wr = 1;
+ next_data = 32'haabbccdd;
+ next_addr = 12;
+ end else if (tick == 40) begin
+ next_do_rd = 1;
+ next_addr = 4;
+ end else if (tick == 50) begin
+ next_do_rd = 1;
+ next_addr = 12;
+ end else if (tick == 60) begin
+ $finish;
+ end
+end
+
+always_ff @(posedge clk) begin
+ do_rd <= next_do_rd;
+ do_wr <= next_do_wr;
+ addr <= next_addr;
+ data <= next_data;
+ tick <= tick + 1;
+end
+
+endmodule
+
+
+module axi_rw_engine(
+ input clk,
+ axi_ifc.master m,
+ input rd,
+ input wr,
+ input [31:0]addr,
+ input [31:0]data
+ );
+
+typedef enum { IDLE, RADDR, RDATA, WADDR, WDATA, WRESP } state_t;
+state_t state = IDLE;
+state_t next_state;
+
+reg [31:0]awaddr = 0;
+reg [31:0]next_awaddr;
+reg [31:0]wdata = 0;
+reg [31:0]next_wdata;
+reg [31:0]araddr = 0;
+reg [31:0]next_araddr;
+reg arvalid = 0;
+reg next_arvalid;
+reg rready = 0;
+reg next_rready;
+reg awvalid = 0;
+reg next_awvalid;
+reg wvalid = 0;
+reg next_wvalid;
+reg bready = 0;
+reg next_bready;
+
+always_comb begin
+ next_state = state;
+ next_araddr = araddr;
+ next_awaddr = awaddr;
+ next_wdata = wdata;
+ next_awvalid = 0;
+ next_wvalid = 0;
+ next_bready = 0;
+ next_arvalid = 0;
+ next_rready = 0;
+ case (state)
+ IDLE: begin
+ if (rd) begin
+ next_state = RADDR;
+ next_araddr = addr;
+ next_arvalid = 1;
+ end else if (wr) begin
+ next_state = WADDR;
+ next_awaddr = addr;
+ next_wdata = data;
+ next_awvalid = 1;
+ end
+ end
+ WADDR: begin
+ if (m.awready) begin
+ next_state = WDATA;
+ next_wvalid = 1;
+ end else begin
+ next_awvalid = 1;
+ end
+ end
+ WDATA: begin
+ if (m.wready) begin
+ next_state = WRESP;
+ next_bready = 1;
+ end else begin
+ next_wvalid = 1;
+ end
+ end
+ WRESP: begin
+ if (m.bvalid) begin
+ next_state = IDLE;
+ $display("wr %x -> %x (status %x)", wdata, awaddr, m.bresp);
+ end else begin
+ next_bready = 1;
+ end
+ end
+ RADDR: begin
+ if (m.arready) begin
+ next_state = RDATA;
+ next_rready = 1;
+ end else begin
+ next_arvalid = 1;
+ end
+ end
+ RDATA: begin
+ if (m.rvalid) begin
+ next_state = IDLE;
+ $display("rd %x <- %x (status %x)", m.rdata, m.araddr, m.rresp);
+ end else begin
+ next_rready = 1;
+ end
+ end
+ endcase
+end
+
+always_ff @(posedge clk) begin
+ state <= next_state;
+ araddr <= next_araddr;
+ awaddr <= next_awaddr;
+ arvalid <= next_arvalid;
+ awvalid <= next_awvalid;
+ rready <= next_rready;
+ wvalid <= next_wvalid;
+ bready <= next_bready;
+ wdata <= next_wdata;
+end
+
+assign m.awid = 0;
+assign m.awaddr = awaddr;
+assign m.awvalid = awvalid;
+assign m.wdata = wdata;
+assign m.wstrb = 4'b1111;
+assign m.wvalid = wvalid;
+assign m.bready = bready;
+assign m.awburst = 1; // INCR
+assign m.awcache = 0;
+assign m.awlen = 0;
+assign m.awsize = 2; // 4 bytes
+assign m.awlock = 0;
+assign m.wlast = 1;
+
+assign m.arid = 0;
+assign m.araddr = araddr;
+assign m.arvalid = arvalid;
+assign m.rready = rready;
+assign m.arburst = 1; // INCR
+assign m.arcache = 0;
+assign m.arlen = 0;
+assign m.arsize = 2; // 4 bytes
+assign m.arlock = 0;
+
+endmodule