diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eef60d614..84d84adef 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,7 +48,7 @@ jobs: cd Raptor_Tools/python_tools/build/share/envs/litex/bin - excluded_ips=("on_chip_memory" "axil_quadspi" "ahb2axi_bridge" "axi2axilite_bridge" "axis_width_converter" "i2c_master" "axil_ethernet") + excluded_ips=("on_chip_memory" "axil_quadspi" "ahb2axi_bridge" "axi2ahb_bridge" "axi2axilite_bridge" "axis_width_converter" "i2c_master" "axil_ethernet") simulation_list=( "axi fifo" "dsp_generator" "axi_ram" "axi2axilite_bridge" "fifo_generator" "axis_ram_switch" "axis_switch" "axis_broadcast" "axis_uart" "axis_adapter" "i2c_master" "i2c_slave") #fix ethernet ip for n in $gen_list diff --git a/rapidsilicon/README.md b/rapidsilicon/README.md index b6d46d00c..d2864729f 100644 --- a/rapidsilicon/README.md +++ b/rapidsilicon/README.md @@ -23,6 +23,7 @@ IP Catalog is an IP library for Raptor toolchain. ip/ ├── ahb2axi_bridge ├── ahb_sram + ├── axi2ahb_bridge ├── axi2axilite_bridge ├── axi_async_fifo ├── axi_cdma diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/LICENSE b/rapidsilicon/ip/axi2ahb_bridge/v1_0/LICENSE new file mode 100644 index 000000000..e6d6ee2d9 --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/LICENSE @@ -0,0 +1,50 @@ + +COPYRIGHT TEXT: +-------------- + +Copyright (c) 2022 RapidSilicon + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: The above copyright notice and this +permission notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +FILES: +rapidsilicon/ip/ahb2axi_bridge/v1_0/ahb2axi_bridge_gen.py +rapidsilicon/ip/ahb2axi_bridge/v1_0/litex_wrapper/ahb2axi_bridge_litex_wrapper.py + +--------------------------------------------------------------------------------------- + +COPYRIGHT TEXT: +-------------- + +Copyright 2019-2022 Gisselquist Technology, LLC + +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. + +FILES: +rapidsilicon/ip/ahb2axi_bridge/v1_0/src/ahb2axi4.sv +rapidsilicon/ip/ahb2axi_bridge/v1_0/src/beh_lib.sv + +--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/README.md b/rapidsilicon/ip/axi2ahb_bridge/v1_0/README.md new file mode 100644 index 000000000..8c59b9c5f --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/README.md @@ -0,0 +1,32 @@ +# AHB to AXI4 Brigde IP +## Introduction +AHB-to-AXI4 Bridge IP + +For more information, visit: https://github.com/westerndigitalcorporation/swerv_eh1/blob/master/design/lib/axi4_to_ahb.sv + +## Generator Script +This directory contains the generator script which places the RTL to `rapidsilicon/ip/ahb2axi_bridge/v1_0//src` directory and generates its wrapper in the same directory. + +## Parameters +User can configure ahb2axi_bridge CORE using following parameters: + +| Sr.No.| Parameter | Keyword | Value | +|-------|----------------------|------------------------|-----------------------| +| 1. | data_width | data_width | 32-64 | +| 2. | addr_width | addr_width | 6-32 | +| 3. | id_width | id_width | 1-32 | + + + +To generate RTL with above parameters, run the following command: +``` +python3 ahb2axi_bridge_gen.py --data_width=32 --addr_width=8 --build-name=wrapper --build +``` + +## TCL File + +This python script also generates a raptor.tcl file which will be placed in `rapidsilicon/ip/ahb2axi_bridge/v1_0//synth` directory. + + +## References +https://github.com/westerndigitalcorporation/swerv_eh1/blob/master/design/lib/axi4_to_ahb.sv diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/axi2ahb_bridge_gen.py b/rapidsilicon/ip/axi2ahb_bridge/v1_0/axi2ahb_bridge_gen.py new file mode 100755 index 000000000..50ba8af3f --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/axi2ahb_bridge_gen.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python3 +# +# This file is Copyright (c) 2022 RapidSilicon. +# +# SPDX-License-Identifier: MIT + +import os +import sys +import logging +import argparse + +from datetime import datetime + +from litex_wrapper.axi2ahb_bridge_litex_wrapper import AXI2AHB + +from migen import * + +from litex.build.generic_platform import * + +from litex.build.osfpga import OSFPGAPlatform + +from litex.soc.interconnect.axi import AXIInterface, AXILiteInterface + + +# IOs / Interface ---------------------------------------------------------------------------------- +def get_clkin_ios(): + return [ + ("s_axi_aclk", 0, Pins(1)), + ("s_axi_aresetn", 0, Pins(1))] + + +def ahb_interface(addr_width,data_width): + return [ + + ("ahb_haddr", 0, Pins(addr_width)), + ("ahb_hburst", 0, Pins(3)), + ("ahb_hmastlock", 0, Pins(1)), + ("ahb_hprot", 0, Pins(4)), + ("ahb_hsize", 0, Pins(3)), + ("ahb_htrans", 0, Pins(2)), + ("ahb_hwrite", 0, Pins(1)), + ("ahb_hwdata", 0, Pins(data_width)), + ("ahb_hsel", 0, Pins(1)), + ("ahb_hnonsec", 0, Pins(1)), + ("ahb_hrdata", 0, Pins(data_width)), + ("ahb_hready", 0, Pins(1)), + ("ahb_hresp", 0, Pins(1)), + ] + +# AHB-2-AXI4 Wrapper -------------------------------------------------------------------------------- +class AXI2AHBWrapper(Module): + def __init__(self, platform, data_width, addr_width, id_width): + + # Clocking + platform.add_extension(get_clkin_ios()) + self.clock_domains.cd_sys = ClockDomain() + self.comb += self.cd_sys.clk.eq(platform.request("s_axi_aclk")) + self.comb += self.cd_sys.rst.eq(platform.request("s_axi_aresetn")) + + + # AXI MASTER PORT + s_axi = AXIInterface( + data_width = data_width, + address_width = addr_width, + id_width = id_width + ) + + + platform.add_extension(s_axi.get_ios("s_axi")) + self.comb += s_axi.connect_to_pads(platform.request("s_axi"), mode="slave") + + # AXI_2_AHB + self.submodules.axi2ahb = axi2ahb = AXI2AHB(platform, s_axi) + + platform.add_extension(ahb_interface(addr_width,data_width)) + + self.comb += platform.request("ahb_haddr").eq(axi2ahb.ahb_haddr) + self.comb += platform.request("ahb_hburst").eq(axi2ahb.ahb_hburst) + self.comb += platform.request("ahb_hmastlock").eq(axi2ahb.ahb_hmastlock) + self.comb += platform.request("ahb_hprot").eq(axi2ahb.ahb_hprot) + self.comb += platform.request("ahb_hsize").eq(axi2ahb.ahb_hsize) + self.comb += platform.request("ahb_htrans").eq(axi2ahb.ahb_htrans) + self.comb += platform.request("ahb_hwrite").eq(axi2ahb.ahb_hwrite) + self.comb += platform.request("ahb_hwdata").eq(axi2ahb.ahb_hwdata) + + + self.comb += axi2ahb.ahb_hrdata.eq(platform.request("ahb_hrdata")) + self.comb += axi2ahb.ahb_hready.eq(platform.request("ahb_hready")) + self.comb += axi2ahb.ahb_hresp.eq(platform.request("ahb_hresp")) + + + +# Build -------------------------------------------------------------------------------------------- +def main(): + parser = argparse.ArgumentParser(description="AHB_2_AXI4 CORE") + + # Import Common Modules. + common_path = os.path.join(os.path.dirname(__file__), "..", "..", "..", "lib") + sys.path.append(common_path) + + from common import IP_Builder + + # Parameter Dependency dictionary + # Ports : Dependency + dep_dict = {} + + # IP Builder. + rs_builder = IP_Builder(device="gemini", ip_name="axi2ahb_bridge", language="System verilog") + + logging.info("===================================================") + logging.info("IP : %s", rs_builder.ip_name.upper()) + logging.info(("===================================================")) + + # Core fix value parameters. + core_fix_param_group = parser.add_argument_group(title="Core fix parameters") + core_fix_param_group.add_argument("--data_width", type=int, default=32, choices=[32, 64], help="Data Width") + + # Core range value parameters. + core_range_param_group = parser.add_argument_group(title="Core range parameters") + core_range_param_group.add_argument("--addr_width", type=int, default=32, choices=range(6, 33), help="Address Width") + core_range_param_group.add_argument("--id_width", type=int, default=1, choices=range(1, 33), help="ID Width") + + # Build Parameters. + build_group = parser.add_argument_group(title="Build parameters") + build_group.add_argument("--build", action="store_true", help="Build Core") + build_group.add_argument("--build-dir", default="./", help="Build Directory") + build_group.add_argument("--build-name", default="axi2ahb_wrapper", help="Build Folder Name, Build RTL File Name and Module Name") + + # JSON Import/Template + json_group = parser.add_argument_group(title="JSON Parameters") + json_group.add_argument("--json", help="Generate Core from JSON File") + json_group.add_argument("--json-template", action="store_true", help="Generate JSON Template") + + args = parser.parse_args() + + #IP Details generation + details = { "IP details": { + 'Name' : 'axi2ahb bridge', + 'Version' : 'V1_0', + 'Interface' : 'AHB and AXI', + 'Description' : 'This bridge acts as a translator and mediator, facilitating seamless data transfer and control signal synchronization between devices or subsystems designed with AHB-based interfaces and those using AXI4-based interfaces.'}} + + # Import JSON (Optional) ----------------------------------------------------------------------- + if args.json: + args = rs_builder.import_args_from_json(parser=parser, json_filename=args.json) + rs_builder.import_ip_details_json(build_dir=args.build_dir ,details=details , build_name = args.build_name, version = "v1_0") + + #IP Summary generation + file_path = os.path.dirname(os.path.realpath(__file__)) + rs_builder.copy_images(file_path) + + summary = { + "Data width programmed": args.data_width, + "Address width programmed": args.addr_width, + "AXI ID width programmed": args.id_width, + } + + # Export JSON Template (Optional) -------------------------------------------------------------- + if args.json_template: + rs_builder.export_json_template(parser=parser, dep_dict=dep_dict, summary=summary) + + + + # Create Wrapper ------------------------------------------------------------------------------- + platform = OSFPGAPlatform(io=[], toolchain="raptor", device="gemini") + module = AXI2AHBWrapper(platform, + data_width = args.data_width, + addr_width = args.addr_width, + id_width = args.id_width + ) + + # Build Project -------------------------------------------------------------------------------- + if args.build: + rs_builder.prepare( + build_dir = args.build_dir, + build_name = args.build_name, + version = "v1_0" + ) + rs_builder.copy_files(gen_path=os.path.dirname(__file__)) + rs_builder.generate_tcl(version = "v1_0") + rs_builder.generate_wrapper( + platform = platform, + module = module, + version = "v1_0" + ) + + # IP_ID Parameter + now = datetime.now() + my_year = now.year - 2022 + year = (bin(my_year)[2:]).zfill(7) # 7-bits # Removing '0b' prefix = [2:] + month = (bin(now.month)[2:]).zfill(4) # 4-bits + day = (bin(now.day)[2:]).zfill(5) # 5-bits + mod_hour = now.hour % 12 # 12 hours Format + hour = (bin(mod_hour)[2:]).zfill(4) # 4-bits + minute = (bin(now.minute)[2:]).zfill(6) # 6-bits + second = (bin(now.second)[2:]).zfill(6) # 6-bits + + # Concatenation for IP_ID Parameter + ip_id = ("{}{}{}{}{}{}").format(year, day, month, hour, minute, second) + ip_id = ("32'h{}").format(hex(int(ip_id,2))[2:]) + + # IP_VERSION parameter + # Base _ Major _ Minor + ip_version = "00000000_00000000_0000000000000001" + ip_version = ("32'h{}").format(hex(int(ip_version, 2))[2:]) + + wrapper = os.path.join(args.build_dir, "rapidsilicon", "ip", "axi2ahb_bridge", "v1_0", args.build_name, "src",args.build_name + "_" + "v1_0" + ".v") + new_lines = [] + with open (wrapper, "r") as file: + lines = file.readlines() + for i, line in enumerate(lines): + if ("module {}".format(args.build_name)) in line: + new_lines.append("module {} #(\n\tparameter IP_TYPE \t\t= \"A2HB\",\n\tparameter IP_VERSION \t= {}, \n\tparameter IP_ID \t\t= {}\n)\n(".format(args.build_name, ip_version, ip_id)) + else: + new_lines.append(line) + + with open(os.path.join(wrapper), "w") as file: + file.writelines(new_lines) + +if __name__ == "__main__": + main() diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/docs/AXI2AHB.drawio.png b/rapidsilicon/ip/axi2ahb_bridge/v1_0/docs/AXI2AHB.drawio.png new file mode 100644 index 000000000..d149128e0 Binary files /dev/null and b/rapidsilicon/ip/axi2ahb_bridge/v1_0/docs/AXI2AHB.drawio.png differ diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/docs/AXI2AHB.pdf b/rapidsilicon/ip/axi2ahb_bridge/v1_0/docs/AXI2AHB.pdf new file mode 100644 index 000000000..8e7b6348b Binary files /dev/null and b/rapidsilicon/ip/axi2ahb_bridge/v1_0/docs/AXI2AHB.pdf differ diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/litex_wrapper/__pycache__/axi2ahb_bridge_litex_wrapper.cpython-38.pyc b/rapidsilicon/ip/axi2ahb_bridge/v1_0/litex_wrapper/__pycache__/axi2ahb_bridge_litex_wrapper.cpython-38.pyc new file mode 100644 index 000000000..6c17e5862 Binary files /dev/null and b/rapidsilicon/ip/axi2ahb_bridge/v1_0/litex_wrapper/__pycache__/axi2ahb_bridge_litex_wrapper.cpython-38.pyc differ diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/litex_wrapper/axi2ahb_bridge_litex_wrapper.py b/rapidsilicon/ip/axi2ahb_bridge/v1_0/litex_wrapper/axi2ahb_bridge_litex_wrapper.py new file mode 100644 index 000000000..8451dc747 --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/litex_wrapper/axi2ahb_bridge_litex_wrapper.py @@ -0,0 +1,156 @@ +# +# This file is part of RapidSilicon's IP_Catalog. +# +# This file is Copyright (c) 2022 RapidSilicon. +# +# SPDX-License-Identifier: MIT +# +# LiteX wrapper around western digital's axi2ahb.v + +import os +import datetime +import logging + +from migen import * + +from litex.soc.interconnect.axi import * + +# logging.basicConfig(level=logging.INFO) +logging.basicConfig(filename="IP.log",filemode="w", level=logging.INFO, format='%(levelname)s: %(message)s\n') + +timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') +logging.info(f'Log started at {timestamp}') + +# AHB_2_AXI4_BRIDGE --------------------------------------------------------------------------------------- +class AXI2AHB(Module): + def __init__(self, platform, m_axi): + + # Get Parameters. + # --------------------- + self.logger = logging.getLogger("AHB_2_AXI4") + + self.logger.propagate = True + + # Clock Domain. + # self.logger.info(f"CLOCK_DOMAIN : {s_ahb.clock_domain}") + self.logger.info(f"=================== PARAMETERS ====================") + # Address width. + address_width = len(m_axi.aw.addr) + self.logger.info(f"C_AXI_ADDR_WIDTH : {address_width}") + + # Data width. + data_width = len(m_axi.w.data) + self.logger.info(f"C_AXI_DATA_WIDTH : {data_width}") + + # ID width. + id_width = len(m_axi.aw.id) + self.logger.info(f"C_AXI_ID_WIDTH : {id_width}") + + self.logger.info(f"===================================================") + + self.ahb_haddr = Signal(address_width) + self.ahb_hburst = Signal(3) + self.ahb_hmastlock = Signal(1) + self.ahb_hprot = Signal(4) + self.ahb_hsize = Signal(3) + self.ahb_htrans = Signal(2) + self.ahb_hwrite = Signal(1) + self.ahb_hwdata = Signal(data_width) + self.ahb_hrdata = Signal(data_width) + self.ahb_hready = Signal(1) + self.ahb_hresp = Signal(1) + + # Module instance. + # ---------------- + self.specials += Instance("ahb_to_axi4", + # Parameters. + # ----------- + # IP Parameters + p_IP_TYPE = Instance.PreformattedParam("IP_TYPE"), + p_IP_ID = Instance.PreformattedParam("IP_ID"), + p_IP_VERSION = Instance.PreformattedParam("IP_VERSION"), + # Global AXI + p_data_width = Instance.PreformattedParam(data_width), + p_addr_width = Instance.PreformattedParam(address_width), + p_id_width = Instance.PreformattedParam(id_width), + + # Clk / Rst. + i_clk = ClockSignal(), + i_rst_l = ResetSignal(), + + # AHB Slave Interface. + # -------------------- + + o_ahb_haddr = self.ahb_haddr, + o_ahb_hburst = self.ahb_hburst, + o_ahb_hmastlock = self.ahb_hmastlock, + o_ahb_hprot = self.ahb_hprot, + o_ahb_hsize = self.ahb_hsize, + o_ahb_htrans = self.ahb_htrans, + o_ahb_hwrite = self.ahb_hwrite, + o_ahb_hwdata = self.ahb_hwdata, + i_ahb_hrdata = self.ahb_hrdata, + i_ahb_hready = self.ahb_hready, + i_ahb_hresp = self.ahb_hresp, + + + + # AXI master Interface. + # -------------------- + # AW. + i_axi_awid = m_axi.aw.id, + i_axi_awaddr = m_axi.aw.addr, + o_axi_awlen = m_axi.aw.len, + i_axi_awsize = m_axi.aw.size, + o_axi_awburst = m_axi.aw.burst, + # o_S_AXI_AWLOCK = m_axi.aw.lock, + # o_S_AXI_AWCACHE = m_axi.aw.cache, + i_axi_awprot = m_axi.aw.prot, + # o_S_AXI_AWQOS = m_axi.aw.qos, + i_axi_awvalid = m_axi.aw.valid, + o_axi_awready = m_axi.aw.ready, + + # W. + i_axi_wdata = m_axi.w.data, + i_axi_wstrb = m_axi.w.strb, + i_axi_wlast = m_axi.w.last, + i_axi_wvalid = m_axi.w.valid, + o_axi_wready = m_axi.w.ready, + + # B. + o_axi_bid = m_axi.b.id, + o_axi_bresp = m_axi.b.resp, + o_axi_bvalid = m_axi.b.valid, + i_axi_bready = m_axi.b.ready, + + # AR. + i_axi_arid = m_axi.ar.id, + i_axi_araddr = m_axi.ar.addr, + i_axi_arlen = m_axi.ar.len, + i_axi_arsize = m_axi.ar.size, + i_axi_arburst = m_axi.ar.burst, + # o_S_AXI_ARLOCK = m_axi.ar.lock, + # o_S_AXI_ARCACHE = m_axi.ar.cache, + i_axi_arprot = m_axi.ar.prot, + # o_S_AXI_ARQOS = m_axi.ar.qos, + i_axi_arvalid = m_axi.ar.valid, + o_axi_arready = m_axi.ar.ready, + + # R. + o_axi_rid = m_axi.r.id, + o_axi_rdata = m_axi.r.data, + o_axi_rresp = m_axi.r.resp, + # o_S_AXI_RLAST = m_axi.r.last, + o_axi_rvalid = m_axi.r.valid, + i_axi_rready = m_axi.r.ready, + + ) + + # Add Sources. + # ------------ + self.add_sources(platform) + + @staticmethod + def add_sources(platform): + rtl_dir = os.path.join(os.path.dirname(__file__), "../src") + platform.add_source(os.path.join(rtl_dir, "axi2ahb.sv")) diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/sdc/README.md b/rapidsilicon/ip/axi2ahb_bridge/v1_0/sdc/README.md new file mode 100644 index 000000000..00c6bb77c --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/sdc/README.md @@ -0,0 +1 @@ +Directory for Constraints \ No newline at end of file diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/sim/README.md b/rapidsilicon/ip/axi2ahb_bridge/v1_0/sim/README.md new file mode 100644 index 000000000..0051b0183 --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/sim/README.md @@ -0,0 +1,2 @@ +# Simulation +This is a directory for simulations. \ No newline at end of file diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/src/axi2ahb.sv b/rapidsilicon/ip/axi2ahb_bridge/v1_0/src/axi2ahb.sv new file mode 100644 index 000000000..36d1f188a --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/src/axi2ahb.sv @@ -0,0 +1,613 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2019 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 #(parameter TAG = 1, Address_Width =32) ( + +input clk, +input rst_l, +input scan_mode, +input bus_clk_en, +input clk_override, + +// 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 [1:0] axi_awburst, +input logic [7:0] axi_awlen, +input logic [3:0] axi_size, + +input logic axi_wvalid, +output logic axi_wready, +input logic [31:0] axi_wdata, +input logic [3: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, +input logic [1:0] axi_arburst, +input logic [7:0] axi_arlen, + +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 [31:0] ahb_hwdata, // ahb bus write data + +input logic [31: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 [3:0] {IDLE=4'b000, CMD_RD=4'b001, CMD_WR=4'b010, DATA_RD=4'b011, DATA_WR=4'b100, DONE=4'b101, STREAM_RD=4'b110, STREAM_ERR_RD=4'b111, WR_BURST=4'b1000, RD_BURST= 4'b1001} 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 [Address_Width-1:0] addr_offset; +logic [Address_Width-1:0] ahb_address; +logic address_valid; + +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 bus_write_clk_en; +logic bus_clk, bus_write_clk; + +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; + +// 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 [3: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, last_ahb_addr; + +// Clocks +logic buf_clken, slvbuf_clken; +logic ahbm_addr_clken; +logic ahbm_data_clken; + +logic buf_clk, slvbuf_clk; +logic ahbm_clk; +logic ahbm_addr_clk; +logic ahbm_data_clk; + +// 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_size + +// Function to get the next byte pointer +function automatic logic [2:0] get_nxtbyte_ptr (logic [2:0] current_byte_ptr, logic [3: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'd4) : current_byte_ptr[2:0]; + for (int j=0; j<4; 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 + + +function automatic logic [2:0] get_haddr_inc(logic hsize); + logic [2:0] haddr_inc; + + case (hsize) + 1: haddr_inc = 1; + 2: haddr_inc = 2; + default: haddr_inc = 0; + endcase + + get_haddr_inc = haddr_inc; +endfunction + + + + +// 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; + +assign axi_awready = ~(wrbuf_vld & ~wrbuf_cmd_sent) & master_ready; +// assign axi_wready = ~(wrbuf_data_vld & ~wrbuf_cmd_sent) & master_ready; +assign axi_wready = (axi_awburst !=0) ? ~axi_wlast : ~(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_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; + +// Clock header logic +assign bus_write_clk_en = bus_clk_en & ((axi_awvalid & axi_awready) | (axi_wvalid & axi_wready)); + +rvclkhdr bus_cgc (.en(bus_clk_en), .l1clk(bus_clk), .*); +rvclkhdr bus_write_cgc (.en(bus_write_clk_en), .l1clk(bus_write_clk), .*); + + +// 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[3: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 = axi_arburst ? RD_BURST :(master_valid & (master_opc[2:0] == 3'b000))? STREAM_RD : DATA_RD; +// 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 + master_ready = 1'b1; + buf_nxtstate = axi_awburst ? WR_BURST : 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; + ahb_address = axi_awaddr; + 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; + ahb_htrans[1:0] = 2'b10; + end + WR_BURST: begin +// bypass_en = 1'b1; + buf_nxtstate = axi_wlast ? DONE : WR_BURST; + buf_write_in = ~axi_wlast; + 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; //get_haddr_inc(ahb_hsize) + 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) : 0;//buf_cmd_byte_ptrQ; + + ahb_address = address_valid ? (last_ahb_addr + 4) : ahb_haddr; + master_ready = 1'b1; + buf_cmd_byte_ptr = get_haddr_inc(ahb_hsize); //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; + ahb_htrans[1:0] = 2'b11; + end + RD_BURST: 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 + 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; + ahb_htrans[1:0] = 2'b11; + 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[3: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; + buf_state_en = 1'b1; + slvbuf_error_en = 1'b1; + slave_valid_pre = 1'b1; + end + endcase +end + + + +always_comb begin + + case (axi_awburst) + 2'b00: begin + ahb_hburst = 3'b0; + end + 2'b01: begin + ahb_hburst = 3'b111; + case (axi_awlen) + 4'h4: begin + ahb_hburst = 3'b011; + end + 4'h8: begin + ahb_hburst = 3'b101; + end + 4'hf: begin + ahb_hburst = 3'b111; + end + default: begin + ahb_hburst = 3'b1; + end + endcase + + end + 2'b10: begin + case (axi_awlen) + 4'd4: begin + ahb_hburst = 3'b010; + end + 4'd8: begin + ahb_hburst = 3'b100; + end + 4'd16: begin + ahb_hburst = 3'b110; + end + default: begin + ahb_hburst = 3'b0; + end + endcase end + 2'b11: begin + ahb_hburst = 3'b0; + end + default: begin + ahb_hburst = 3'b0; + end + endcase +end + + +always @ (posedge clk or posedge rst_l) begin + if (!rst_l) begin + addr_offset <= Address_Width-1'h0; + address_valid <= 1'b0; + end + + + else begin + + if(axi_awburst== 2'b01 && axi_wlast == 1'b0) begin + address_valid<=1'b1; + end + else begin + address_valid<=1'b0; + end + end + end + + + + +// assign ahb_address = address_valid ? (axi_awaddr + addr_offset) : ahb_address; +//assign ahb_address = address_valid ? (axi_awaddr + 4) : ahb_haddr; +//assign ahb_address = address_valid ? ahb_haddr : (axi_awaddr + 4) ; + + + +assign buf_rst = 1'b0; +assign cmd_done_rst = slave_valid_pre; +assign buf_addr_in[2:0] = (buf_aligned_in & (master_opc[2:1] == 2'b01)) ? get_write_addr(wrbuf_byteen[7:0]) : master_addr[2:0]; +assign buf_addr_in[31:3] = master_addr[31:3]; +assign buf_tag_in[TAG-1:0] = master_tag[TAG-1:0]; +assign buf_byteen_in[3:0] = wrbuf_byteen[3: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(wrbuf_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) & + ((wrbuf_byteen[7:0] == 8'h3) | (wrbuf_byteen[7:0] == 8'hc) | (wrbuf_byteen[7:0] == 8'h30) | (wrbuf_byteen[7:0] == 8'hc0) | + (wrbuf_byteen[7:0] == 8'hf) | (wrbuf_byteen[7:0] == 8'hf0) | (wrbuf_byteen[7:0] == 8'hff))); + +// Generate the ahb signals +assign ahb_haddr = ahb_address; +// assign ahb_haddr[31:0] = bypass_en ? {master_addr[31:3],buf_cmd_byte_ptr[2:0]} : {buf_addr[31:3],buf_cmd_byte_ptr[2:0]}; +// assign ahb_hsize[2:0] = ((buf_state == CMD_RD) | (buf_state == STREAM_RD) | (buf_state == STREAM_ERR_RD) | rd_bypass_idle) ? 3'b011 : +// 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_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) : address_valid ? 1'b1 : buf_write; +assign ahb_hwdata[63:0] = buf_data[63:0]; + +assign slave_valid = slave_valid_pre; +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 #(.WIDTH(1)) wrbuf_vldff (.din(1'b1), .dout(wrbuf_vld), .en(wrbuf_en), .clear(wrbuf_rst), .clk(bus_clk), .*); +rvdffsc #(.WIDTH(1)) wrbuf_data_vldff(.din(1'b1), .dout(wrbuf_data_vld), .en(wrbuf_data_en), .clear(wrbuf_rst), .clk(bus_clk), .*); +rvdffs #(.WIDTH(TAG)) wrbuf_tagff (.din(axi_awid[TAG-1:0]), .dout(wrbuf_tag[TAG-1:0]), .en(wrbuf_en), .clk(bus_clk), .*); +rvdffs #(.WIDTH(3)) wrbuf_sizeff (.din(axi_awsize[2:0]), .dout(wrbuf_size[2:0]), .en(wrbuf_en), .clk(bus_clk), .*); +rvdffe #(.WIDTH(32)) wrbuf_addrff (.din(axi_awaddr[31:0]), .dout(wrbuf_addr[31:0]), .en(wrbuf_en), .clk(bus_clk), .*); +rvdffe #(.WIDTH(64)) wrbuf_dataff (.din(axi_wdata[63:0]), .dout(wrbuf_data[63:0]), .en(wrbuf_data_en), .clk(bus_clk), .*); +rvdffs #(.WIDTH(4)) wrbuf_byteenff (.din(axi_wstrb[3:0]), .dout(wrbuf_byteen[3:0]), .en(wrbuf_data_en), .clk(bus_clk), .*); + +rvdffs #(.WIDTH(32)) last_bus_addrff (.din(ahb_haddr[31:0]), .dout(last_bus_addr[31:0]), .en(last_addr_en), .clk(ahbm_clk), .*); +rvdffs #(.WIDTH(32)) last_bus_addressff (.din(ahb_address[31:0]), .dout(last_ahb_addr[31:0]), .en(last_addr_en), .clk(ahbm_clk), .*); + +rvdffsc #(.WIDTH($bits(state_t))) buf_state_ff (.din(buf_nxtstate), .dout({buf_state}), .en(buf_state_en), .clear(buf_rst), .clk(ahbm_clk), .*); +rvdffs #(.WIDTH(1)) buf_writeff (.din(buf_write_in), .dout(buf_write), .en(buf_wr_en), .clk(buf_clk), .*); +rvdffs #(.WIDTH(TAG)) buf_tagff (.din(buf_tag_in[TAG-1:0]), .dout(buf_tag[TAG-1:0]), .en(buf_wr_en), .clk(buf_clk), .*); +rvdffe #(.WIDTH(32)) buf_addrff (.din(buf_addr_in[31:0]), .dout(buf_addr[31:0]), .en(buf_wr_en & bus_clk_en), .*); +rvdffs #(.WIDTH(2)) buf_sizeff (.din(buf_size_in[1:0]), .dout(buf_size[1:0]), .en(buf_wr_en), .clk(buf_clk), .*); +rvdffs #(.WIDTH(1)) buf_alignedff (.din(buf_aligned_in), .dout(buf_aligned), .en(buf_wr_en), .clk(buf_clk), .*); +rvdffs #(.WIDTH(4)) buf_byteenff (.din(buf_byteen_in[3:0]), .dout(buf_byteen[3:0]), .en(buf_wr_en), .clk(buf_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), .*); + + +rvdffs #(.WIDTH(1)) slvbuf_writeff (.din(buf_write), .dout(slvbuf_write), .en(slvbuf_wr_en), .clk(buf_clk), .*); +rvdffs #(.WIDTH(TAG)) slvbuf_tagff (.din(buf_tag[TAG-1:0]), .dout(slvbuf_tag[TAG-1:0]), .en(slvbuf_wr_en), .clk(buf_clk), .*); +rvdffs #(.WIDTH(1)) slvbuf_errorff (.din(slvbuf_error_in), .dout(slvbuf_error), .en(slvbuf_error_en), .clk(ahbm_clk), .*); + +rvdffsc #(.WIDTH(1)) buf_cmd_doneff (.din(1'b1), .en(cmd_done), .dout(cmd_doneQ), .clear(cmd_done_rst), .clk(ahbm_clk), .*); +rvdffs #(.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(ahbm_clk), .*); + +rvdff #(.WIDTH(1)) hready_ff (.din(ahb_hready), .dout(ahb_hready_q), .clk(ahbm_clk), .*); +rvdff #(.WIDTH(2)) htrans_ff (.din(ahb_htrans[1:0]), .dout(ahb_htrans_q[1:0]), .clk(ahbm_clk), .*); +rvdff #(.WIDTH(1)) hwrite_ff (.din(ahb_hwrite), .dout(ahb_hwrite_q), .clk(ahbm_addr_clk), .*); +rvdff #(.WIDTH(1)) hresp_ff (.din(ahb_hresp), .dout(ahb_hresp_q), .clk(ahbm_clk), .*); +rvdff #(.WIDTH(64)) hrdata_ff (.din(ahb_hrdata[63:0]), .dout(ahb_hrdata_q[63:0]), .clk(ahbm_data_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_addr_clken = bus_clk_en & ((ahb_hready & ahb_htrans[1]) | clk_override); +assign ahbm_data_clken = bus_clk_en & ((buf_state != IDLE) | clk_override); + +rvclkhdr buf_cgc (.en(buf_clken), .l1clk(buf_clk), .*); +rvclkhdr ahbm_cgc (.en(bus_clk_en), .l1clk(ahbm_clk), .*); +rvclkhdr ahbm_addr_cgc (.en(ahbm_addr_clken), .l1clk(ahbm_addr_clk), .*); +rvclkhdr ahbm_data_cgc (.en(ahbm_data_clken), .l1clk(ahbm_data_clk), .*); + +`ifdef ASSERT_ON +property ahb_trxn_aligned; + @(posedge ahbm_clk) ahb_htrans[1] |-> ((ahb_hsize[2:0] == 3'h0) | + ((ahb_hsize[2:0] == 3'h1) & (ahb_haddr[0] == 1'b0)) | + ((ahb_hsize[2:0] == 3'h2) & (ahb_haddr[1:0] == 2'b0)) | + ((ahb_hsize[2:0] == 3'h3) & (ahb_haddr[2:0] == 3'b0))); +endproperty +assert_ahb_trxn_aligned: assert property (ahb_trxn_aligned) else + $display("Assertion ahb_trxn_aligned failed: ahb_htrans=2'h%h, ahb_hsize=3'h%h, ahb_haddr=32'h%h",ahb_htrans[1:0], ahb_hsize[2:0], ahb_haddr[31:0]); + +property ahb_error_protocol; + @(posedge ahbm_clk) (ahb_hready & ahb_hresp) |-> (~$past(ahb_hready) & $past(ahb_hresp)); +endproperty +assert_ahb_error_protocol: assert property (ahb_error_protocol) else + $display("Bus Error with hReady isn't preceded with Bus Error without hready"); +`endif + +endmodule // axi4_to_ahb diff --git a/rapidsilicon/ip/axi2ahb_bridge/v1_0/src/beh_lib.sv b/rapidsilicon/ip/axi2ahb_bridge/v1_0/src/beh_lib.sv new file mode 100644 index 000000000..6b06d8e75 --- /dev/null +++ b/rapidsilicon/ip/axi2ahb_bridge/v1_0/src/beh_lib.sv @@ -0,0 +1,241 @@ + +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2019 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. + +// all flops call the rvdff flop +`timescale 1ns / 1ps + + +// +`define RV_FPGA_OPTIMIZE 1 +`define RV_DCCM_SIZE 64 + + +module rvdffsc #( parameter WIDTH=1 ) + ( + input logic [WIDTH-1:0] din, + input logic en, + input logic clear, + input logic clk, + input logic rst_l, + output logic [WIDTH-1:0] dout + ); + + logic [WIDTH-1:0] din_new; + assign din_new = {WIDTH{~clear}} & (en ? din[WIDTH-1:0] : dout[WIDTH-1:0]); + rvdff #(WIDTH) dffsc (.din(din_new[WIDTH-1:0]), .*); + +endmodule + +module rvdff #( parameter WIDTH=1 ) + ( + input logic [WIDTH-1:0] din, + input logic clk, + // input logic en, + input logic rst_l, + + output logic [WIDTH-1:0] dout + ); + +`ifdef CLOCKGATE + always @(posedge tb_top.clk) begin + #0 $strobe("CG: %0t %m din %x dout %x clk %b width %d",$time,din,dout,clk,WIDTH); + end +`endif + + always_ff @(posedge clk or posedge rst_l) begin //changed by me from active low to high negedge + if (rst_l == 1) + dout[WIDTH-1:0] <= 32'd0; + else if(rst_l == 0) + dout[WIDTH-1:0] <= din[WIDTH-1:0]; + else + dout[WIDTH-1:0] <= dout[WIDTH-1:0]; + end + + +endmodule + +// rvdff with 2:1 input mux to flop din iff sel==1 +module rvdffs #( parameter WIDTH=1 ) + ( + input logic [WIDTH-1:0] din, + input logic en, + input logic clk, + input logic rst_l, + output logic [WIDTH-1:0] dout + ); + + //rvdff #(WIDTH) dffs (.din((en) ? din[WIDTH-1:0] : dout[WIDTH-1:0]), .*); + rvdff #(WIDTH) dffs (.din(din), .*); + +endmodule + + + +// versions with clock enables .clken to assist in RV_FPGA_OPTIMIZE +module rvdff_fpga #( parameter WIDTH=1 ) + ( + input logic [WIDTH-1:0] din, + input logic clk, + input logic clken, + input logic rawclk, + input logic rst_l, + input logic scan_mode, + + output logic [WIDTH-1:0] dout + ); + + rvdffs #(WIDTH) dffs (.clk(rawclk), .en(clken), .*); + + + +endmodule + +// rvdff with 2:1 input mux to flop din iff sel==1 +module rvdffs_fpga #( parameter WIDTH=1 ) + ( + input logic [WIDTH-1:0] din, + input logic en, + input logic clk, + input logic clken, + input logic rawclk, + input logic rst_l, + input logic scan_mode, + output logic [WIDTH-1:0] dout + ); + + rvdffs #(WIDTH) dffs (.clk(rawclk), .en(clken), .*); //en coment by me + +endmodule + +// rvdff with en and clear +module rvdffsc_fpga #( parameter WIDTH=1 ) + ( + input logic [WIDTH-1:0] din, + input logic en, + input logic clear, + input logic clk, + input logic clken, + input logic rawclk, + input logic rst_l, + input logic scan_mode, + output logic [WIDTH-1:0] dout + ); + + + rvdffsc #(WIDTH) dffsc (.*); + +endmodule + +module TEC_RV_ICG + ( + input logic TE, E, CP, + output Q + ); + + logic en_ff; + logic enable; + + assign enable = E | TE; + +`ifdef VERILATOR + always @(negedge CP) begin + en_ff <= enable; + end +`else + always @(CP, enable) begin + if(!CP) + en_ff = enable; + end +`endif + assign Q = CP & en_ff; + +endmodule + + + +module rvclkhdr + ( + input logic en, + input logic clk, + input logic scan_mode, + output logic l1clk + ); + + logic TE; + assign TE = scan_mode; + + TEC_RV_ICG clkhdr ( .*, .E(en), .CP(clk), .Q(l1clk)); //by me TEC_RV_ICG to abc + +endmodule // rvclkhdr + + +module rvdffe #( parameter WIDTH=1, parameter OVERRIDE=0 ) + ( + input logic [WIDTH-1:0] din, + input logic en, + input logic clk, + input logic rst_l, + input logic scan_mode, + output logic [WIDTH-1:0] dout + ); + + logic l1clk; + + +`ifndef PHYSICAL + if (WIDTH >= 8 || OVERRIDE==1) begin: genblock +`endif + +`ifdef RV_FPGA_OPTIMIZE + rvdffs #(WIDTH) dff ( .* ); +`else + rvclkhdr clkhdr ( .* ); + rvdff #(WIDTH) dff (.*, .clk(l1clk)); +`endif + +`ifndef PHYSICAL + end + else + $error("%m: rvdffe width must be >= 8"); +`endif + + +endmodule // rvdffe + +// Check if the S_ADDR <= addr < E_ADDR +module rvrangecheck #(CCM_SADR = 32'h0, + CCM_SIZE = 128) ( + input logic [31:0] addr, // Address to be checked for range + output logic in_range, // S_ADDR <= start_addr < E_ADDR + output logic in_region +); + + localparam REGION_BITS = 4; + localparam MASK_BITS = 10 + $clog2(CCM_SIZE); + + logic [31:0] start_addr; + logic [3:0] region; + + assign start_addr[31:0] = CCM_SADR; + assign region[REGION_BITS-1:0] = start_addr[31:(32-REGION_BITS)]; + + assign in_region = (addr[31:(32-REGION_BITS)] == region[REGION_BITS-1:0]); + if (CCM_SIZE == 48) + assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]) & ~(&addr[MASK_BITS-1 : MASK_BITS-2]); + else + assign in_range = (addr[31:MASK_BITS] == start_addr[31:MASK_BITS]); + +endmodule // rvrangechecker \ No newline at end of file diff --git a/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/axi2axilite.v b/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/axi2axilite.v index 762ecce32..f8e4b09ac 100644 --- a/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/axi2axilite.v +++ b/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/axi2axilite.v @@ -175,7 +175,7 @@ module axi2axilite #( // // Write registers reg m_axi_awvalid, s_axi_wready; - reg [C_AXI_ADDR_WIDTH-1:0] axi_awaddr; + reg [C_AXI_ADDR_WIDTH-1:0] axi_awaddr =0; reg [7:0] axi_awlen, axi_blen; reg [1:0] axi_awburst; reg [2:0] axi_awsize; @@ -186,7 +186,7 @@ module axi2axilite #( wire [7:0] wfifo_bcount; wire [IW-1:0] wfifo_bid; reg [8:0] bcounts; - reg [C_AXI_ID_WIDTH-1:0] axi_bid, bid; + reg [C_AXI_ID_WIDTH-1:0] axi_bid =0, bid =0; reg [1:0] axi_bresp; reg s_axi_bvalid; wire read_from_wrfifo; @@ -198,16 +198,16 @@ module axi2axilite #( wire rfifo_empty; wire [7:0] rfifo_rcount; reg s_axi_rvalid; - reg [1:0] s_axi_rresp; + reg [1:0] s_axi_rresp =0; reg [8:0] rcounts; - reg [C_AXI_ADDR_WIDTH-1:0] axi_araddr; + reg [C_AXI_ADDR_WIDTH-1:0] axi_araddr =0; reg [7:0] axi_arlen, axi_rlen; reg [1:0] axi_arburst; reg [2:0] axi_arsize; wire [C_AXI_ADDR_WIDTH-1:0] next_read_addr; reg [C_AXI_ID_WIDTH-1:0] s_axi_rid; wire [C_AXI_ID_WIDTH-1:0] rfifo_rid; - reg [C_AXI_DATA_WIDTH-1:0] s_axi_rdata; + reg [C_AXI_DATA_WIDTH-1:0] s_axi_rdata =0; reg s_axi_rlast; reg [IW-1:0] rid; wire read_from_rdfifo; @@ -773,13 +773,13 @@ module axi2axilite #( if (!S_AXI_RVALID || S_AXI_RREADY) begin // if (rcounts == 1) s_axi_rlast <= 1; else - if (read_from_rdfifo) - s_axi_rlast <= (rfifo_rcount == 0); - else - s_axi_rlast <= 0; - - if (rcounts == 1) - s_axi_rlast <= 1; + if (rcounts == 1) begin + s_axi_rlast <= 1; // Highest priority + end else if (read_from_rdfifo) begin + s_axi_rlast <= (rfifo_rcount == 0); // Based on rfifo_rcount + end else begin + s_axi_rlast <= 0; // Default case + end end // }}} diff --git a/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/sfifo.v b/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/sfifo.v index 786740949..2f02ae797 100644 --- a/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/sfifo.v +++ b/rapidsilicon/ip/axi2axilite_bridge/v1_0/src/sfifo.v @@ -66,6 +66,7 @@ module sfifo #( // {{{ localparam FLEN=(1<> ADDR_LSB)]; - else + if (CONTROL_REG[0] == 1) begin + if (S_AXI_ARADDR > NO_OF_OUT_PROBE_REGS-1) + AXI_DAT_IN <= 0; + else + AXI_DAT_IN <= output_probe_reg[((S_AXI_ARADDR - 32'h00000010) >> ADDR_LSB)]; + end + + else begin + if (S_AXI_ARADDR > NO_OF_OUT_PROBE_REGS-1) + AXI_DAT_IN <= 0; + else AXI_DAT_IN <= input_probe_reg_o[((S_AXI_ARADDR - 32'h00000010) >> ADDR_LSB)]; end + end endcase end @@ -266,6 +277,12 @@ begin if (!S_AXI_ARESETN) begin CONTROL_REG <= 0; + for(j = 0 ; j <= NO_OF_IN_PROBE_REGS; j = j+1) begin + input_probe_reg_o[j] = 0; + input_probe_reg_i[j] =0; + end + for(i = 0 ; i <= NO_OF_OUT_PROBE_REGS; i = i+1) + output_probe_reg[i] = 0; end else begin if (AXI_WREN) diff --git a/rapidsilicon/ip/axil_eio/v1_0/src/ff_sync.v b/rapidsilicon/ip/axil_eio/v1_0/src/ff_sync_eio.v similarity index 100% rename from rapidsilicon/ip/axil_eio/v1_0/src/ff_sync.v rename to rapidsilicon/ip/axil_eio/v1_0/src/ff_sync_eio.v diff --git a/rapidsilicon/ip/ddr_sdram/v1_0/src/ddr_sdram_ctrl.v b/rapidsilicon/ip/ddr_sdram/v1_0/src/ddr_sdram_ctrl.v index 1adb0fca8..357ce701e 100644 --- a/rapidsilicon/ip/ddr_sdram/v1_0/src/ddr_sdram_ctrl.v +++ b/rapidsilicon/ip/ddr_sdram/v1_0/src/ddr_sdram_ctrl.v @@ -58,17 +58,19 @@ module ddr_sdram_ctrl #( output reg [ ROW_BITS-1:0] ddr_a, output wire [((1<= data_width_read): self.comb += [ - If(self.counter == 0, - self.empty.eq(1) - ).Elif(self.pessimistic_empty == 2, - self.empty.eq(0) - ).Else( + If (ResetSignal("sys"), + self.empty.eq(1) + ).Elif(self.counter == 0, + self.empty.eq(1) + ).Elif(self.pessimistic_empty == 2, + self.empty.eq(0) + ).Else( self.empty.eq(1) ) + ] # Checking for Programmable Empty if (empty_threshold): @@ -3385,7 +3388,9 @@ def __init__(self, data_width_write, data_width_read, synchronous, full_threshol ] else: self.comb += [ - If(self.counter <= clocks_for_output, + If (ResetSignal("sys"), + self.empty.eq(1) + ).Elif(self.counter <= clocks_for_output, self.empty.eq(1) ).Elif(self.pessimistic_empty == 2, self.empty.eq(0) @@ -3517,7 +3522,9 @@ def __init__(self, data_width_write, data_width_read, synchronous, full_threshol # Checking if the FIFO is empty if (data_width_write > data_width_read): self.comb += [ - If(self.rd_ptr == self.sync_rdclk_wrtptr_binary_multiple, + If (ResetSignal("rd"), + self.empty.eq(1) + ).Elif(self.rd_ptr == self.sync_rdclk_wrtptr_binary_multiple, self.empty.eq(1) ).Elif(self.pessimistic_empty == 2, self.empty.eq(0) @@ -3560,7 +3567,9 @@ def __init__(self, data_width_write, data_width_read, synchronous, full_threshol ] elif (data_width_write == data_width_read): self.comb += [ - If(self.rd_ptr == self.sync_rdclk_wrtptr_binary, + If (ResetSignal("rd"), + self.empty.eq(1) + ).Elif(self.rd_ptr == self.sync_rdclk_wrtptr_binary, self.empty.eq(1) ).Elif(self.pessimistic_empty == 2, self.empty.eq(0) @@ -3603,7 +3612,9 @@ def __init__(self, data_width_write, data_width_read, synchronous, full_threshol ] else: self.comb += [ - If(self.rd_pointer_multiple == self.sync_rdclk_wrtptr_binary, + If (ResetSignal("rd"), + self.empty.eq(1) + ).Elif(self.rd_pointer_multiple == self.sync_rdclk_wrtptr_binary, self.empty.eq(1) ).Elif(self.pessimistic_empty == 2, self.empty.eq(0) diff --git a/rapidsilicon/ip/ocla/v1_0/src/ocla.sv b/rapidsilicon/ip/ocla/v1_0/src/ocla.sv index 41ca4c03d..e90af7c2f 100644 --- a/rapidsilicon/ip/ocla/v1_0/src/ocla.sv +++ b/rapidsilicon/ip/ocla/v1_0/src/ocla.sv @@ -3176,11 +3176,11 @@ module ocla_mem_controller #( end end - dual_port_ram #( + dual_port_ram_ocla #( .DATASIZE(DATASIZE), .ADDRSIZE(ADDRSIZE), .DEPTH(MEM_DEPTH) - ) dual_port_ram ( + ) dual_port_ram_ocla ( .rdata (rd_data), .wr_clk(wr_clk), .rd_clk(rd_clk), @@ -3191,10 +3191,10 @@ module ocla_mem_controller #( .raddr (rdaddr) ); - synchronizer #( + synchronizer_ocla #( .SYNC_STAGES(SYNC_STAGES), .ADDRSIZE (ADDRSIZE) - ) synchronizer ( + ) synchronizer_ocla ( .wptr_reg(wptr_reg), .rptr_reg(rptr_reg), .wr_clk (wr_clk), @@ -3436,7 +3436,7 @@ endmodule // // ***************************************************************** -module dual_port_ram #( +module dual_port_ram_ocla #( parameter DATASIZE = 32, parameter ADDRSIZE = 8, parameter DEPTH = 256 @@ -3451,13 +3451,13 @@ module dual_port_ram #( input [ADDRSIZE-1:0] waddr, input [ADDRSIZE-1:0] raddr ); - reg [DATASIZE-1:0] mem [0:DEPTH-1]; + reg [DATASIZE-1:0] ocla_mem [0:DEPTH-1]; always @(posedge rd_clk) begin if (ren) begin - rdata <= mem[raddr]; + rdata <= ocla_mem[raddr]; end end @@ -3465,7 +3465,7 @@ module dual_port_ram #( begin if (wen) begin - mem[waddr] <= wdata; + ocla_mem[waddr] <= wdata; end end @@ -3756,7 +3756,7 @@ endmodule // // ***************************************************************** -module synchronizer #( +module synchronizer_ocla #( parameter SYNC_STAGES = 2, parameter ADDRSIZE = 4 )