Remove ahb connect axi4.
This commit is contained in:
parent
902f44a21c
commit
a8c8d46382
|
@ -1,432 +0,0 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
|
||||||
//
|
|
||||||
// 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$
|
|
||||||
//
|
|
||||||
// Owner:
|
|
||||||
// Function: AHB to AXI4 Bridge
|
|
||||||
// Comments:
|
|
||||||
//
|
|
||||||
//********************************************************************************
|
|
||||||
module ahb_to_axi4
|
|
||||||
import el2_pkg::*;
|
|
||||||
#(
|
|
||||||
TAG = 1,
|
|
||||||
`include "el2_param.vh"
|
|
||||||
)
|
|
||||||
// ,TAG = 1)
|
|
||||||
(
|
|
||||||
input clk,
|
|
||||||
input rst_l,
|
|
||||||
input scan_mode,
|
|
||||||
input bus_clk_en,
|
|
||||||
input clk_override,
|
|
||||||
|
|
||||||
// AXI signals
|
|
||||||
// AXI Write Channels
|
|
||||||
output logic axi_awvalid,
|
|
||||||
input logic axi_awready,
|
|
||||||
output logic [TAG-1:0] axi_awid,
|
|
||||||
output logic [ 31:0] axi_awaddr,
|
|
||||||
output logic [ 2:0] axi_awsize,
|
|
||||||
output logic [ 2:0] axi_awprot,
|
|
||||||
output logic [ 7:0] axi_awlen,
|
|
||||||
output logic [ 1:0] axi_awburst,
|
|
||||||
|
|
||||||
output logic axi_wvalid,
|
|
||||||
input logic axi_wready,
|
|
||||||
output logic [63:0] axi_wdata,
|
|
||||||
output logic [ 7:0] axi_wstrb,
|
|
||||||
output logic axi_wlast,
|
|
||||||
|
|
||||||
input logic axi_bvalid,
|
|
||||||
output logic axi_bready,
|
|
||||||
input logic [ 1:0] axi_bresp,
|
|
||||||
input logic [TAG-1:0] axi_bid,
|
|
||||||
|
|
||||||
// AXI Read Channels
|
|
||||||
output logic axi_arvalid,
|
|
||||||
input logic axi_arready,
|
|
||||||
output logic [TAG-1:0] axi_arid,
|
|
||||||
output logic [ 31:0] axi_araddr,
|
|
||||||
output logic [ 2:0] axi_arsize,
|
|
||||||
output logic [ 2:0] axi_arprot,
|
|
||||||
output logic [ 7:0] axi_arlen,
|
|
||||||
output logic [ 1:0] axi_arburst,
|
|
||||||
|
|
||||||
input logic axi_rvalid,
|
|
||||||
output logic axi_rready,
|
|
||||||
input logic [TAG-1:0] axi_rid,
|
|
||||||
input logic [ 63:0] axi_rdata,
|
|
||||||
input logic [ 1:0] axi_rresp,
|
|
||||||
|
|
||||||
// AHB-Lite signals
|
|
||||||
input logic [31:0] ahb_haddr, // ahb bus address
|
|
||||||
input logic [ 2:0] ahb_hburst, // tied to 0
|
|
||||||
input logic ahb_hmastlock, // tied to 0
|
|
||||||
input logic [ 3:0] ahb_hprot, // tied to 4'b0011
|
|
||||||
input logic [ 2:0] ahb_hsize, // size of bus transaction (possible values 0,1,2,3)
|
|
||||||
input logic [ 1:0] ahb_htrans, // Transaction type (possible values 0,2 only right now)
|
|
||||||
input logic ahb_hwrite, // ahb bus write
|
|
||||||
input logic [63:0] ahb_hwdata, // ahb bus write data
|
|
||||||
input logic ahb_hsel, // this slave was selected
|
|
||||||
input logic ahb_hreadyin, // previous hready was accepted or not
|
|
||||||
|
|
||||||
output logic [63:0] ahb_hrdata, // ahb bus read data
|
|
||||||
output logic ahb_hreadyout, // slave ready to accept transaction
|
|
||||||
output logic ahb_hresp // slave response (high indicates erro)
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
logic [7:0] master_wstrb;
|
|
||||||
|
|
||||||
typedef enum logic [1:0] {
|
|
||||||
IDLE = 2'b00, // Nothing in the buffer. No commands yet recieved
|
|
||||||
WR = 2'b01, // Write Command recieved
|
|
||||||
RD = 2'b10, // Read Command recieved
|
|
||||||
PEND = 2'b11 // Waiting on Read Data from core
|
|
||||||
} state_t;
|
|
||||||
state_t buf_state, buf_nxtstate;
|
|
||||||
logic buf_state_en;
|
|
||||||
|
|
||||||
// Buffer signals (one entry buffer)
|
|
||||||
logic buf_read_error_in, buf_read_error;
|
|
||||||
logic [63:0] buf_rdata;
|
|
||||||
|
|
||||||
logic ahb_hready;
|
|
||||||
logic ahb_hready_q;
|
|
||||||
logic [1:0] ahb_htrans_in, ahb_htrans_q;
|
|
||||||
logic [ 2:0] ahb_hsize_q;
|
|
||||||
logic ahb_hwrite_q;
|
|
||||||
logic [31:0] ahb_haddr_q;
|
|
||||||
logic [63:0] ahb_hwdata_q;
|
|
||||||
logic ahb_hresp_q;
|
|
||||||
|
|
||||||
//Miscellaneous signals
|
|
||||||
logic ahb_addr_in_dccm, ahb_addr_in_iccm, ahb_addr_in_pic;
|
|
||||||
logic ahb_addr_in_dccm_region_nc, ahb_addr_in_iccm_region_nc, ahb_addr_in_pic_region_nc;
|
|
||||||
// signals needed for the read data coming back from the core and to block any further commands as AHB is a blocking bus
|
|
||||||
logic buf_rdata_en;
|
|
||||||
|
|
||||||
logic ahb_addr_clk_en, buf_rdata_clk_en;
|
|
||||||
logic bus_clk, ahb_addr_clk, buf_rdata_clk;
|
|
||||||
// Command buffer is the holding station where we convert to AXI and send to core
|
|
||||||
logic cmdbuf_wr_en, cmdbuf_rst;
|
|
||||||
logic cmdbuf_full;
|
|
||||||
logic cmdbuf_vld, cmdbuf_write;
|
|
||||||
logic [ 1:0] cmdbuf_size;
|
|
||||||
logic [ 7:0] cmdbuf_wstrb;
|
|
||||||
logic [31:0] cmdbuf_addr;
|
|
||||||
logic [63:0] cmdbuf_wdata;
|
|
||||||
|
|
||||||
// FSM to control the bus states and when to block the hready and load the command buffer
|
|
||||||
always_comb begin
|
|
||||||
buf_nxtstate = IDLE;
|
|
||||||
buf_state_en = 1'b0;
|
|
||||||
buf_rdata_en = 1'b0; // signal to load the buffer when the core sends read data back
|
|
||||||
buf_read_error_in = 1'b0; // signal indicating that an error came back with the read from the core
|
|
||||||
cmdbuf_wr_en = 1'b0; // all clear from the gasket to load the buffer with the command for reads, command/dat for writes
|
|
||||||
case (buf_state)
|
|
||||||
IDLE: begin // No commands recieved
|
|
||||||
buf_nxtstate = ahb_hwrite ? WR : RD;
|
|
||||||
buf_state_en = ahb_hready & ahb_htrans[1] & ahb_hsel; // only transition on a valid hrtans
|
|
||||||
end
|
|
||||||
WR: begin // Write command recieved last cycle
|
|
||||||
buf_nxtstate = (ahb_hresp | (ahb_htrans[1:0] == 2'b0) | ~ahb_hsel) ? IDLE : ahb_hwrite ? WR : RD;
|
|
||||||
buf_state_en = (~cmdbuf_full | ahb_hresp);
|
|
||||||
cmdbuf_wr_en = ~cmdbuf_full & ~(ahb_hresp | ((ahb_htrans[1:0] == 2'b01) & ahb_hsel)); // Dont send command to the buffer in case of an error or when the master is not ready with the data now.
|
|
||||||
end
|
|
||||||
RD: begin // Read command recieved last cycle.
|
|
||||||
buf_nxtstate = ahb_hresp ? IDLE : PEND; // If error go to idle, else wait for read data
|
|
||||||
buf_state_en = (~cmdbuf_full | ahb_hresp); // only when command can go, or if its an error
|
|
||||||
cmdbuf_wr_en = ~ahb_hresp & ~cmdbuf_full; // send command only when no error
|
|
||||||
end
|
|
||||||
PEND: begin // Read Command has been sent. Waiting on Data.
|
|
||||||
buf_nxtstate = IDLE; // go back for next command and present data next cycle
|
|
||||||
buf_state_en = axi_rvalid & ~cmdbuf_write; // read data is back
|
|
||||||
buf_rdata_en = buf_state_en; // buffer the read data coming back from core
|
|
||||||
buf_read_error_in = buf_state_en & |axi_rresp[1:0]; // buffer error flag if return has Error ( ECC )
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end // always_comb begin
|
|
||||||
|
|
||||||
rvdffs_fpga #($bits(
|
|
||||||
state_t
|
|
||||||
)) state_reg (
|
|
||||||
.*,
|
|
||||||
.din(buf_nxtstate),
|
|
||||||
.dout({buf_state}),
|
|
||||||
.en(buf_state_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk)
|
|
||||||
);
|
|
||||||
|
|
||||||
assign master_wstrb[7:0] = ({8{ahb_hsize_q[2:0] == 3'b0}} & (8'b1 << ahb_haddr_q[2:0])) |
|
|
||||||
({8{ahb_hsize_q[2:0] == 3'b1}} & (8'b11 << ahb_haddr_q[2:0])) |
|
|
||||||
({8{ahb_hsize_q[2:0] == 3'b10}} & (8'b1111 << ahb_haddr_q[2:0])) |
|
|
||||||
({8{ahb_hsize_q[2:0] == 3'b11}} & 8'b1111_1111);
|
|
||||||
|
|
||||||
// AHB signals
|
|
||||||
assign ahb_hreadyout = ahb_hresp ? (ahb_hresp_q & ~ahb_hready_q) :
|
|
||||||
((~cmdbuf_full | (buf_state == IDLE)) & ~(buf_state == RD | buf_state == PEND) & ~buf_read_error);
|
|
||||||
|
|
||||||
assign ahb_hready = ahb_hreadyout & ahb_hreadyin;
|
|
||||||
assign ahb_htrans_in[1:0] = {2{ahb_hsel}} & ahb_htrans[1:0];
|
|
||||||
assign ahb_hrdata[63:0] = buf_rdata[63:0];
|
|
||||||
assign ahb_hresp = ((ahb_htrans_q[1:0] != 2'b0) & (buf_state != IDLE) &
|
|
||||||
|
|
||||||
((~(ahb_addr_in_dccm | ahb_addr_in_iccm)) | // request not for ICCM or DCCM
|
|
||||||
((ahb_addr_in_iccm | (ahb_addr_in_dccm & ahb_hwrite_q)) & ~((ahb_hsize_q[1:0] == 2'b10) | (ahb_hsize_q[1:0] == 2'b11))) | // ICCM Rd/Wr OR DCCM Wr not the right size
|
|
||||||
((ahb_hsize_q[2:0] == 3'h1) & ahb_haddr_q[0]) | // HW size but unaligned
|
|
||||||
((ahb_hsize_q[2:0] == 3'h2) & (|ahb_haddr_q[1:0])) | // W size but unaligned
|
|
||||||
((ahb_hsize_q[2:0] == 3'h3) & (|ahb_haddr_q[2:0])))) | // DW size but unaligned
|
|
||||||
buf_read_error | // Read ECC error
|
|
||||||
(ahb_hresp_q & ~ahb_hready_q);
|
|
||||||
|
|
||||||
// Buffer signals - needed for the read data and ECC error response
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(64)
|
|
||||||
) buf_rdata_ff (
|
|
||||||
.din(axi_rdata[63:0]),
|
|
||||||
.dout(buf_rdata[63:0]),
|
|
||||||
.clk(buf_rdata_clk),
|
|
||||||
.clken(buf_rdata_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) buf_read_error_ff (
|
|
||||||
.din(buf_read_error_in),
|
|
||||||
.dout(buf_read_error),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
); // buf_read_error will be high only one cycle
|
|
||||||
|
|
||||||
// All the Master signals are captured before presenting it to the command buffer. We check for Hresp before sending it to the cmd buffer.
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) hresp_ff (
|
|
||||||
.din(ahb_hresp),
|
|
||||||
.dout(ahb_hresp_q),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) hready_ff (
|
|
||||||
.din(ahb_hready),
|
|
||||||
.dout(ahb_hready_q),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(2)
|
|
||||||
) htrans_ff (
|
|
||||||
.din(ahb_htrans_in[1:0]),
|
|
||||||
.dout(ahb_htrans_q[1:0]),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(3)
|
|
||||||
) hsize_ff (
|
|
||||||
.din(ahb_hsize[2:0]),
|
|
||||||
.dout(ahb_hsize_q[2:0]),
|
|
||||||
.clk(ahb_addr_clk),
|
|
||||||
.clken(ahb_addr_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) hwrite_ff (
|
|
||||||
.din(ahb_hwrite),
|
|
||||||
.dout(ahb_hwrite_q),
|
|
||||||
.clk(ahb_addr_clk),
|
|
||||||
.clken(ahb_addr_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(32)
|
|
||||||
) haddr_ff (
|
|
||||||
.din(ahb_haddr[31:0]),
|
|
||||||
.dout(ahb_haddr_q[31:0]),
|
|
||||||
.clk(ahb_addr_clk),
|
|
||||||
.clken(ahb_addr_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
// Address check dccm
|
|
||||||
rvrangecheck #(
|
|
||||||
.CCM_SADR(pt.DCCM_SADR),
|
|
||||||
.CCM_SIZE(pt.DCCM_SIZE)
|
|
||||||
) addr_dccm_rangecheck (
|
|
||||||
.addr(ahb_haddr_q[31:0]),
|
|
||||||
.in_range(ahb_addr_in_dccm),
|
|
||||||
.in_region(ahb_addr_in_dccm_region_nc)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Address check iccm
|
|
||||||
if (pt.ICCM_ENABLE == 1) begin : GenICCM
|
|
||||||
rvrangecheck #(
|
|
||||||
.CCM_SADR(pt.ICCM_SADR),
|
|
||||||
.CCM_SIZE(pt.ICCM_SIZE)
|
|
||||||
) addr_iccm_rangecheck (
|
|
||||||
.addr(ahb_haddr_q[31:0]),
|
|
||||||
.in_range(ahb_addr_in_iccm),
|
|
||||||
.in_region(ahb_addr_in_iccm_region_nc)
|
|
||||||
);
|
|
||||||
end else begin : GenNoICCM
|
|
||||||
assign ahb_addr_in_iccm = '0;
|
|
||||||
assign ahb_addr_in_iccm_region_nc = '0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// PIC memory address check
|
|
||||||
rvrangecheck #(
|
|
||||||
.CCM_SADR(pt.PIC_BASE_ADDR),
|
|
||||||
.CCM_SIZE(pt.PIC_SIZE)
|
|
||||||
) addr_pic_rangecheck (
|
|
||||||
.addr(ahb_haddr_q[31:0]),
|
|
||||||
.in_range(ahb_addr_in_pic),
|
|
||||||
.in_region(ahb_addr_in_pic_region_nc)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Command Buffer - Holding for the commands to be sent for the AXI. It will be converted to the AXI signals.
|
|
||||||
assign cmdbuf_rst = (((axi_awvalid & axi_awready) | (axi_arvalid & axi_arready)) & ~cmdbuf_wr_en) | (ahb_hresp & ~cmdbuf_write);
|
|
||||||
assign cmdbuf_full = (cmdbuf_vld & ~((axi_awvalid & axi_awready) | (axi_arvalid & axi_arready)));
|
|
||||||
|
|
||||||
rvdffsc_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) cmdbuf_vldff (
|
|
||||||
.din(1'b1),
|
|
||||||
.dout(cmdbuf_vld),
|
|
||||||
.en(cmdbuf_wr_en),
|
|
||||||
.clear(cmdbuf_rst),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) cmdbuf_writeff (
|
|
||||||
.din(ahb_hwrite_q),
|
|
||||||
.dout(cmdbuf_write),
|
|
||||||
.en(cmdbuf_wr_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(2)
|
|
||||||
) cmdbuf_sizeff (
|
|
||||||
.din(ahb_hsize_q[1:0]),
|
|
||||||
.dout(cmdbuf_size[1:0]),
|
|
||||||
.en(cmdbuf_wr_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(8)
|
|
||||||
) cmdbuf_wstrbff (
|
|
||||||
.din(master_wstrb[7:0]),
|
|
||||||
.dout(cmdbuf_wstrb[7:0]),
|
|
||||||
.en(cmdbuf_wr_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffe #(
|
|
||||||
.WIDTH(32)
|
|
||||||
) cmdbuf_addrff (
|
|
||||||
.din (ahb_haddr_q[31:0]),
|
|
||||||
.dout(cmdbuf_addr[31:0]),
|
|
||||||
.en (cmdbuf_wr_en & bus_clk_en),
|
|
||||||
.clk (clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffe #(
|
|
||||||
.WIDTH(64)
|
|
||||||
) cmdbuf_wdataff (
|
|
||||||
.din (ahb_hwdata[63:0]),
|
|
||||||
.dout(cmdbuf_wdata[63:0]),
|
|
||||||
.en (cmdbuf_wr_en & bus_clk_en),
|
|
||||||
.clk (clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
// AXI Write Command Channel
|
|
||||||
assign axi_awvalid = cmdbuf_vld & cmdbuf_write;
|
|
||||||
assign axi_awid[TAG-1:0] = '0;
|
|
||||||
assign axi_awaddr[31:0] = cmdbuf_addr[31:0];
|
|
||||||
assign axi_awsize[2:0] = {1'b0, cmdbuf_size[1:0]};
|
|
||||||
assign axi_awprot[2:0] = 3'b0;
|
|
||||||
assign axi_awlen[7:0] = '0;
|
|
||||||
assign axi_awburst[1:0] = 2'b01;
|
|
||||||
// AXI Write Data Channel - This is tied to the command channel as we only write the command buffer once we have the data.
|
|
||||||
assign axi_wvalid = cmdbuf_vld & cmdbuf_write;
|
|
||||||
assign axi_wdata[63:0] = cmdbuf_wdata[63:0];
|
|
||||||
assign axi_wstrb[7:0] = cmdbuf_wstrb[7:0];
|
|
||||||
assign axi_wlast = 1'b1;
|
|
||||||
// AXI Write Response - Always ready. AHB does not require a write response.
|
|
||||||
assign axi_bready = 1'b1;
|
|
||||||
// AXI Read Channels
|
|
||||||
assign axi_arvalid = cmdbuf_vld & ~cmdbuf_write;
|
|
||||||
assign axi_arid[TAG-1:0] = '0;
|
|
||||||
assign axi_araddr[31:0] = cmdbuf_addr[31:0];
|
|
||||||
assign axi_arsize[2:0] = {1'b0, cmdbuf_size[1:0]};
|
|
||||||
assign axi_arprot = 3'b0;
|
|
||||||
assign axi_arlen[7:0] = '0;
|
|
||||||
assign axi_arburst[1:0] = 2'b01;
|
|
||||||
// AXI Read Response Channel - Always ready as AHB reads are blocking and the the buffer is available for the read coming back always.
|
|
||||||
assign axi_rready = 1'b1;
|
|
||||||
|
|
||||||
// Clock header logic
|
|
||||||
assign ahb_addr_clk_en = bus_clk_en & (ahb_hready & ahb_htrans[1]);
|
|
||||||
assign buf_rdata_clk_en = bus_clk_en & buf_rdata_en;
|
|
||||||
|
|
||||||
rvclkhdr bus_cgc (
|
|
||||||
.en(bus_clk_en),
|
|
||||||
.l1clk(bus_clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvclkhdr ahb_addr_cgc (
|
|
||||||
.en(ahb_addr_clk_en),
|
|
||||||
.l1clk(ahb_addr_clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvclkhdr buf_rdata_cgc (
|
|
||||||
.en(buf_rdata_clk_en),
|
|
||||||
.l1clk(buf_rdata_clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
endmodule // ahb_to_axi4
|
|
|
@ -1,743 +0,0 @@
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
// Copyright 2020 Western Digital Corporation or its affiliates.
|
|
||||||
//
|
|
||||||
// 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$
|
|
||||||
//
|
|
||||||
// Owner:
|
|
||||||
// Function: AXI4 -> AHB Bridge
|
|
||||||
// Comments:
|
|
||||||
//
|
|
||||||
//********************************************************************************
|
|
||||||
module axi4_to_ahb
|
|
||||||
import el2_pkg::*;
|
|
||||||
#(
|
|
||||||
`include "el2_param.vh",
|
|
||||||
parameter TAG = 1
|
|
||||||
) (
|
|
||||||
|
|
||||||
input clk,
|
|
||||||
input free_clk,
|
|
||||||
input rst_l,
|
|
||||||
input scan_mode,
|
|
||||||
input bus_clk_en,
|
|
||||||
input clk_override,
|
|
||||||
input dec_tlu_force_halt,
|
|
||||||
|
|
||||||
// AXI signals
|
|
||||||
// AXI Write Channels
|
|
||||||
input logic axi_awvalid,
|
|
||||||
output logic axi_awready,
|
|
||||||
input logic [TAG-1:0] axi_awid,
|
|
||||||
input logic [ 31:0] axi_awaddr,
|
|
||||||
input logic [ 2:0] axi_awsize,
|
|
||||||
input logic [ 2:0] axi_awprot,
|
|
||||||
|
|
||||||
input logic axi_wvalid,
|
|
||||||
output logic axi_wready,
|
|
||||||
input logic [63:0] axi_wdata,
|
|
||||||
input logic [ 7:0] axi_wstrb,
|
|
||||||
input logic axi_wlast,
|
|
||||||
|
|
||||||
output logic axi_bvalid,
|
|
||||||
input logic axi_bready,
|
|
||||||
output logic [ 1:0] axi_bresp,
|
|
||||||
output logic [TAG-1:0] axi_bid,
|
|
||||||
|
|
||||||
// AXI Read Channels
|
|
||||||
input logic axi_arvalid,
|
|
||||||
output logic axi_arready,
|
|
||||||
input logic [TAG-1:0] axi_arid,
|
|
||||||
input logic [ 31:0] axi_araddr,
|
|
||||||
input logic [ 2:0] axi_arsize,
|
|
||||||
input logic [ 2:0] axi_arprot,
|
|
||||||
|
|
||||||
output logic axi_rvalid,
|
|
||||||
input logic axi_rready,
|
|
||||||
output logic [TAG-1:0] axi_rid,
|
|
||||||
output logic [ 63:0] axi_rdata,
|
|
||||||
output logic [ 1:0] axi_rresp,
|
|
||||||
output logic axi_rlast,
|
|
||||||
|
|
||||||
// AHB-Lite signals
|
|
||||||
output logic [31:0] ahb_haddr, // ahb bus address
|
|
||||||
output logic [ 2:0] ahb_hburst, // tied to 0
|
|
||||||
output logic ahb_hmastlock, // tied to 0
|
|
||||||
output logic [ 3:0] ahb_hprot, // tied to 4'b0011
|
|
||||||
output logic [ 2:0] ahb_hsize, // size of bus transaction (possible values 0,1,2,3)
|
|
||||||
output logic [ 1:0] ahb_htrans, // Transaction type (possible values 0,2 only right now)
|
|
||||||
output logic ahb_hwrite, // ahb bus write
|
|
||||||
output logic [63:0] ahb_hwdata, // ahb bus write data
|
|
||||||
|
|
||||||
input logic [63:0] ahb_hrdata, // ahb bus read data
|
|
||||||
input logic ahb_hready, // slave ready to accept transaction
|
|
||||||
input logic ahb_hresp // slave response (high indicates erro)
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam ID = 1;
|
|
||||||
localparam PRTY = 1;
|
|
||||||
typedef enum logic [2:0] {
|
|
||||||
IDLE = 3'b000,
|
|
||||||
CMD_RD = 3'b001,
|
|
||||||
CMD_WR = 3'b010,
|
|
||||||
DATA_RD = 3'b011,
|
|
||||||
DATA_WR = 3'b100,
|
|
||||||
DONE = 3'b101,
|
|
||||||
STREAM_RD = 3'b110,
|
|
||||||
STREAM_ERR_RD = 3'b111
|
|
||||||
} state_t;
|
|
||||||
state_t buf_state, buf_nxtstate;
|
|
||||||
|
|
||||||
logic slave_valid;
|
|
||||||
logic slave_ready;
|
|
||||||
logic [TAG-1:0] slave_tag;
|
|
||||||
logic [ 63:0] slave_rdata;
|
|
||||||
logic [ 3:0] slave_opc;
|
|
||||||
|
|
||||||
logic wrbuf_en, wrbuf_data_en;
|
|
||||||
logic wrbuf_cmd_sent, wrbuf_rst;
|
|
||||||
logic wrbuf_vld;
|
|
||||||
logic wrbuf_data_vld;
|
|
||||||
logic [TAG-1:0] wrbuf_tag;
|
|
||||||
logic [ 2:0] wrbuf_size;
|
|
||||||
logic [ 31:0] wrbuf_addr;
|
|
||||||
logic [ 63:0] wrbuf_data;
|
|
||||||
logic [ 7:0] wrbuf_byteen;
|
|
||||||
|
|
||||||
logic master_valid;
|
|
||||||
logic master_ready;
|
|
||||||
logic [TAG-1:0] master_tag;
|
|
||||||
logic [ 31:0] master_addr;
|
|
||||||
logic [ 63:0] master_wdata;
|
|
||||||
logic [ 2:0] master_size;
|
|
||||||
logic [ 2:0] master_opc;
|
|
||||||
logic [ 7:0] master_byteen;
|
|
||||||
|
|
||||||
// Buffer signals (one entry buffer)
|
|
||||||
logic [ 31:0] buf_addr;
|
|
||||||
logic [ 1:0] buf_size;
|
|
||||||
logic buf_write;
|
|
||||||
logic [ 7:0] buf_byteen;
|
|
||||||
logic buf_aligned;
|
|
||||||
logic [ 63:0] buf_data;
|
|
||||||
logic [TAG-1:0] buf_tag;
|
|
||||||
|
|
||||||
//Miscellaneous signals
|
|
||||||
logic buf_rst;
|
|
||||||
logic [TAG-1:0] buf_tag_in;
|
|
||||||
logic [ 31:0] buf_addr_in;
|
|
||||||
logic [ 7:0] buf_byteen_in;
|
|
||||||
logic [ 63:0] buf_data_in;
|
|
||||||
logic buf_write_in;
|
|
||||||
logic buf_aligned_in;
|
|
||||||
logic [ 2:0] buf_size_in;
|
|
||||||
|
|
||||||
logic buf_state_en;
|
|
||||||
logic buf_wr_en;
|
|
||||||
logic buf_data_wr_en;
|
|
||||||
logic slvbuf_error_en;
|
|
||||||
logic wr_cmd_vld;
|
|
||||||
|
|
||||||
logic cmd_done_rst, cmd_done, cmd_doneQ;
|
|
||||||
logic trxn_done;
|
|
||||||
logic [2:0] buf_cmd_byte_ptr, buf_cmd_byte_ptrQ, buf_cmd_nxtbyte_ptr;
|
|
||||||
logic buf_cmd_byte_ptr_en;
|
|
||||||
logic found;
|
|
||||||
|
|
||||||
logic slave_valid_pre;
|
|
||||||
logic ahb_hready_q;
|
|
||||||
logic ahb_hresp_q;
|
|
||||||
logic [ 1:0] ahb_htrans_q;
|
|
||||||
logic ahb_hwrite_q;
|
|
||||||
logic [ 63:0] ahb_hrdata_q;
|
|
||||||
|
|
||||||
|
|
||||||
logic slvbuf_write;
|
|
||||||
logic slvbuf_error;
|
|
||||||
logic [TAG-1:0] slvbuf_tag;
|
|
||||||
|
|
||||||
logic slvbuf_error_in;
|
|
||||||
logic slvbuf_wr_en;
|
|
||||||
logic bypass_en;
|
|
||||||
logic rd_bypass_idle;
|
|
||||||
|
|
||||||
logic last_addr_en;
|
|
||||||
logic [ 31:0] last_bus_addr;
|
|
||||||
|
|
||||||
// Clocks
|
|
||||||
logic buf_clken;
|
|
||||||
logic ahbm_data_clken;
|
|
||||||
|
|
||||||
logic buf_clk;
|
|
||||||
logic bus_clk;
|
|
||||||
logic ahbm_data_clk;
|
|
||||||
|
|
||||||
logic dec_tlu_force_halt_bus, dec_tlu_force_halt_bus_ns, dec_tlu_force_halt_bus_q;
|
|
||||||
|
|
||||||
// Function to get the length from byte enable
|
|
||||||
function automatic logic [1:0] get_write_size;
|
|
||||||
input logic [7:0] byteen;
|
|
||||||
|
|
||||||
logic [1:0] size;
|
|
||||||
|
|
||||||
size[1:0] = (2'b11 & {2{(byteen[7:0] == 8'hff)}}) |
|
|
||||||
(2'b10 & {2{((byteen[7:0] == 8'hf0) | (byteen[7:0] == 8'h0f))}}) |
|
|
||||||
(2'b01 & {2{((byteen[7:0] == 8'hc0) | (byteen[7:0] == 8'h30) | (byteen[7:0] == 8'h0c) | (byteen[7:0] == 8'h03))}});
|
|
||||||
|
|
||||||
return size[1:0];
|
|
||||||
endfunction // get_write_size
|
|
||||||
|
|
||||||
// Function to get the length from byte enable
|
|
||||||
function automatic logic [2:0] get_write_addr;
|
|
||||||
input logic [7:0] byteen;
|
|
||||||
|
|
||||||
logic [2:0] addr;
|
|
||||||
|
|
||||||
addr[2:0] = (3'h0 & {3{((byteen[7:0] == 8'hff) | (byteen[7:0] == 8'h0f) | (byteen[7:0] == 8'h03))}}) |
|
|
||||||
(3'h2 & {3{(byteen[7:0] == 8'h0c)}}) |
|
|
||||||
(3'h4 & {3{((byteen[7:0] == 8'hf0) | (byteen[7:0] == 8'h03))}}) |
|
|
||||||
(3'h6 & {3{(byteen[7:0] == 8'hc0)}});
|
|
||||||
|
|
||||||
return addr[2:0];
|
|
||||||
endfunction // get_write_addr
|
|
||||||
|
|
||||||
// Function to get the next byte pointer
|
|
||||||
function automatic logic [2:0] get_nxtbyte_ptr(logic [2:0] current_byte_ptr, logic [7:0] byteen,
|
|
||||||
logic get_next);
|
|
||||||
logic [2:0] start_ptr;
|
|
||||||
logic found;
|
|
||||||
found = '0;
|
|
||||||
//get_nxtbyte_ptr[2:0] = current_byte_ptr[2:0];
|
|
||||||
start_ptr[2:0] = get_next ? (current_byte_ptr[2:0] + 3'b1) : current_byte_ptr[2:0];
|
|
||||||
for (int j = 0; j < 8; j++) begin
|
|
||||||
if (~found) begin
|
|
||||||
get_nxtbyte_ptr[2:0] = 3'(j);
|
|
||||||
found |= (byteen[j] & (3'(j) >= start_ptr[2:0]));
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endfunction // get_nextbyte_ptr
|
|
||||||
|
|
||||||
// Create bus synchronized version of force halt
|
|
||||||
assign dec_tlu_force_halt_bus = dec_tlu_force_halt | dec_tlu_force_halt_bus_q;
|
|
||||||
assign dec_tlu_force_halt_bus_ns = ~bus_clk_en & dec_tlu_force_halt_bus;
|
|
||||||
rvdff #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) force_halt_busff (
|
|
||||||
.din (dec_tlu_force_halt_bus_ns),
|
|
||||||
.dout(dec_tlu_force_halt_bus_q),
|
|
||||||
.clk (free_clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write buffer
|
|
||||||
assign wrbuf_en = axi_awvalid & axi_awready & master_ready;
|
|
||||||
assign wrbuf_data_en = axi_wvalid & axi_wready & master_ready;
|
|
||||||
assign wrbuf_cmd_sent = master_valid & master_ready & (master_opc[2:1] == 2'b01);
|
|
||||||
assign wrbuf_rst = (wrbuf_cmd_sent & ~wrbuf_en) | dec_tlu_force_halt_bus;
|
|
||||||
|
|
||||||
assign axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent) & master_ready;
|
|
||||||
assign axi_wready = ~(wrbuf_data_vld & ~wrbuf_cmd_sent) & master_ready;
|
|
||||||
assign axi_arready = ~(wrbuf_vld & wrbuf_data_vld) & master_ready;
|
|
||||||
assign axi_rlast = 1'b1;
|
|
||||||
|
|
||||||
assign wr_cmd_vld = (wrbuf_vld & wrbuf_data_vld);
|
|
||||||
assign master_valid = wr_cmd_vld | axi_arvalid;
|
|
||||||
assign master_tag[TAG-1:0] = wr_cmd_vld ? wrbuf_tag[TAG-1:0] : axi_arid[TAG-1:0];
|
|
||||||
assign master_opc[2:0] = wr_cmd_vld ? 3'b011 : 3'b0;
|
|
||||||
assign master_addr[31:0] = wr_cmd_vld ? wrbuf_addr[31:0] : axi_araddr[31:0];
|
|
||||||
assign master_size[2:0] = wr_cmd_vld ? wrbuf_size[2:0] : axi_arsize[2:0];
|
|
||||||
assign master_byteen[7:0] = wrbuf_byteen[7:0];
|
|
||||||
assign master_wdata[63:0] = wrbuf_data[63:0];
|
|
||||||
|
|
||||||
// AXI response channel signals
|
|
||||||
assign axi_bvalid = slave_valid & slave_ready & slave_opc[3];
|
|
||||||
assign axi_bresp[1:0] = slave_opc[0] ? 2'b10 : (slave_opc[1] ? 2'b11 : 2'b0);
|
|
||||||
assign axi_bid[TAG-1:0] = slave_tag[TAG-1:0];
|
|
||||||
|
|
||||||
assign axi_rvalid = slave_valid & slave_ready & (slave_opc[3:2] == 2'b0);
|
|
||||||
assign axi_rresp[1:0] = slave_opc[0] ? 2'b10 : (slave_opc[1] ? 2'b11 : 2'b0);
|
|
||||||
assign axi_rid[TAG-1:0] = slave_tag[TAG-1:0];
|
|
||||||
assign axi_rdata[63:0] = slave_rdata[63:0];
|
|
||||||
assign slave_ready = axi_bready & axi_rready;
|
|
||||||
|
|
||||||
// FIFO state machine
|
|
||||||
always_comb begin
|
|
||||||
buf_nxtstate = IDLE;
|
|
||||||
buf_state_en = 1'b0;
|
|
||||||
buf_wr_en = 1'b0;
|
|
||||||
buf_data_wr_en = 1'b0;
|
|
||||||
slvbuf_error_in = 1'b0;
|
|
||||||
slvbuf_error_en = 1'b0;
|
|
||||||
buf_write_in = 1'b0;
|
|
||||||
cmd_done = 1'b0;
|
|
||||||
trxn_done = 1'b0;
|
|
||||||
buf_cmd_byte_ptr_en = 1'b0;
|
|
||||||
buf_cmd_byte_ptr[2:0] = '0;
|
|
||||||
slave_valid_pre = 1'b0;
|
|
||||||
master_ready = 1'b0;
|
|
||||||
ahb_htrans[1:0] = 2'b0;
|
|
||||||
slvbuf_wr_en = 1'b0;
|
|
||||||
bypass_en = 1'b0;
|
|
||||||
rd_bypass_idle = 1'b0;
|
|
||||||
|
|
||||||
case (buf_state)
|
|
||||||
IDLE: begin
|
|
||||||
master_ready = 1'b1;
|
|
||||||
buf_write_in = (master_opc[2:1] == 2'b01);
|
|
||||||
buf_nxtstate = buf_write_in ? CMD_WR : CMD_RD;
|
|
||||||
buf_state_en = master_valid & master_ready;
|
|
||||||
buf_wr_en = buf_state_en;
|
|
||||||
buf_data_wr_en = buf_state_en & (buf_nxtstate == CMD_WR);
|
|
||||||
buf_cmd_byte_ptr_en = buf_state_en;
|
|
||||||
buf_cmd_byte_ptr[2:0] = buf_write_in ? get_nxtbyte_ptr(3'b0, buf_byteen_in[7:0], 1'b0) :
|
|
||||||
master_addr[2:0];
|
|
||||||
bypass_en = buf_state_en;
|
|
||||||
rd_bypass_idle = bypass_en & (buf_nxtstate == CMD_RD);
|
|
||||||
ahb_htrans[1:0] = {2{bypass_en}} & 2'b10;
|
|
||||||
end
|
|
||||||
CMD_RD: begin
|
|
||||||
buf_nxtstate = (master_valid & (master_opc[2:0] == 3'b000)) ? STREAM_RD : DATA_RD;
|
|
||||||
buf_state_en = ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) & ~ahb_hwrite_q;
|
|
||||||
cmd_done = buf_state_en & ~master_valid;
|
|
||||||
slvbuf_wr_en = buf_state_en;
|
|
||||||
master_ready = buf_state_en & (buf_nxtstate == STREAM_RD);
|
|
||||||
buf_wr_en = master_ready;
|
|
||||||
bypass_en = master_ready & master_valid;
|
|
||||||
buf_cmd_byte_ptr[2:0] = bypass_en ? master_addr[2:0] : buf_addr[2:0];
|
|
||||||
ahb_htrans[1:0] = 2'b10 & {2{~buf_state_en | bypass_en}};
|
|
||||||
end
|
|
||||||
STREAM_RD: begin
|
|
||||||
master_ready = (ahb_hready_q & ~ahb_hresp_q) & ~(master_valid & master_opc[2:1] == 2'b01);
|
|
||||||
buf_wr_en = (master_valid & master_ready & (master_opc[2:0] == 3'b000)); // update the fifo if we are streaming the read commands
|
|
||||||
buf_nxtstate = ahb_hresp_q ? STREAM_ERR_RD : (buf_wr_en ? STREAM_RD : DATA_RD); // assuming that the master accpets the slave response right away.
|
|
||||||
buf_state_en = (ahb_hready_q | ahb_hresp_q);
|
|
||||||
buf_data_wr_en = buf_state_en;
|
|
||||||
slvbuf_error_in = ahb_hresp_q;
|
|
||||||
slvbuf_error_en = buf_state_en;
|
|
||||||
slave_valid_pre = buf_state_en & ~ahb_hresp_q; // send a response right away if we are not going through an error response.
|
|
||||||
cmd_done = buf_state_en & ~master_valid; // last one of the stream should not send a htrans
|
|
||||||
bypass_en = master_ready & master_valid & (buf_nxtstate == STREAM_RD) & buf_state_en;
|
|
||||||
buf_cmd_byte_ptr[2:0] = bypass_en ? master_addr[2:0] : buf_addr[2:0];
|
|
||||||
ahb_htrans[1:0] = 2'b10 & {2{~((buf_nxtstate != STREAM_RD) & buf_state_en)}};
|
|
||||||
slvbuf_wr_en = buf_wr_en; // shifting the contents from the buf to slv_buf for streaming cases
|
|
||||||
end // case: STREAM_RD
|
|
||||||
STREAM_ERR_RD: begin
|
|
||||||
buf_nxtstate = DATA_RD;
|
|
||||||
buf_state_en = ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) & ~ahb_hwrite_q;
|
|
||||||
slave_valid_pre = buf_state_en;
|
|
||||||
slvbuf_wr_en = buf_state_en; // Overwrite slvbuf with buffer
|
|
||||||
buf_cmd_byte_ptr[2:0] = buf_addr[2:0];
|
|
||||||
ahb_htrans[1:0] = 2'b10 & {2{~buf_state_en}};
|
|
||||||
end
|
|
||||||
DATA_RD: begin
|
|
||||||
buf_nxtstate = DONE;
|
|
||||||
buf_state_en = (ahb_hready_q | ahb_hresp_q);
|
|
||||||
buf_data_wr_en = buf_state_en;
|
|
||||||
slvbuf_error_in = ahb_hresp_q;
|
|
||||||
slvbuf_error_en = buf_state_en;
|
|
||||||
slvbuf_wr_en = buf_state_en;
|
|
||||||
|
|
||||||
end
|
|
||||||
CMD_WR: begin
|
|
||||||
buf_nxtstate = DATA_WR;
|
|
||||||
trxn_done = ahb_hready_q & ahb_hwrite_q & (ahb_htrans_q[1:0] != 2'b0);
|
|
||||||
buf_state_en = trxn_done;
|
|
||||||
buf_cmd_byte_ptr_en = buf_state_en;
|
|
||||||
slvbuf_wr_en = buf_state_en;
|
|
||||||
buf_cmd_byte_ptr = trxn_done ?
|
|
||||||
get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0], buf_byteen[7:0], 1'b1) : buf_cmd_byte_ptrQ;
|
|
||||||
cmd_done = trxn_done & (buf_aligned | (buf_cmd_byte_ptrQ == 3'b111) |
|
|
||||||
(buf_byteen[get_nxtbyte_ptr(
|
|
||||||
buf_cmd_byte_ptrQ[2:0], buf_byteen[7:0], 1'b1)] == 1'b0));
|
|
||||||
ahb_htrans[1:0] = {2{~(cmd_done | cmd_doneQ)}} & 2'b10;
|
|
||||||
end
|
|
||||||
DATA_WR: begin
|
|
||||||
buf_state_en = (cmd_doneQ & ahb_hready_q) | ahb_hresp_q;
|
|
||||||
master_ready = buf_state_en & ~ahb_hresp_q & slave_ready; // Ready to accept new command if current command done and no error
|
|
||||||
buf_nxtstate = (ahb_hresp_q | ~slave_ready) ? DONE :
|
|
||||||
((master_valid & master_ready) ? ((master_opc[2:1] == 2'b01) ? CMD_WR : CMD_RD) : IDLE);
|
|
||||||
slvbuf_error_in = ahb_hresp_q;
|
|
||||||
slvbuf_error_en = buf_state_en;
|
|
||||||
|
|
||||||
buf_write_in = (master_opc[2:1] == 2'b01);
|
|
||||||
buf_wr_en = buf_state_en & ((buf_nxtstate == CMD_WR) | (buf_nxtstate == CMD_RD));
|
|
||||||
buf_data_wr_en = buf_wr_en;
|
|
||||||
|
|
||||||
cmd_done = (ahb_hresp_q | (ahb_hready_q & (ahb_htrans_q[1:0] != 2'b0) &
|
|
||||||
((buf_cmd_byte_ptrQ == 3'b111) | (buf_byteen[get_nxtbyte_ptr(
|
|
||||||
buf_cmd_byte_ptrQ[2:0], buf_byteen[7:0], 1'b1)] == 1'b0))));
|
|
||||||
bypass_en = buf_state_en & buf_write_in & (buf_nxtstate == CMD_WR); // Only bypass for writes for the time being
|
|
||||||
ahb_htrans[1:0] = {2{(~(cmd_done | cmd_doneQ) | bypass_en)}} & 2'b10;
|
|
||||||
slave_valid_pre = buf_state_en & (buf_nxtstate != DONE);
|
|
||||||
|
|
||||||
trxn_done = ahb_hready_q & ahb_hwrite_q & (ahb_htrans_q[1:0] != 2'b0);
|
|
||||||
buf_cmd_byte_ptr_en = trxn_done | bypass_en;
|
|
||||||
buf_cmd_byte_ptr = bypass_en ? get_nxtbyte_ptr(3'b0, buf_byteen_in[7:0], 1'b0) : trxn_done ?
|
|
||||||
get_nxtbyte_ptr(buf_cmd_byte_ptrQ[2:0], buf_byteen[7:0], 1'b1) : buf_cmd_byte_ptrQ;
|
|
||||||
end
|
|
||||||
DONE: begin
|
|
||||||
buf_nxtstate = IDLE;
|
|
||||||
buf_state_en = slave_ready;
|
|
||||||
slvbuf_error_en = 1'b1;
|
|
||||||
slave_valid_pre = 1'b1;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
assign buf_rst = dec_tlu_force_halt_bus;
|
|
||||||
assign cmd_done_rst = slave_valid_pre;
|
|
||||||
assign buf_addr_in[31:3] = master_addr[31:3];
|
|
||||||
assign buf_addr_in[2:0] = (buf_aligned_in & (master_opc[2:1] == 2'b01)) ? get_write_addr(
|
|
||||||
master_byteen[7:0]
|
|
||||||
) : master_addr[2:0];
|
|
||||||
assign buf_tag_in[TAG-1:0] = master_tag[TAG-1:0];
|
|
||||||
assign buf_byteen_in[7:0] = wrbuf_byteen[7:0];
|
|
||||||
assign buf_data_in[63:0] = (buf_state == DATA_RD) ? ahb_hrdata_q[63:0] : master_wdata[63:0];
|
|
||||||
assign buf_size_in[1:0] = (buf_aligned_in & (master_size[1:0] == 2'b11) & (master_opc[2:1] == 2'b01)) ? get_write_size(
|
|
||||||
master_byteen[7:0]
|
|
||||||
) : master_size[1:0];
|
|
||||||
assign buf_aligned_in = (master_opc[2:0] == 3'b0) | // reads are always aligned since they are either DW or sideeffects
|
|
||||||
(master_size[1:0] == 2'b0) | (master_size[1:0] == 2'b01) | (master_size[1:0] == 2'b10) | // Always aligned for Byte/HW/Word since they can be only for non-idempotent. IFU/SB are always aligned
|
|
||||||
((master_size[1:0] == 2'b11) &
|
|
||||||
((master_byteen[7:0] == 8'h3) | (master_byteen[7:0] == 8'hc) | (master_byteen[7:0] == 8'h30) | (master_byteen[7:0] == 8'hc0) |
|
|
||||||
(master_byteen[7:0] == 8'hf) | (master_byteen[7:0] == 8'hf0) | (master_byteen[7:0] == 8'hff)));
|
|
||||||
|
|
||||||
// Generate the ahb signals
|
|
||||||
assign ahb_haddr[31:3] = bypass_en ? master_addr[31:3] : buf_addr[31:3];
|
|
||||||
assign ahb_haddr[2:0] = {3{(ahb_htrans == 2'b10)}} & buf_cmd_byte_ptr[2:0]; // Trxn should be aligned during IDLE
|
|
||||||
assign ahb_hsize[2:0] = bypass_en ? {1'b0, ({2{buf_aligned_in}} & buf_size_in[1:0])} :
|
|
||||||
{1'b0, ({2{buf_aligned}} & buf_size[1:0])}; // Send the full size for aligned trxn
|
|
||||||
assign ahb_hburst[2:0] = 3'b0;
|
|
||||||
assign ahb_hmastlock = 1'b0;
|
|
||||||
assign ahb_hprot[3:0] = {3'b001, ~axi_arprot[2]};
|
|
||||||
assign ahb_hwrite = bypass_en ? (master_opc[2:1] == 2'b01) : buf_write;
|
|
||||||
assign ahb_hwdata[63:0] = buf_data[63:0];
|
|
||||||
|
|
||||||
assign slave_valid = slave_valid_pre; // & (~slvbuf_posted_write | slvbuf_error);
|
|
||||||
assign slave_opc[3:2] = slvbuf_write ? 2'b11 : 2'b00;
|
|
||||||
assign slave_opc[1:0] = {2{slvbuf_error}} & 2'b10;
|
|
||||||
assign slave_rdata[63:0] = slvbuf_error ? {2{last_bus_addr[31:0]}} : ((buf_state == DONE) ? buf_data[63:0] : ahb_hrdata_q[63:0]);
|
|
||||||
assign slave_tag[TAG-1:0] = slvbuf_tag[TAG-1:0];
|
|
||||||
|
|
||||||
assign last_addr_en = (ahb_htrans[1:0] != 2'b0) & ahb_hready & ahb_hwrite;
|
|
||||||
|
|
||||||
|
|
||||||
rvdffsc_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) wrbuf_vldff (
|
|
||||||
.din(1'b1),
|
|
||||||
.dout(wrbuf_vld),
|
|
||||||
.en(wrbuf_en),
|
|
||||||
.clear(wrbuf_rst),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffsc_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) wrbuf_data_vldff (
|
|
||||||
.din(1'b1),
|
|
||||||
.dout(wrbuf_data_vld),
|
|
||||||
.en(wrbuf_data_en),
|
|
||||||
.clear(wrbuf_rst),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(TAG)
|
|
||||||
) wrbuf_tagff (
|
|
||||||
.din(axi_awid[TAG-1:0]),
|
|
||||||
.dout(wrbuf_tag[TAG-1:0]),
|
|
||||||
.en(wrbuf_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(3)
|
|
||||||
) wrbuf_sizeff (
|
|
||||||
.din(axi_awsize[2:0]),
|
|
||||||
.dout(wrbuf_size[2:0]),
|
|
||||||
.en(wrbuf_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffe #(
|
|
||||||
.WIDTH(32)
|
|
||||||
) wrbuf_addrff (
|
|
||||||
.din (axi_awaddr[31:0]),
|
|
||||||
.dout(wrbuf_addr[31:0]),
|
|
||||||
.en (wrbuf_en & bus_clk_en),
|
|
||||||
.clk (clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffe #(
|
|
||||||
.WIDTH(64)
|
|
||||||
) wrbuf_dataff (
|
|
||||||
.din (axi_wdata[63:0]),
|
|
||||||
.dout(wrbuf_data[63:0]),
|
|
||||||
.en (wrbuf_data_en & bus_clk_en),
|
|
||||||
.clk (clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(8)
|
|
||||||
) wrbuf_byteenff (
|
|
||||||
.din(axi_wstrb[7:0]),
|
|
||||||
.dout(wrbuf_byteen[7:0]),
|
|
||||||
.en(wrbuf_data_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(32)
|
|
||||||
) last_bus_addrff (
|
|
||||||
.din(ahb_haddr[31:0]),
|
|
||||||
.dout(last_bus_addr[31:0]),
|
|
||||||
.en(last_addr_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
rvdffsc_fpga #(
|
|
||||||
.WIDTH($bits(state_t))
|
|
||||||
) buf_state_ff (
|
|
||||||
.din(buf_nxtstate),
|
|
||||||
.dout({buf_state}),
|
|
||||||
.en(buf_state_en),
|
|
||||||
.clear(buf_rst),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) buf_writeff (
|
|
||||||
.din(buf_write_in),
|
|
||||||
.dout(buf_write),
|
|
||||||
.en(buf_wr_en),
|
|
||||||
.clk(buf_clk),
|
|
||||||
.clken(buf_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(TAG)
|
|
||||||
) buf_tagff (
|
|
||||||
.din(buf_tag_in[TAG-1:0]),
|
|
||||||
.dout(buf_tag[TAG-1:0]),
|
|
||||||
.en(buf_wr_en),
|
|
||||||
.clk(buf_clk),
|
|
||||||
.clken(buf_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffe #(
|
|
||||||
.WIDTH(32)
|
|
||||||
) buf_addrff (
|
|
||||||
.din (buf_addr_in[31:0]),
|
|
||||||
.dout(buf_addr[31:0]),
|
|
||||||
.en (buf_wr_en & bus_clk_en),
|
|
||||||
.clk (clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(2)
|
|
||||||
) buf_sizeff (
|
|
||||||
.din(buf_size_in[1:0]),
|
|
||||||
.dout(buf_size[1:0]),
|
|
||||||
.en(buf_wr_en),
|
|
||||||
.clk(buf_clk),
|
|
||||||
.clken(buf_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) buf_alignedff (
|
|
||||||
.din(buf_aligned_in),
|
|
||||||
.dout(buf_aligned),
|
|
||||||
.en(buf_wr_en),
|
|
||||||
.clk(buf_clk),
|
|
||||||
.clken(buf_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(8)
|
|
||||||
) buf_byteenff (
|
|
||||||
.din(buf_byteen_in[7:0]),
|
|
||||||
.dout(buf_byteen[7:0]),
|
|
||||||
.en(buf_wr_en),
|
|
||||||
.clk(buf_clk),
|
|
||||||
.clken(buf_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffe #(
|
|
||||||
.WIDTH(64)
|
|
||||||
) buf_dataff (
|
|
||||||
.din (buf_data_in[63:0]),
|
|
||||||
.dout(buf_data[63:0]),
|
|
||||||
.en (buf_data_wr_en & bus_clk_en),
|
|
||||||
.clk (clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) slvbuf_writeff (
|
|
||||||
.din(buf_write),
|
|
||||||
.dout(slvbuf_write),
|
|
||||||
.en(slvbuf_wr_en),
|
|
||||||
.clk(buf_clk),
|
|
||||||
.clken(buf_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(TAG)
|
|
||||||
) slvbuf_tagff (
|
|
||||||
.din(buf_tag[TAG-1:0]),
|
|
||||||
.dout(slvbuf_tag[TAG-1:0]),
|
|
||||||
.en(slvbuf_wr_en),
|
|
||||||
.clk(buf_clk),
|
|
||||||
.clken(buf_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) slvbuf_errorff (
|
|
||||||
.din(slvbuf_error_in),
|
|
||||||
.dout(slvbuf_error),
|
|
||||||
.en(slvbuf_error_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
rvdffsc_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) buf_cmd_doneff (
|
|
||||||
.din(1'b1),
|
|
||||||
.dout(cmd_doneQ),
|
|
||||||
.en(cmd_done),
|
|
||||||
.clear(cmd_done_rst),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdffs_fpga #(
|
|
||||||
.WIDTH(3)
|
|
||||||
) buf_cmd_byte_ptrff (
|
|
||||||
.din(buf_cmd_byte_ptr[2:0]),
|
|
||||||
.dout(buf_cmd_byte_ptrQ[2:0]),
|
|
||||||
.en(buf_cmd_byte_ptr_en),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) hready_ff (
|
|
||||||
.din(ahb_hready),
|
|
||||||
.dout(ahb_hready_q),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(2)
|
|
||||||
) htrans_ff (
|
|
||||||
.din(ahb_htrans[1:0]),
|
|
||||||
.dout(ahb_htrans_q[1:0]),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) hwrite_ff (
|
|
||||||
.din(ahb_hwrite),
|
|
||||||
.dout(ahb_hwrite_q),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(1)
|
|
||||||
) hresp_ff (
|
|
||||||
.din(ahb_hresp),
|
|
||||||
.dout(ahb_hresp_q),
|
|
||||||
.clk(bus_clk),
|
|
||||||
.clken(bus_clk_en),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvdff_fpga #(
|
|
||||||
.WIDTH(64)
|
|
||||||
) hrdata_ff (
|
|
||||||
.din(ahb_hrdata[63:0]),
|
|
||||||
.dout(ahb_hrdata_q[63:0]),
|
|
||||||
.clk(ahbm_data_clk),
|
|
||||||
.clken(ahbm_data_clken),
|
|
||||||
.rawclk(clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
// Clock headers
|
|
||||||
// clock enables for ahbm addr/data
|
|
||||||
assign buf_clken = bus_clk_en & (buf_wr_en | slvbuf_wr_en | clk_override);
|
|
||||||
assign ahbm_data_clken = bus_clk_en & ((buf_state != IDLE) | clk_override);
|
|
||||||
|
|
||||||
rvclkhdr bus_cgc (
|
|
||||||
.en(bus_clk_en),
|
|
||||||
.l1clk(bus_clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvclkhdr buf_cgc (
|
|
||||||
.en(buf_clken),
|
|
||||||
.l1clk(buf_clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
rvclkhdr ahbm_data_cgc (
|
|
||||||
.en(ahbm_data_clken),
|
|
||||||
.l1clk(ahbm_data_clk),
|
|
||||||
.*
|
|
||||||
);
|
|
||||||
|
|
||||||
endmodule // axi4_to_ahb
|
|
|
@ -43,9 +43,6 @@
|
||||||
../design/lib/beh_lib.sv
|
../design/lib/beh_lib.sv
|
||||||
../design/lib/mem_lib.sv
|
../design/lib/mem_lib.sv
|
||||||
|
|
||||||
../design/lib/ahb_to_axi4.sv
|
|
||||||
../design/lib/axi4_to_ahb.sv
|
|
||||||
|
|
||||||
./ahb_sif.sv
|
./ahb_sif.sv
|
||||||
./axi_lsu_dma_bridge.sv
|
./axi_lsu_dma_bridge.sv
|
||||||
./soc_top.sv
|
./soc_top.sv
|
Loading…
Reference in New Issue