mirror of
https://gitlab.com/brendanhaines/cpu.git
synced 2024-12-25 18:46:53 -07:00
implement axi-lite to wishbone bridge. Untested
This commit is contained in:
parent
03828419a9
commit
c1ec8520be
|
@ -1,5 +1,205 @@
|
|||
module axi4_lite(
|
||||
input wire aclk
|
||||
// TODO: improve throughput. Currently limited to 1 write every 3 cycles and read every 2 cycles (plus wb slave latency)
|
||||
|
||||
module axi4l_wb_bridge #(
|
||||
parameter ADDR_WIDTH = 8,
|
||||
parameter DATA_WIDTH = 32
|
||||
)(
|
||||
// Global
|
||||
input logic clk,
|
||||
input logic reset,
|
||||
|
||||
///// AXI4-Lite /////
|
||||
|
||||
// Write address
|
||||
input logic axil_awvalid,
|
||||
output logic axil_awready,
|
||||
input logic [ADDR_WIDTH-1:0] axil_awaddr,
|
||||
input logic [2:0] axil_awprot,
|
||||
|
||||
// Write data
|
||||
input logic axil_wvalid,
|
||||
output logic axil_wready,
|
||||
input logic [DATA_WIDTH-1:0] axil_wdata,
|
||||
input logic [DATA_WIDTH/8 - 1:0] axil_wstrb,
|
||||
|
||||
// Write response
|
||||
output logic axil_bvalid,
|
||||
input logic axil_bready,
|
||||
output logic [1:0] axil_bresp,
|
||||
|
||||
// Read address
|
||||
input logic axil_arvalid,
|
||||
output logic axil_arready,
|
||||
input logic [ADDR_WIDTH-1:0] axil_araddr,
|
||||
input logic [2:0] axil_arprot,
|
||||
|
||||
// Read data
|
||||
output logic axil_rvalid,
|
||||
input logic axil_rready,
|
||||
output logic [DATA_WIDTH-1:0] axil_rdata,
|
||||
output logic [1:0] axil_rresp,
|
||||
|
||||
///// Wishbone /////
|
||||
|
||||
output logic [ADDR_WIDTH-1:0] wb_adr_o,
|
||||
input logic [DATA_WIDTH-1:0] wb_dat_i,
|
||||
output logic [DATA_WIDTH-1:0] wb_dat_o,
|
||||
output logic wb_we_o,
|
||||
output logic wb_sel_o,
|
||||
output logic wb_stb_o,
|
||||
input logic wb_ack_i,
|
||||
output logic wb_cyc_o
|
||||
);
|
||||
|
||||
localparam AXIL_RESP_OKAY = 2'b00;
|
||||
// localparam AXIL_RESP_EXOKAY = 2'b01; // Only valid for full AXI, not AXI-Lite
|
||||
localparam AXIL_RESP_SLVERR = 2'b10;
|
||||
localparam AXIL_RESP_DECERR = 2'b11; // Indicates there is no slave at the transaction address
|
||||
|
||||
localparam STATE_IDLE = 0;
|
||||
localparam STATE_READ = 1;
|
||||
localparam STATE_WRITE = 2;
|
||||
|
||||
logic [ADDR_WIDTH-1:0] waddr;
|
||||
logic [ADDR_WIDTH-1:0] raddr;
|
||||
logic [DATA_WIDTH-1:0] wdata;
|
||||
logic [DATA_WIDTH-1:0] rdata;
|
||||
logic waddr_legal;
|
||||
logic raddr_legal;
|
||||
logic wdata_legal;
|
||||
|
||||
logic waddr_valid = 0;
|
||||
logic raddr_valid = 0;
|
||||
logic wdata_valid = 0;
|
||||
logic rdata_valid = 0;
|
||||
logic w_complete = 0;
|
||||
logic [1:0] state_wb = STATE_IDLE;
|
||||
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (reset) begin
|
||||
waddr_valid <= 0;
|
||||
wdata_valid <= 0;
|
||||
w_complete <= 0;
|
||||
raddr_valid <= 0;
|
||||
rdata_valid <= 0;
|
||||
state_wb <= STATE_IDLE;
|
||||
end else begin
|
||||
// axil write address
|
||||
if (axil_awvalid && axil_awready) begin
|
||||
waddr <= axil_awaddr;
|
||||
waddr_valid <= 1;
|
||||
waddr_legal <= 1;
|
||||
// TODO: use write protection
|
||||
end
|
||||
|
||||
// axil write data
|
||||
if (axil_wvalid && axil_wready) begin
|
||||
wdata <= axil_wdata;
|
||||
wdata_valid <= 1;
|
||||
if (&axil_wstrb) begin
|
||||
// wishbone only supports full width writes
|
||||
wdata_legal <= 1;
|
||||
// end else if (!|axil_wstrb) begin
|
||||
// // TODO: optionally discard and ignore access with axil_wstrb = 4'b0000
|
||||
end else begin
|
||||
// invalid write strobe combination
|
||||
wdata_legal <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
if (
|
||||
((axil_wvalid && axil_wready) || wdata_valid) &&
|
||||
((axil_awvalid && axil_awready) || waddr_valid) &&
|
||||
!w_complete
|
||||
) begin
|
||||
if (state_wb == STATE_IDLE) begin
|
||||
state_wb <= STATE_WRITE;
|
||||
end
|
||||
end
|
||||
|
||||
// axil write response
|
||||
if (axil_bvalid && axil_bready) begin
|
||||
// reset write logic for next transfer
|
||||
waddr_valid <= 0;
|
||||
wdata_valid <= 0;
|
||||
w_complete <= 0;
|
||||
end
|
||||
|
||||
// axil read address
|
||||
if (axil_arvalid && axil_arready) begin
|
||||
raddr <= axil_araddr;
|
||||
raddr_valid <= 1;
|
||||
raddr_legal <= 1;
|
||||
// TODO: use read protection
|
||||
|
||||
if (state_wb == STATE_IDLE) begin
|
||||
// if write and read arrive on the same cycle, read takes priority
|
||||
state_wb <= STATE_READ;
|
||||
end
|
||||
end
|
||||
|
||||
// axil read data
|
||||
if (axil_rvalid && axil_rready) begin
|
||||
// read is complete. Get ready for next read
|
||||
raddr_valid <= 0;
|
||||
rdata_valid <= 0;
|
||||
end
|
||||
|
||||
// wb
|
||||
case (state_wb)
|
||||
STATE_IDLE: begin
|
||||
// do nothing
|
||||
end
|
||||
STATE_WRITE: begin
|
||||
if (wb_cyc_o && wb_sel_o && wb_stb_o && wb_ack_i) begin
|
||||
w_complete <= 1;
|
||||
state_wb <= STATE_IDLE;
|
||||
// TODO: switch directly to STATE_READ if we can
|
||||
end
|
||||
end
|
||||
STATE_READ: begin
|
||||
if (wb_cyc_o && wb_sel_o && wb_stb_o && wb_ack_i) begin
|
||||
rdata <= wb_dat_i;
|
||||
rdata_valid <= 1;
|
||||
state_wb <= STATE_IDLE;
|
||||
// TODO: switch directly to STATE_WRITE if we can
|
||||
// This will also ensure continuous reads don't inhibit all writes
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
// bh_assert_equal(state_wb, 0, "Wishbone master encountered unknown state");
|
||||
state_wb <= STATE_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
// axil write address
|
||||
axil_awready = !waddr_valid;
|
||||
|
||||
// axil write data
|
||||
axil_wready = !wdata_valid;
|
||||
|
||||
// axil write response
|
||||
axil_bvalid = waddr_valid && wdata_valid && w_complete;
|
||||
axil_bresp = (waddr_legal && wdata_legal) ? AXIL_RESP_OKAY : AXIL_RESP_SLVERR;
|
||||
|
||||
// axil read address
|
||||
axil_arready = !raddr_valid;
|
||||
|
||||
// axil read data
|
||||
axil_rvalid = rdata_valid;
|
||||
axil_rresp = raddr_legal ? AXIL_RESP_OKAY : AXIL_RESP_SLVERR;
|
||||
|
||||
// wishbone
|
||||
wb_we_o = state_wb == STATE_WRITE;
|
||||
wb_dat_o = wdata;
|
||||
wb_adr_o = (state_wb == STATE_WRITE) ? waddr : raddr;
|
||||
wb_cyc_o = state_wb == STATE_WRITE || state_wb == STATE_READ;
|
||||
wb_sel_o = 1; // TODO: figure out if this is right
|
||||
wb_stb_o = 1; // TODO: figure out if this is right
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user