411 lines
9.1 KiB
Verilog
411 lines
9.1 KiB
Verilog
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright 2019 Peter Gustavsson <peter.gustavsson@qamcom.se>
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//********************************************************************************
|
|
// $Id$
|
|
//
|
|
// Function: AXI lite to Wishbone non pipelined bridge
|
|
// Comments: Assumes single accesses to a 32bit register on an 64bit aligned address
|
|
//
|
|
//********************************************************************************
|
|
|
|
`default_nettype none
|
|
module axi2wb
|
|
#(parameter AW = 12,
|
|
parameter IW = 0)
|
|
(
|
|
input wire i_clk,
|
|
input wire i_rst,
|
|
|
|
// Wishbone master
|
|
output reg [AW-1:2] o_wb_adr,
|
|
output reg [31:0] o_wb_dat,
|
|
output reg [3:0] o_wb_sel,
|
|
output reg o_wb_we,
|
|
output reg o_wb_cyc,
|
|
output reg o_wb_stb,
|
|
|
|
input wire [31:0] i_wb_rdt,
|
|
input wire i_wb_ack,
|
|
input wire i_wb_err,
|
|
|
|
// AXI slave
|
|
// AXI adress write channel
|
|
input wire [AW-1:0] i_awaddr,
|
|
input wire [IW-1:0] i_awid,
|
|
input wire i_awvalid,
|
|
output reg o_awready,
|
|
//AXI adress read channel
|
|
input wire [AW-1:0] i_araddr,
|
|
input wire [IW-1:0] i_arid,
|
|
input wire i_arvalid,
|
|
output reg o_arready,
|
|
//AXI write channel
|
|
input wire [63:0] i_wdata,
|
|
input wire [7:0] i_wstrb,
|
|
input wire i_wvalid,
|
|
output reg o_wready,
|
|
//AXI response channel
|
|
output reg [IW-1:0] o_bid,
|
|
output wire [1:0] o_bresp,
|
|
output reg o_bvalid,
|
|
input wire i_bready,
|
|
//AXI read channel
|
|
output reg [63:0] o_rdata,
|
|
output reg [IW-1:0] o_rid,
|
|
output wire [1:0] o_rresp,
|
|
output wire o_rlast,
|
|
output reg o_rvalid,
|
|
input wire i_rready
|
|
);
|
|
|
|
assign o_bresp = 2'b00;
|
|
assign o_rresp = 2'b00;
|
|
assign o_rlast = 1'b1;
|
|
|
|
reg hi_32b_w;
|
|
reg arbiter;
|
|
reg [31:0] wb_rdt_low;
|
|
|
|
|
|
parameter STATESIZE = 4;
|
|
|
|
parameter [STATESIZE-1:0]
|
|
IDLE = 4'd0,
|
|
AWACK = 4'd1,
|
|
WBWACK= 4'd2,
|
|
WBRACK1 = 4'd3,
|
|
WBR2 = 4'd4,
|
|
WBRACK2 = 4'd5,
|
|
BAXI = 4'd6,
|
|
RRAXI = 4'd7;
|
|
|
|
reg [STATESIZE-1:0] cs;
|
|
|
|
// formal helper registers
|
|
reg aw_req;
|
|
reg w_req;
|
|
reg ar_req;
|
|
|
|
|
|
initial o_rvalid = 1'b0;
|
|
initial o_bvalid = 1'b0;
|
|
initial o_wb_stb = 1'b0;
|
|
initial o_wb_cyc = 1'b0;
|
|
initial o_wb_we = 1'b0;
|
|
initial cs = 4'd0;
|
|
initial aw_req = 1'b0;
|
|
initial w_req = 1'b0;
|
|
initial ar_req = 1'b0;
|
|
|
|
|
|
always @(posedge i_clk) begin
|
|
if (i_rst) begin
|
|
o_awready <= 1'b0;
|
|
o_wready <= 1'b0;
|
|
o_arready <= 1'b0;
|
|
o_rvalid <= 1'b0;
|
|
o_bvalid <= 1'b0;
|
|
o_wb_adr <= {AW-2{1'b0}};
|
|
o_wb_cyc <= 1'b0;
|
|
o_wb_stb <= 1'b0;
|
|
o_wb_sel <= 4'd0;
|
|
o_wb_we <= 1'b0;
|
|
arbiter <= 1'b1;
|
|
wb_rdt_low <= 32'hDEADBEEF;
|
|
cs <= IDLE;
|
|
|
|
aw_req <= 1'b0;
|
|
w_req <= 1'b0;
|
|
ar_req <= 1'b0;
|
|
o_bid <= {IW{1'b0}};
|
|
o_rid <= {IW{1'b0}};
|
|
|
|
end
|
|
else begin
|
|
if (i_awvalid & o_awready)
|
|
o_bid <= i_awid;
|
|
|
|
if (i_arvalid & o_arready)
|
|
o_rid <= i_arid;
|
|
|
|
o_awready <= 1'b0;
|
|
o_wready <= 1'b0;
|
|
o_arready <= 1'b0;
|
|
|
|
if (i_awvalid && o_awready)
|
|
aw_req <= 1'b1;
|
|
else if (i_bready && o_bvalid)
|
|
aw_req <= 1'b0;
|
|
|
|
if (i_wvalid && o_wready)
|
|
w_req <= 1'b1;
|
|
else if (i_bready && o_bvalid)
|
|
w_req <= 1'b0;
|
|
|
|
if (i_arvalid && o_arready)
|
|
ar_req <= 1'b1;
|
|
else if (i_rready && o_rvalid)
|
|
ar_req <= 1'b0;
|
|
|
|
case (cs)
|
|
IDLE : begin
|
|
arbiter <= 1'b1;
|
|
if (i_awvalid && arbiter) begin
|
|
o_wb_adr[AW-1:3] <= i_awaddr[AW-1:3];
|
|
o_awready <= 1'b1;
|
|
arbiter <= 1'b0;
|
|
if (i_wvalid) begin
|
|
hi_32b_w = (i_wstrb[3:0] == 4'h0) ? 1'b1 : 1'b0;
|
|
o_wb_adr[2] <= hi_32b_w;
|
|
o_wb_cyc <= 1'b1;
|
|
o_wb_stb <= 1'b1;
|
|
o_wb_sel <= hi_32b_w ? i_wstrb[7:4] : i_wstrb[3:0];
|
|
o_wb_dat <= hi_32b_w ? i_wdata[63:32] : i_wdata[31:0];
|
|
o_wb_we <= 1'b1;
|
|
o_wready <= 1'b1;
|
|
cs <= WBWACK;
|
|
end
|
|
else begin
|
|
cs <= AWACK;
|
|
end
|
|
end
|
|
else if (i_arvalid) begin
|
|
o_wb_adr[AW-1:2] <= i_araddr[AW-1:2];
|
|
o_wb_sel <= 4'hF;
|
|
o_wb_cyc <= 1'b1;
|
|
o_wb_stb <= 1'b1;
|
|
o_arready <= 1'b1;
|
|
cs <= WBRACK1;
|
|
end
|
|
end
|
|
|
|
AWACK : begin
|
|
if (i_wvalid) begin
|
|
hi_32b_w = (i_wstrb[3:0] == 4'h0) ? 1'b1 : 1'b0;
|
|
o_wb_adr[2] <= hi_32b_w;
|
|
o_wb_cyc <= 1'b1;
|
|
o_wb_stb <= 1'b1;
|
|
o_wb_sel <= hi_32b_w ? i_wstrb[7:4] : i_wstrb[3:0];
|
|
o_wb_dat <= hi_32b_w ? i_wdata[63:32] : i_wdata[31:0];
|
|
o_wb_we <= 1'b1;
|
|
o_wready <= 1'b1;
|
|
cs <= WBWACK;
|
|
end
|
|
end
|
|
|
|
WBWACK : begin
|
|
if ( i_wb_err || i_wb_ack ) begin
|
|
o_wb_cyc <= 1'b0;
|
|
o_wb_stb <= 1'b0;
|
|
o_wb_sel <= 4'h0;
|
|
o_wb_we <= 1'b0;
|
|
o_bvalid <= 1'b1;
|
|
cs <= BAXI;
|
|
end
|
|
end
|
|
|
|
WBRACK1 : begin
|
|
if ( i_wb_err || i_wb_ack) begin
|
|
o_wb_cyc <= 1'b0;
|
|
o_wb_stb <= 1'b0;
|
|
o_wb_sel <= 4'h0;
|
|
wb_rdt_low <= i_wb_rdt;
|
|
cs <= WBR2;
|
|
end
|
|
end
|
|
|
|
WBR2 : begin
|
|
o_wb_adr[2] <= 1'b1;
|
|
o_wb_sel <= 4'hF;
|
|
o_wb_cyc <= 1'b1;
|
|
o_wb_stb <= 1'b1;
|
|
cs <= WBRACK2;
|
|
end
|
|
|
|
|
|
WBRACK2 : begin
|
|
if ( i_wb_err || i_wb_ack) begin
|
|
o_wb_cyc <= 1'b0;
|
|
o_wb_stb <= 1'b0;
|
|
o_wb_sel <= 4'h0;
|
|
o_rvalid <= 1'b1;
|
|
o_rdata <= {i_wb_rdt, wb_rdt_low};
|
|
cs <= RRAXI;
|
|
end
|
|
end
|
|
|
|
BAXI : begin
|
|
o_bvalid <= 1'b1;
|
|
if (i_bready) begin
|
|
o_bvalid <= 1'b0;
|
|
cs <= IDLE;
|
|
end
|
|
end
|
|
|
|
RRAXI : begin
|
|
o_rvalid <= 1'b1;
|
|
if (i_rready) begin
|
|
o_rvalid <= 1'b0;
|
|
cs <= IDLE;
|
|
end
|
|
end
|
|
|
|
default : begin
|
|
o_awready <= 1'b0;
|
|
o_wready <= 1'b0;
|
|
o_arready <= 1'b0;
|
|
o_rvalid <= 1'b0;
|
|
o_bvalid <= 1'b0;
|
|
o_wb_adr <= {AW-2{1'b0}};
|
|
o_wb_cyc <= 1'b0;
|
|
o_wb_stb <= 1'b0;
|
|
o_wb_sel <= 4'd0;
|
|
o_wb_we <= 1'b0;
|
|
arbiter <= 1'b1;
|
|
cs <= IDLE;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
|
|
`ifdef FORMAL
|
|
localparam F_LGDEPTH = 4;
|
|
|
|
wire [(F_LGDEPTH-1):0] faxi_awr_outstanding,
|
|
faxi_wr_outstanding,
|
|
faxi_rd_outstanding;
|
|
|
|
|
|
faxil_slave
|
|
#(
|
|
.C_AXI_DATA_WIDTH(64),
|
|
.C_AXI_ADDR_WIDTH(AW),
|
|
.F_OPT_BRESP (1'b1),
|
|
.F_OPT_RRESP (1'b1),
|
|
.F_AXI_MAXWAIT (16),
|
|
.F_AXI_MAXDELAY (4),
|
|
.F_AXI_MAXRSTALL (1),
|
|
.F_LGDEPTH(F_LGDEPTH))
|
|
faxil_slave
|
|
(
|
|
.i_clk(i_clk),
|
|
.i_axi_reset_n(~i_rst),
|
|
//
|
|
.i_axi_awaddr(i_awaddr),
|
|
.i_axi_awcache(4'h0),
|
|
.i_axi_awprot(3'd0),
|
|
.i_axi_awvalid(i_awvalid),
|
|
.i_axi_awready(o_awready),
|
|
//
|
|
.i_axi_wdata(i_wdata),
|
|
.i_axi_wstrb(i_wstrb),
|
|
.i_axi_wvalid(i_wvalid),
|
|
.i_axi_wready(o_wready),
|
|
//
|
|
.i_axi_bresp(2'd0),
|
|
.i_axi_bvalid(o_bvalid),
|
|
.i_axi_bready(i_bready),
|
|
//
|
|
.i_axi_araddr(i_araddr),
|
|
.i_axi_arprot(3'd0),
|
|
.i_axi_arcache(4'h0),
|
|
.i_axi_arvalid(i_arvalid),
|
|
.i_axi_arready(o_arready),
|
|
//
|
|
.i_axi_rdata(o_rdata),
|
|
.i_axi_rresp(2'd0),
|
|
.i_axi_rvalid(o_rvalid),
|
|
.i_axi_rready(i_rready),
|
|
//
|
|
.f_axi_rd_outstanding(faxi_rd_outstanding),
|
|
.f_axi_wr_outstanding(faxi_wr_outstanding),
|
|
.f_axi_awr_outstanding(faxi_awr_outstanding));
|
|
|
|
|
|
always @(*) begin
|
|
|
|
assert(faxi_awr_outstanding <= 1);
|
|
assert(faxi_wr_outstanding <= 1);
|
|
assert(faxi_rd_outstanding <= 1);
|
|
|
|
case (cs)
|
|
IDLE : begin
|
|
assert(!o_wb_we);
|
|
assert(!o_wb_stb);
|
|
assert(!o_wb_cyc);
|
|
assert(!aw_req);
|
|
assert(!ar_req);
|
|
assert(!w_req);
|
|
assert(faxi_awr_outstanding == 0);
|
|
assert(faxi_wr_outstanding == 0);
|
|
assert(faxi_rd_outstanding == 0);
|
|
end
|
|
AWACK : begin
|
|
assert(!o_wb_we);
|
|
assert(!o_wb_stb);
|
|
assert(!o_wb_cyc);
|
|
assert(faxi_awr_outstanding == (aw_req ? 1:0));
|
|
assert(faxi_wr_outstanding == 0);
|
|
assert(faxi_rd_outstanding == 0);
|
|
end
|
|
WBWACK : begin
|
|
assert(faxi_awr_outstanding == (aw_req ? 1:0));
|
|
assert(faxi_wr_outstanding == (w_req ? 1:0));
|
|
assert(faxi_rd_outstanding == 0);
|
|
end
|
|
WBRACK : begin
|
|
assert(faxi_awr_outstanding == 0);
|
|
assert(faxi_wr_outstanding == 0);
|
|
assert(faxi_rd_outstanding == (ar_req ? 1:0));
|
|
end
|
|
BAXI : begin
|
|
assert(faxi_rd_outstanding == 0);
|
|
end
|
|
RRAXI : begin
|
|
assert(faxi_awr_outstanding == 0);
|
|
assert(faxi_wr_outstanding == 0);
|
|
end
|
|
|
|
default:
|
|
assert(0);
|
|
endcase // case (cs)
|
|
end
|
|
|
|
fwbc_master
|
|
#(.AW (AW-2),
|
|
.DW (32),
|
|
.F_MAX_DELAY (4),
|
|
.OPT_BUS_ABORT (0))
|
|
fwbc_master
|
|
(.i_clk (i_clk),
|
|
.i_reset (i_rst),
|
|
.i_wb_addr (o_wb_adr),
|
|
.i_wb_data (o_wb_dat),
|
|
.i_wb_sel (o_wb_sel),
|
|
.i_wb_we (o_wb_we),
|
|
.i_wb_cyc (o_wb_cyc),
|
|
.i_wb_stb (o_wb_stb),
|
|
.i_wb_cti (3'd0),
|
|
.i_wb_bte (2'd0),
|
|
.i_wb_idata (i_wb_rdt),
|
|
.i_wb_ack (i_wb_ack),
|
|
.i_wb_err (i_wb_err),
|
|
.i_wb_rty (1'b0));
|
|
|
|
`endif
|
|
endmodule
|
|
`default_nettype wire
|