abstractaccelerator/design/lib/svci_to_axi4.sv

209 lines
10 KiB
Systemverilog

// SPDX-License-Identifier: Apache-2.0
// Copyright 2018 Western Digital Corporation or it's 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: SVCI to AXI4 Bridge
// Comments:
//
//********************************************************************************
module svci_to_axi4 #(parameter TAG = 1,
ID = 1,
PRTY = 1) (
input logic clk,
input logic rst_l,
input logic scan_mode,
input logic bus_clk_en,
input logic clk_override,
// AXI signals
// AXI Write Channels
output logic axi_awvalid,
input logic axi_awready,
output logic axi_awposted,
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 [ID-1:0] axi_awmid,
output logic [PRTY-1:0] axi_awprty,
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 axi_bposted,
input logic [1:0] axi_bresp,
input logic [TAG-1:0] axi_bid,
input logic [ID-1:0] axi_bmid,
input logic [PRTY-1:0] axi_bprty,
// 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,
output logic [ID-1:0] axi_armid,
output logic [PRTY-1:0] axi_arprty,
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,
input logic [ID-1:0] axi_rmid,
input logic [PRTY-1:0] axi_rprty,
// SVCI signals
input logic svci_cmd_valid,
output logic svci_cmd_ready,
input logic [TAG-1:0] svci_cmd_tag,
input logic [ID-1:0] svci_cmd_mid,
input logic [31:0] svci_cmd_addr,
input logic [63:0] svci_cmd_wdata,
input logic [7:0] svci_cmd_wbe,
input logic [2:0] svci_cmd_length,
input logic [2:0] svci_cmd_opc,
input logic [PRTY-1:0] svci_cmd_prty,
input logic dma_slv_algn_err,
output logic svci_rsp_valid,
input logic svci_rsp_ready,
output logic [TAG-1:0] svci_rsp_tag,
output logic [ID-1:0] svci_rsp_mid,
output logic [63:0] svci_rsp_rdata,
output logic [3:0] svci_rsp_opc,
output logic [PRTY-1:0] svci_rsp_prty
);
logic cmdbuf_wr_en, cmdbuf_data_en, cmdbuf_rst, cmdbuf_data_rst;
logic cmdbuf_full;
logic cmdbuf_vld, cmdbuf_data_vld;
logic [2:0] cmdbuf_opc, cmdbuf_size;
logic [7:0] cmdbuf_wstrb;
logic [31:0] cmdbuf_addr;
logic [63:0] cmdbuf_wdata;
logic [TAG-1:0] cmdbuf_tag;
logic [ID-1:0] cmdbuf_mid;
logic [PRTY-1:0] cmdbuf_prty;
logic wrbuf_en, wrbuf_rst;
logic wrbuf_vld;
logic wrbuf_posted;
logic [TAG-1:0] wrbuf_tag;
logic [ID-1:0] wrbuf_mid;
logic [1:0] wrbuf_resp;
logic [63:0] error_address; // SVCI needs the error address back on the rdata.
logic [PRTY-1:0] wrbuf_prty;
logic [1:0] axi_bresp_in; // need to map 2 errors in to 3 errors
logic bus_clk;
// Command buffer
assign cmdbuf_wr_en = svci_cmd_valid & svci_cmd_ready;
assign cmdbuf_data_en = cmdbuf_wr_en & (svci_cmd_opc[2:1] == 2'b01);
assign cmdbuf_rst = ((axi_awvalid & axi_awready) | (axi_arvalid & axi_arready)) & ~cmdbuf_wr_en;
assign cmdbuf_data_rst = (axi_wvalid & axi_wready) & (cmdbuf_opc[2:1] == 2'b01) & ~cmdbuf_data_en;
assign cmdbuf_full = (cmdbuf_vld & ~((axi_awvalid & axi_awready) | (axi_arvalid & axi_arready))) | (cmdbuf_data_vld & ~((axi_wvalid & axi_wready) & (cmdbuf_opc[2:1] == 2'b01)));
rvdffsc #(.WIDTH(1)) cmdbuf_vldff(.din(1'b1), .dout(cmdbuf_vld), .en(cmdbuf_wr_en), .clear(cmdbuf_rst), .clk(bus_clk), .*);
rvdffsc #(.WIDTH(1)) cmdbuf_data_vldff(.din(1'b1), .dout(cmdbuf_data_vld), .en(cmdbuf_data_en), .clear(cmdbuf_data_rst), .clk(bus_clk), .*);
rvdffs #(.WIDTH(3)) cmdbuf_opcff(.din(svci_cmd_opc[2:0]), .dout(cmdbuf_opc[2:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(3)) cmdbuf_sizeff(.din(svci_cmd_length[2:0]), .dout(cmdbuf_size[2:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
rvdffe #(.WIDTH(8)) cmdbuf_wstrbff(.din(svci_cmd_wbe[7:0]), .dout(cmdbuf_wstrb[7:0]), .en(cmdbuf_wr_en & bus_clk_en), .*);
rvdffe #(.WIDTH(32)) cmdbuf_addrff(.din(svci_cmd_addr[31:0]), .dout(cmdbuf_addr[31:0]), .en(cmdbuf_wr_en & bus_clk_en), .*);
rvdffe #(.WIDTH(64)) cmdbuf_wdataff(.din(svci_cmd_wdata[63:0]), .dout(cmdbuf_wdata[63:0]), .en(cmdbuf_data_en & bus_clk_en), .*);
rvdffs #(.WIDTH(TAG)) cmdbuf_tagff(.din(svci_cmd_tag[TAG-1:0]), .dout(cmdbuf_tag[TAG-1:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(ID)) cmdbuf_midff(.din(svci_cmd_mid[ID-1:0]), .dout(cmdbuf_mid[ID-1:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(PRTY)) cmdbuf_prtyff(.din(svci_cmd_prty[PRTY-1:0]), .dout(cmdbuf_prty[PRTY-1:0]), .en(cmdbuf_wr_en), .clk(bus_clk), .*);
// AXI Write Channels
assign axi_awvalid = cmdbuf_vld & (cmdbuf_opc[2:1] == 2'b01);
assign axi_awposted = axi_awvalid & ~cmdbuf_opc[0];
assign axi_awid[TAG-1:0] = cmdbuf_tag[TAG-1:0];
assign axi_awaddr[31:0] = cmdbuf_addr[31:0];
assign axi_awsize[2:0] = cmdbuf_size[2:0];
assign axi_awprot[2:0] = 3'b0;
assign axi_awlen[7:0] = '0;
assign axi_awburst[1:0] = 2'b01;
assign axi_awmid = cmdbuf_mid[ID-1:0];
assign axi_awprty = cmdbuf_prty[PRTY-1:0];
assign axi_wvalid = cmdbuf_data_vld;
assign axi_wdata[63:0] = cmdbuf_wdata[63:0];
assign axi_wstrb[7:0] = cmdbuf_wstrb[7:0];
assign axi_wlast = 1'b1;
assign axi_bready = ~wrbuf_vld | svci_rsp_ready;
// AXI Read Channels
assign axi_arvalid = cmdbuf_vld & (cmdbuf_opc[2:0] == 3'b0);
assign axi_arid[TAG-1:0] = cmdbuf_tag[TAG-1:0];
assign axi_araddr[31:0] = cmdbuf_addr[31:0];
assign axi_arsize[2:0] = cmdbuf_size[2:0];
assign axi_arprot = 3'b0;
assign axi_arlen[7:0] = '0;
assign axi_arburst[1:0] = 2'b01;
assign axi_armid = cmdbuf_mid[ID-1:0];
assign axi_rready = ~wrbuf_vld & svci_rsp_ready;
assign axi_arprty = cmdbuf_prty[PRTY-1:0];
// SVCI_response signals
assign svci_rsp_valid = wrbuf_vld | axi_rvalid;
assign svci_rsp_tag[TAG-1:0] = wrbuf_vld ? wrbuf_tag[TAG-1:0] : axi_rid[TAG-1:0];
assign svci_rsp_mid[ID-1:0] = wrbuf_vld ? wrbuf_mid[ID-1:0] : axi_rmid[ID-1:0];
assign svci_rsp_rdata[63:0] = wrbuf_vld ? {32'b0, error_address[31:0]} : axi_rdata[63:0]; // rdata
assign svci_rsp_opc[3:2] = wrbuf_vld ? {1'b1, ~wrbuf_posted} : 2'b0;
// assign svci_rsp_opc[1:0] = wrbuf_vld ? {wrbuf_resp[1] ? (wrbuf_resp[0] ? 2'b10 : 2'b01) : 2'b0} : // AXI Slave Error -> SVCI Slave Error, AXI Decode Error -> SVCI Address Error
// {axi_rresp[1] ? (axi_rresp[0] ? 2'b10 : 2'b01) : 2'b0};
assign svci_rsp_opc[1:0] = wrbuf_vld ? wrbuf_resp[1:0] : // AXI Slave Error -> SVCI Slave Error, AXI Decode Error -> SVCI Address Error
{axi_rresp[1] ? (axi_rresp[0] ? 2'b10 : {dma_slv_algn_err, 1'b1}) : 2'b0};
assign svci_rsp_prty[PRTY-1:0] = wrbuf_vld ? wrbuf_prty[PRTY-1:0] : axi_rprty[PRTY-1:0];
assign svci_cmd_ready = ~cmdbuf_full;
// Write Response Buffer. Errors for writes need to send the Error address back on the rsp_rdata for SVCI. The address is sent back on axi_rdata bus for both reads and writes that have errors.
// assign wrbuf_en = axi_bvalid & svci_rsp_ready & (~axi_bposted | axi_bresp[1]);
assign wrbuf_en = axi_bvalid & axi_bready & (~axi_bposted | axi_bresp[1]);
assign wrbuf_rst = svci_rsp_valid & svci_rsp_ready & svci_rsp_opc[3] & ~wrbuf_en;
assign axi_bresp_in[1:0] = {axi_bresp[1] ? (axi_bresp[0] ? 2'b10 : {dma_slv_algn_err, 1'b1}) : 2'b0};
rvdffsc #(.WIDTH(1)) wrbuf_vldff (.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(bus_clk), .*);
rvdffs #(.WIDTH(32)) wrbuf_erroff (.din(axi_rdata[31:0]), .dout(error_address[31:0]), .en(wrbuf_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(1)) wrbuf_postedff(.din(axi_bposted), .dout(wrbuf_posted), .en(wrbuf_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(TAG)) wrbuf_tagff (.din(axi_bid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(ID)) wrbuf_midff (.din(axi_bmid[ID-1:0]), .dout(wrbuf_mid[ID-1:0]), .en(wrbuf_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(PRTY))wrbuf_prtyff (.din(axi_bprty[PRTY-1:0]), .dout(wrbuf_prty[PRTY-1:0]), .en(wrbuf_en), .clk(bus_clk), .*);
rvdffs #(.WIDTH(2)) wrbuf_respff (.din(axi_bresp_in[1:0]), .dout(wrbuf_resp[1:0]), .en(wrbuf_en), .clk(bus_clk), .*);
// Clock header logic
rvclkhdr bus_cgc (.en(bus_clk_en), .l1clk(bus_clk), .*);
endmodule // svci_to_axi4