diff --git a/EDA-3228/raptor.tcl b/EDA-3228/raptor.tcl new file mode 100644 index 00000000..d04654ff --- /dev/null +++ b/EDA-3228/raptor.tcl @@ -0,0 +1,23 @@ +create_design axi_fifo_wrapper +target_device 1VG28 +configure_ip axi_fifo_v1_0 -mod_name axi_fifo_wrapper -Pdata_width=32 -Paddr_width=32 -Pid_width=1 -Paw_user_en=0 -Paw_user_width=1 -Pw_user_en=0 -Pw_user_width=1 -Pb_user_en=0 -Pb_user_width=1 -Par_user_en=0 -Par_user_width=1 -Pr_user_en=0 -Pr_user_width=1 -Pwrite_fifo_depth=128 -Pread_fifo_depth=128 -Pwrite_fifo_delay=0 -Pread_fifo_delay=0 -out_file ./axi_fifo_wrapper/run_1/IPs/axi_fifo_wrapper +ipgenerate +add_library_path ./axi_fifo_wrapper/run_1/IPs/rapidsilicon/ip/axi_fifo/v1_0/axi_fifo_wrapper/src/ +add_design_file ./axi_fifo_wrapper/run_1/IPs/rapidsilicon/ip/axi_fifo/v1_0/axi_fifo_wrapper/src/axi_fifo_wrapper\_v1_0.v +set_top_module axi_fifo_wrapper +analyze +synth_options -new_tdp36k +synthesize delay +setup_lec_sim +simulation_options compilation icarus gate +simulate gate icarus +pin_loc_assign_method free +packing +place +route +simulation_options compilation icarus pnr +simulate pnr icarus +sta +power +bitstream + diff --git a/EDA-3229/raptor.tcl b/EDA-3229/raptor.tcl new file mode 100644 index 00000000..af5a8718 --- /dev/null +++ b/EDA-3229/raptor.tcl @@ -0,0 +1,26 @@ +create_design eio_top2 +target_device 1VG28 +configure_ip axil_eio_v1_0 -mod_name axil_eio_default -out_file ./axil_eio_default/run_1/IPs/axil_eio_default + +ipgenerate +add_include_path ./axil_eio_default/run_1/IPs/rapidsilicon/ip/axil_eio/v1_0/axil_eio_default/src/ +add_library_ext .v .sv +add_library_path ./axil_eio_default/run_1/IPs/rapidsilicon/ip/axil_eio/v1_0/axil_eio_default/src/ +add_design_file ./axil_eio_default/run_1/IPs/rapidsilicon/ip/axil_eio/v1_0/axil_eio_default/src/axil_eio_default_v1_0.v +set_top_module axil_eio_default + +analyze +synth_options -new_tdp36k +synthesize delay +setup_lec_sim +simulation_options compilation icarus gate +simulate gate icarus +pin_loc_assign_method free +packing +place +route +simulation_options compilation icarus pnr +simulate pnr icarus +sta +power +bitstream diff --git a/EDA-3236/raptor_tcl.tcl b/EDA-3236/raptor_tcl.tcl new file mode 100644 index 00000000..6c7f2af9 --- /dev/null +++ b/EDA-3236/raptor_tcl.tcl @@ -0,0 +1,19 @@ +create_design ocla_probe1024_mem_depth_32 +target_device 1VG28 +add_library_ext .v .sv +add_library_path ./rtl +add_design_file ./rtl/ocla_probe1024_mem_depth_32.sv +set_top_module ocla_probe1024_mem_depth_32 +analyze +synthesize delay +setup_lec_sim +simulation_options compilation icarus gate +simulate gate icarus +packing +place +route +simulation_options compilation icarus pnr +simulate pnr icarus +sta +power +bitstream diff --git a/EDA-3236/rtl/arbiter.v b/EDA-3236/rtl/arbiter.v new file mode 100644 index 00000000..cfac70d1 --- /dev/null +++ b/EDA-3236/rtl/arbiter.v @@ -0,0 +1,159 @@ +/* + +Copyright (c) 2014-2021 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * Arbiter module + */ +module arbiter # +( + parameter PORTS = 4, + // select round robin arbitration + parameter ARB_TYPE_ROUND_ROBIN = 0, + // blocking arbiter enable + parameter ARB_BLOCK = 0, + // block on acknowledge assert when nonzero, request deassert when 0 + parameter ARB_BLOCK_ACK = 1, + // LSB priority selection + parameter ARB_LSB_HIGH_PRIORITY = 0 +) +( + input wire clk, + input wire rst, + + input wire [PORTS-1:0] request, + input wire [PORTS-1:0] acknowledge, + + output wire [PORTS-1:0] grant, + output wire grant_valid, + output wire [$clog2(PORTS)-1:0] grant_encoded +); + +reg [PORTS-1:0] grant_reg = 0, grant_next; +reg grant_valid_reg = 0, grant_valid_next; +reg [$clog2(PORTS)-1:0] grant_encoded_reg = 0, grant_encoded_next; + +assign grant_valid = grant_valid_reg; +assign grant = grant_reg; +assign grant_encoded = grant_encoded_reg; + +wire request_valid; +wire [$clog2(PORTS)-1:0] request_index; +wire [PORTS-1:0] request_mask; + +priority_encoder #( + .WIDTH(PORTS), + .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) +) +priority_encoder_inst ( + .input_unencoded(request), + .output_valid(request_valid), + .output_encoded(request_index), + .output_unencoded(request_mask) +); + +reg [PORTS-1:0] mask_reg = 0, mask_next; + +wire masked_request_valid; +wire [$clog2(PORTS)-1:0] masked_request_index; +wire [PORTS-1:0] masked_request_mask; + +priority_encoder #( + .WIDTH(PORTS), + .LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY) +) +priority_encoder_masked ( + .input_unencoded(request & mask_reg), + .output_valid(masked_request_valid), + .output_encoded(masked_request_index), + .output_unencoded(masked_request_mask) +); + +always @* begin + grant_next = 0; + grant_valid_next = 0; + grant_encoded_next = 0; + mask_next = mask_reg; + + if (ARB_BLOCK && !ARB_BLOCK_ACK && grant_reg & request) begin + // granted request still asserted; hold it + grant_valid_next = grant_valid_reg; + grant_next = grant_reg; + grant_encoded_next = grant_encoded_reg; + end else if (ARB_BLOCK && ARB_BLOCK_ACK && grant_valid && !(grant_reg & acknowledge)) begin + // granted request not yet acknowledged; hold it + grant_valid_next = grant_valid_reg; + grant_next = grant_reg; + grant_encoded_next = grant_encoded_reg; + end else if (request_valid) begin + if (ARB_TYPE_ROUND_ROBIN) begin + if (masked_request_valid) begin + grant_valid_next = 1; + grant_next = masked_request_mask; + grant_encoded_next = masked_request_index; + if (ARB_LSB_HIGH_PRIORITY) begin + mask_next = {PORTS{1'b1}} << (masked_request_index + 1); + end else begin + mask_next = {PORTS{1'b1}} >> (PORTS - masked_request_index); + end + end else begin + grant_valid_next = 1; + grant_next = request_mask; + grant_encoded_next = request_index; + if (ARB_LSB_HIGH_PRIORITY) begin + mask_next = {PORTS{1'b1}} << (request_index + 1); + end else begin + mask_next = {PORTS{1'b1}} >> (PORTS - request_index); + end + end + end else begin + grant_valid_next = 1; + grant_next = request_mask; + grant_encoded_next = request_index; + end + end +end + +always @(posedge clk) begin + if (rst) begin + grant_reg <= 0; + grant_valid_reg <= 0; + grant_encoded_reg <= 0; + mask_reg <= 0; + end else begin + grant_reg <= grant_next; + grant_valid_reg <= grant_valid_next; + grant_encoded_reg <= grant_encoded_next; + mask_reg <= mask_next; + end +end + +endmodule + +`resetall diff --git a/EDA-3236/rtl/axi2axilite.v b/EDA-3236/rtl/axi2axilite.v new file mode 100644 index 00000000..9b81f992 --- /dev/null +++ b/EDA-3236/rtl/axi2axilite.v @@ -0,0 +1,872 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: axi2axilite.v +// {{{ +// Project: WB2AXIPSP: bus bridges and other odds and ends +// +// Purpose: Convert from AXI to AXI-lite with no performance loss. +// +// Performance: The goal of this converter is to convert from AXI to AXI-lite +// while still maintaining the one-clock per transaction speed +// of AXI. It currently achieves this goal. The design needs very little +// configuration to be useful, but you might wish to resize the FIFOs +// within depending upon the length of your slave's data path. The current +// FIFO length, LGFIFO=4, is sufficient to maintain full speed. If the +// slave, however, can maintain full speed but requires a longer +// processing cycle, then you may need longer FIFOs. +// +// The AXI specification does require an additional 2 clocks per +// transaction when using this core, so your latency will go up. +// +// Related: There's a related axidouble.v core in the same repository as +// well. That can be used to convert the AXI protocol to something +// simpler (even simpler than AXI-lite), but it can also do so for multiple +// downstream slaves at the same time. +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// }}} +// Copyright (C) 2019-2022, Gisselquist Technology, LLC +// {{{ +// This file is part of the WB2AXIP project. +// +// The WB2AXIP project contains free software and gateware, licensed under the +// Apache License, Version 2.0 (the "License"). You may not use this project, +// or 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. +// +//////////////////////////////////////////////////////////////////////////////// +// +// +//`default_nettype none +// }}} +module axi2axilite #( + // {{{ + parameter integer C_AXI_ID_WIDTH = 2, + parameter integer C_AXI_DATA_WIDTH = 32, + parameter integer C_AXI_ADDR_WIDTH = 6, + parameter [0:0] OPT_WRITES = 1, + parameter [0:0] OPT_READS = 1, + parameter [0:0] OPT_LOWPOWER = 0, + // Log (based two) of the maximum number of outstanding AXI + // (not AXI-lite) transactions. If you multiply 2^LGFIFO * 256, + // you'll get the maximum number of outstanding AXI-lite + // transactions + parameter LGFIFO = 4 + // }}} + ) ( + // {{{ + input wire S_AXI_ACLK, + input wire S_AXI_ARESETN, + // AXI4 slave interface + // {{{ + // Write address channel + // {{{ + input wire S_AXI_AWVALID, + output wire S_AXI_AWREADY, + input wire [C_AXI_ID_WIDTH-1:0] S_AXI_AWID, + input wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_AWADDR, + input wire [7:0] S_AXI_AWLEN, + input wire [2:0] S_AXI_AWSIZE, + input wire [1:0] S_AXI_AWBURST, + input wire S_AXI_AWLOCK, + input wire [3:0] S_AXI_AWCACHE, + input wire [2:0] S_AXI_AWPROT, + input wire [3:0] S_AXI_AWQOS, + // }}} + // Write data channel + // {{{ + input wire S_AXI_WVALID, + output wire S_AXI_WREADY, + input wire [C_AXI_DATA_WIDTH-1:0] S_AXI_WDATA, + input wire [(C_AXI_DATA_WIDTH/8)-1:0] S_AXI_WSTRB, + input wire S_AXI_WLAST, + // }}} + // Write return channel + // {{{ + output wire S_AXI_BVALID, + input wire S_AXI_BREADY, + output wire [C_AXI_ID_WIDTH-1:0] S_AXI_BID, + output wire [1:0] S_AXI_BRESP, + // }}} + // Read address channel + // {{{ + input wire S_AXI_ARVALID, + output wire S_AXI_ARREADY, + input wire [C_AXI_ID_WIDTH-1:0] S_AXI_ARID, + input wire [C_AXI_ADDR_WIDTH-1:0] S_AXI_ARADDR, + input wire [7:0] S_AXI_ARLEN, + input wire [2:0] S_AXI_ARSIZE, + input wire [1:0] S_AXI_ARBURST, + input wire S_AXI_ARLOCK, + input wire [3:0] S_AXI_ARCACHE, + input wire [2:0] S_AXI_ARPROT, + input wire [3:0] S_AXI_ARQOS, + // }}} + // Read data channel + // {{{ + output wire S_AXI_RVALID, + input wire S_AXI_RREADY, + output wire [C_AXI_ID_WIDTH-1:0] S_AXI_RID, + output wire [C_AXI_DATA_WIDTH-1:0] S_AXI_RDATA, + output wire [1:0] S_AXI_RRESP, + output wire S_AXI_RLAST, + // }}} + // }}} + // AXI-lite master interface + // {{{ + // AXI-lite Write interface + // {{{ + output wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_AWADDR, + output wire [2 : 0] M_AXI_AWPROT, + output wire M_AXI_AWVALID, + input wire M_AXI_AWREADY, + + output wire [C_AXI_DATA_WIDTH-1:0] M_AXI_WDATA, + output wire [(C_AXI_DATA_WIDTH/8)-1:0] M_AXI_WSTRB, + output wire M_AXI_WVALID, + input wire M_AXI_WREADY, + + input wire [1 : 0] M_AXI_BRESP, + input wire M_AXI_BVALID, + output wire M_AXI_BREADY, + // }}} + // AXI-lite read interface + // {{{ + output wire [C_AXI_ADDR_WIDTH-1:0] M_AXI_ARADDR, + output wire [2:0] M_AXI_ARPROT, + output wire M_AXI_ARVALID, + input wire M_AXI_ARREADY, + // + input wire M_AXI_RVALID, + output wire M_AXI_RREADY, + input wire [C_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA, + input wire [1 : 0] M_AXI_RRESP + // }}} + // }}} + // }}} + ); + + // Local parameters, register, and net declarations + // {{{ + localparam [1:0] SLVERR = 2'b10; + // localparam [1:0] OKAY = 2'b00, + // EXOKAY = 2'b01, + // DECERR = 2'b10; + localparam AW = C_AXI_ADDR_WIDTH; + localparam DW = C_AXI_DATA_WIDTH; + localparam IW = C_AXI_ID_WIDTH; + // }}} + // Register declarations + // {{{ + // + // Write registers + reg m_axi_awvalid, s_axi_wready; + reg [C_AXI_ADDR_WIDTH-1:0] axi_awaddr; + reg [7:0] axi_awlen, axi_blen; + reg [1:0] axi_awburst; + reg [2:0] axi_awsize; + wire [C_AXI_ADDR_WIDTH-1:0] next_write_addr; + wire [4:0] wfifo_count; + wire wfifo_full; + wire wfifo_empty; + 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 [1:0] axi_bresp; + reg s_axi_bvalid; + wire read_from_wrfifo; + // + // Read register + reg m_axi_arvalid; + wire [4:0] rfifo_count; + wire rfifo_full; + wire rfifo_empty; + wire [7:0] rfifo_rcount; + reg s_axi_rvalid; + reg [1:0] s_axi_rresp; + reg [8:0] rcounts; + reg [C_AXI_ADDR_WIDTH-1:0] axi_araddr; + 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 s_axi_rlast; + reg [IW-1:0] rid; + wire read_from_rdfifo; + + // + // S_AXI_AW* skid buffer + wire skids_awvalid, skids_awready; + wire [IW-1:0] skids_awid; + wire [AW-1:0] skids_awaddr; + wire [7:0] skids_awlen; + wire [2:0] skids_awsize; + wire [1:0] skids_awburst; + // + // S_AXI_W* skid buffer + wire skids_wvalid, skids_wready, skids_wlast; + wire [DW-1:0] skids_wdata; + wire [DW/8-1:0] skids_wstrb; + // + // S_AXI_B* skid buffer isn't needed + // + // M_AXI_AW* skid buffer isn't needed + // + // M_AXI_W* skid buffer + wire skidm_wvalid, skidm_wready; + wire [DW-1:0] skidm_wdata; + wire [DW/8-1:0] skidm_wstrb; + // + // M_AXI_B* skid buffer + wire skidm_bvalid, skidm_bready; + wire [1:0] skidm_bresp; + // + // + // + // S_AXI_AR* skid buffer + wire skids_arvalid, skids_arready; + wire [IW-1:0] skids_arid; + wire [AW-1:0] skids_araddr; + wire [7:0] skids_arlen; + wire [2:0] skids_arsize; + wire [1:0] skids_arburst; + // + // S_AXI_R* skid buffer isn't needed + // + // M_AXI_AR* skid buffer isn't needed + // M_AXI_R* skid buffer + wire skidm_rvalid, skidm_rready; + wire [DW-1:0] skidm_rdata; + wire [1:0] skidm_rresp; + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Write logic + // {{{ + //////////////////////////////////////////////////////////////////////// + // + // + generate if (OPT_WRITES) + begin : IMPLEMENT_WRITES + // {{{ + // The write address channel's skid buffer + // {{{ + skidbuffer #( + // {{{ + .DW(IW+AW+8+3+2), .OPT_LOWPOWER(0), .OPT_OUTREG(0) + // }}} + ) awskid( + // {{{ + S_AXI_ACLK, !S_AXI_ARESETN, + S_AXI_AWVALID, S_AXI_AWREADY, + { S_AXI_AWID, S_AXI_AWADDR, S_AXI_AWLEN, S_AXI_AWSIZE, + S_AXI_AWBURST }, + skids_awvalid, skids_awready, + { skids_awid, skids_awaddr, skids_awlen, skids_awsize, + skids_awburst } + // }}} + ); + // }}} + // + // The write data channel's skid buffer (S_AXI_W*) + // {{{ + skidbuffer #( + // {{{ + .DW(DW+DW/8+1), .OPT_LOWPOWER(0), .OPT_OUTREG(0) + // }}} + ) wskid( + // {{{ + S_AXI_ACLK, !S_AXI_ARESETN, + S_AXI_WVALID, S_AXI_WREADY, + { S_AXI_WDATA, S_AXI_WSTRB, S_AXI_WLAST }, + skids_wvalid, skids_wready, + { skids_wdata, skids_wstrb, skids_wlast } + // }}} + ); + // }}} + // + // The downstream AXI-lite write data (M_AXI_W*) skid buffer + // {{{ + skidbuffer #( + // {{{ + .DW(DW+DW/8), .OPT_LOWPOWER(0), .OPT_OUTREG(1) + // }}} + ) mwskid( + // {{{ + S_AXI_ACLK, !S_AXI_ARESETN, + skidm_wvalid, skidm_wready, { skidm_wdata, skidm_wstrb }, + M_AXI_WVALID,M_AXI_WREADY,{ M_AXI_WDATA, M_AXI_WSTRB } + // }}} + ); + // }}} + // + // The downstream AXI-lite response (M_AXI_B*) skid buffer + // {{{ + skidbuffer #( + // {{{ + .DW(2), .OPT_LOWPOWER(0), .OPT_OUTREG(0) + // }}} + ) bskid( + // {{{ + S_AXI_ACLK, !S_AXI_ARESETN, + M_AXI_BVALID, M_AXI_BREADY, { M_AXI_BRESP }, + skidm_bvalid, skidm_bready, { skidm_bresp } + // }}} + ); + // }}} + + // m_axi_awvalid + // {{{ + initial m_axi_awvalid = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + m_axi_awvalid <= 0; + else if (skids_awvalid & skids_awready) + m_axi_awvalid <= 1; + else if (M_AXI_AWREADY && axi_awlen == 0) + m_axi_awvalid <= 0; + + assign M_AXI_AWVALID = m_axi_awvalid; + // }}} + + // skids_awready + // {{{ + assign skids_awready = (!M_AXI_AWVALID + || ((axi_awlen == 0)&&M_AXI_AWREADY)) + && !wfifo_full + &&(!s_axi_wready || (skids_wvalid && skids_wlast && skids_wready)); + // }}} + + // Address processing + // {{{ + always @(posedge S_AXI_ACLK) + if (skids_awvalid && skids_awready) + begin + axi_awaddr <= skids_awaddr; + axi_blen <= skids_awlen; + axi_awburst<= skids_awburst; + axi_awsize <= skids_awsize; + end else if (M_AXI_AWVALID && M_AXI_AWREADY) + axi_awaddr <= next_write_addr; + // }}} + + // axi_awlen + // {{{ + initial axi_awlen = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + axi_awlen <= 0; + else if (skids_awvalid && skids_awready) + axi_awlen <= skids_awlen; + else if (M_AXI_AWVALID && M_AXI_AWREADY && axi_awlen > 0) + axi_awlen <= axi_awlen - 1; + // }}} + + // axi_addr + // {{{ + axi_addr #( + // {{{ + .AW(C_AXI_ADDR_WIDTH), .DW(C_AXI_DATA_WIDTH) + // }}} + ) calcwraddr( + // {{{ + axi_awaddr, axi_awsize, axi_awburst, + axi_blen, next_write_addr + // }}} + ); + // }}} + + // s_axi_wready + // {{{ + // We really don't need to do anything special to the write + // channel. + initial s_axi_wready = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + s_axi_wready <= 0; + else if (skids_awvalid && skids_awready) + s_axi_wready <= 1; + else if (skids_wvalid && skids_wready && skids_wlast) + s_axi_wready <= 0; + // }}} + + // skidm*, and read_from_wrfifo + // {{{ + assign skidm_wdata = skids_wdata; + assign skidm_wstrb = skids_wstrb; + assign skidm_wvalid = skids_wvalid && s_axi_wready; + assign skids_wready = s_axi_wready && skidm_wready; + + assign read_from_wrfifo = (bcounts <= 1)&&(!wfifo_empty) + &&(skidm_bvalid && skidm_bready); + // }}} + + // BFIFO + // {{{ + sfifo #( + .BW(C_AXI_ID_WIDTH+8), .LGFLEN(LGFIFO) + ) bidlnfifo( + S_AXI_ACLK, !S_AXI_ARESETN, + skids_awvalid && skids_awready, + { skids_awid, skids_awlen }, + wfifo_full, wfifo_count, + read_from_wrfifo, + { wfifo_bid, wfifo_bcount }, wfifo_empty); + // }}} + + // bcounts + // {{{ + // Return counts + initial bcounts = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + bcounts <= 0; + else if (read_from_wrfifo) + begin + bcounts <= wfifo_bcount + bcounts; + end else if (skidm_bvalid && skidm_bready) + bcounts <= bcounts - 1; + // }}} + + // bid + // {{{ + always @(posedge S_AXI_ACLK) + if (read_from_wrfifo) + bid <= wfifo_bid; + + always @(posedge S_AXI_ACLK) + if (!S_AXI_BVALID || S_AXI_BREADY) + axi_bid <= (read_from_wrfifo && bcounts==0) ? wfifo_bid : bid; + // }}} + + // s_axi_bvalid + // {{{ + initial s_axi_bvalid = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + s_axi_bvalid <= 0; + else if (skidm_bvalid && skidm_bready) + s_axi_bvalid <= (bcounts == 1) + ||((bcounts == 0) && (!wfifo_empty) && (wfifo_bcount == 0)); + else if (S_AXI_BREADY) + s_axi_bvalid <= 0; + // }}} + + // axi_bresp + // {{{ + initial axi_bresp = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + axi_bresp <= 0; + else if (S_AXI_BVALID && S_AXI_BREADY) + begin + if (skidm_bvalid && skidm_bready) + axi_bresp <= skidm_bresp; + else + axi_bresp <= 0; + end else if (skidm_bvalid && skidm_bready) + begin + // Let SLVERR take priority over DECERR + casez({ S_AXI_BRESP, skidm_bresp }) + 4'b??0?: axi_bresp <= S_AXI_BRESP; + 4'b0?1?: axi_bresp <= skidm_bresp; + 4'b1?10: axi_bresp <= SLVERR; + 4'b1011: axi_bresp <= SLVERR; + 4'b1111: axi_bresp <= skidm_bresp; + endcase + end + // /}}} + + // M_AXI_AW* + // {{{ + assign M_AXI_AWVALID= m_axi_awvalid; + assign M_AXI_AWADDR = axi_awaddr; + assign M_AXI_AWPROT = S_AXI_AWPROT; + // }}} + + // skidm_bready, S_AXI_B* + // {{{ + assign skidm_bready = ((bcounts > 0)||(!wfifo_empty))&&(!S_AXI_BVALID | S_AXI_BREADY); + assign S_AXI_BID = axi_bid; + assign S_AXI_BRESP = axi_bresp; + assign S_AXI_BVALID = s_axi_bvalid; + // }}} + // }}} + end else begin : NO_WRITE_SUPPORT + // {{{ + assign S_AXI_AWREADY = 0; + assign S_AXI_WREADY = 0; + assign S_AXI_BID = 0; + assign S_AXI_BRESP = 2'b11; + assign S_AXI_BVALID = 0; + assign S_AXI_BID = 0; + + // + assign M_AXI_AWVALID = 0; + assign M_AXI_AWADDR = 0; + assign M_AXI_AWPROT = 0; + // + assign M_AXI_WVALID = 0; + assign M_AXI_WDATA = 0; + assign M_AXI_WSTRB = 0; + // + assign M_AXI_BREADY = 0; + + // + // S_AXI_AW* skid buffer + assign skids_awvalid = 0; + assign skids_awready = 0; + assign skids_awid = 0; + assign skids_awaddr = 0; + assign skids_awlen = 0; + assign skids_awsize = 0; + assign skids_awburst = 0; + // + // S_AXI_W* skid buffer + assign skids_wvalid = S_AXI_WVALID; + assign skids_wready = S_AXI_WREADY; + assign skids_wdata = S_AXI_WDATA; + assign skids_wstrb = S_AXI_WSTRB; + assign skids_wlast = S_AXI_WLAST; + // + // S_AXI_B* skid buffer isn't needed + // + // M_AXI_AW* skid buffer isn't needed + // + // M_AXI_W* skid buffer + assign skidm_wvalid = M_AXI_WVALID; + assign skidm_wready = M_AXI_WREADY; + assign skidm_wdata = M_AXI_WDATA; + assign skidm_wstrb = M_AXI_WSTRB; + // + // M_AXI_B* skid buffer + assign skidm_bvalid = M_AXI_BVALID; + assign skidm_bready = M_AXI_BREADY; + assign skidm_bresp = M_AXI_BRESP; + // + // + always @(*) + begin + s_axi_wready = 0; + + axi_awlen = 0; + bcounts = 0; + bid = 0; + axi_bresp = 0; + axi_bid = 0; + + end + + assign wfifo_full = 0; + assign wfifo_empty = 1; + assign wfifo_count = 0; + assign read_from_wrfifo = 0; + + // Make Verilator happy + // {{{ + // Verilator lint_off UNUSED + wire unused_write_signals; + assign unused_write_signals = &{ 1'b0, M_AXI_AWREADY, + M_AXI_WREADY, S_AXI_BREADY }; + // Verilator lint_on UNUSED + // }}} + + // }}} + end endgenerate + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Read logic + // {{{ + //////////////////////////////////////////////////////////////////////// + // + // + generate if (OPT_READS) + begin : IMPLEMENT_READS + // {{{ + // S_AXI_AR* skid buffer + // {{{ + skidbuffer #( + // {{{ + .DW(IW+AW+8+3+2), .OPT_LOWPOWER(0), .OPT_OUTREG(0) + // }}} + ) arskid( + // {{{ + S_AXI_ACLK, !S_AXI_ARESETN, + S_AXI_ARVALID, S_AXI_ARREADY, + { S_AXI_ARID, S_AXI_ARADDR, S_AXI_ARLEN, S_AXI_ARSIZE, + S_AXI_ARBURST }, + skids_arvalid, skids_arready, + { skids_arid, skids_araddr, skids_arlen, skids_arsize, + skids_arburst } + // }}} + ); + // }}} + // M_AXI_R* skid buffer + // {{{ + skidbuffer #( + // {{{ + .DW(DW+2), .OPT_LOWPOWER(0), .OPT_OUTREG(0) + // }}} + ) rskid( + // {{{ + S_AXI_ACLK, !S_AXI_ARESETN, + M_AXI_RVALID, M_AXI_RREADY,{ M_AXI_RDATA, M_AXI_RRESP }, + skidm_rvalid,skidm_rready,{ skidm_rdata, skidm_rresp } + // }}} + ); + // }}} + // m_axi_arvalid + // {{{ + initial m_axi_arvalid = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + m_axi_arvalid <= 0; + else if (skids_arvalid && skids_arready) + m_axi_arvalid <= 1; + else if (M_AXI_ARREADY && axi_arlen == 0) + m_axi_arvalid <= 0; + // }}} + + // Read address processing + // {{{ + always @(posedge S_AXI_ACLK) + if (skids_arvalid && skids_arready) + begin + axi_araddr <= skids_araddr; + axi_arburst <= skids_arburst; + axi_arsize <= skids_arsize; + axi_rlen <= skids_arlen; + end else if (M_AXI_ARREADY) + begin + axi_araddr <= next_read_addr; + if (OPT_LOWPOWER && axi_arlen == 0) + axi_araddr <= 0; + end + + axi_addr #( + // {{{ + .AW(C_AXI_ADDR_WIDTH), .DW(C_AXI_DATA_WIDTH) + // }}} + ) calcrdaddr( + // {{{ + axi_araddr, axi_arsize, axi_arburst, + axi_rlen, next_read_addr + // }}} + ); + // }}} + + // axi_arlen, Read length processing + // {{{ + initial axi_arlen = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + axi_arlen <= 0; + else if (skids_arvalid && skids_arready) + axi_arlen <= skids_arlen; + else if (M_AXI_ARVALID && M_AXI_ARREADY && axi_arlen > 0) + axi_arlen <= axi_arlen - 1; + // }}} + + assign skids_arready = (!M_AXI_ARVALID || + ((axi_arlen == 0) && M_AXI_ARREADY)) + && !rfifo_full; + + assign read_from_rdfifo = skidm_rvalid && skidm_rready + && (rcounts <= 1) && !rfifo_empty; + // Make Verilator happy + // {{{ + // Verilator lint_off UNUSED + wire unused_write_signals; + assign unused_write_signals = &{ 1'b0, M_AXI_AWREADY, + M_AXI_WREADY, S_AXI_BREADY }; + // Verilator lint_on UNUSED + // }}} + + // Read ID FIFO + // {{{ + sfifo #( + // {{{ + .BW(C_AXI_ID_WIDTH+8), .LGFLEN(LGFIFO) + // }}} + ) ridlnfifo( + // {{{ + S_AXI_ACLK, !S_AXI_ARESETN, + skids_arvalid && skids_arready, + { skids_arid, skids_arlen }, + rfifo_full, rfifo_count, + read_from_rdfifo, + { rfifo_rid, rfifo_rcount }, rfifo_empty + // }}} + ); + // }}} + + assign skidm_rready = (!S_AXI_RVALID || S_AXI_RREADY); + + // s_axi_rvalid + // {{{ + initial s_axi_rvalid = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + s_axi_rvalid <= 0; + else if (skidm_rvalid && skidm_rready) + s_axi_rvalid <= 1; + else if (S_AXI_RREADY) + s_axi_rvalid <= 0; + // }}} + + // s_axi_rresp, s_axi_rdata + // {{{ + always @(posedge S_AXI_ACLK) + if (skidm_rvalid && skidm_rready) + begin + s_axi_rresp <= skidm_rresp; + s_axi_rdata <= skidm_rdata; + end else if (S_AXI_RREADY) + begin + s_axi_rresp <= 0; + s_axi_rdata <= 0; + end + // }}} + + // rcounts, Return counts + // {{{ + initial rcounts = 0; + always @(posedge S_AXI_ACLK) + if (!S_AXI_ARESETN) + rcounts <= 0; + else if (read_from_rdfifo) + rcounts <= rfifo_rcount + rcounts; + else if (skidm_rvalid && skidm_rready) + rcounts <= rcounts - 1; + // }}} + + // rid + // {{{ + initial rid = 0; + always @(posedge S_AXI_ACLK) + if (read_from_rdfifo) + rid <= rfifo_rid; + // }}} + + // s_axi_rlast + // {{{ + always @(posedge S_AXI_ACLK) + 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; + end + // }}} + + // s_axi_rid + // {{{ + initial s_axi_rid = 0; + always @(posedge S_AXI_ACLK) + if ((S_AXI_RVALID && S_AXI_RREADY && S_AXI_RLAST) + ||(!S_AXI_RVALID && rcounts == 0)) + s_axi_rid <= (read_from_rdfifo)&&(rcounts == 0)?rfifo_rid : rid; + // }}} + + // M_AXI_AR* + // {{{ + assign M_AXI_ARVALID= m_axi_arvalid; + assign M_AXI_ARADDR = axi_araddr; + assign M_AXI_ARPROT = S_AXI_ARPROT; + // }}} + // S_AXI_R* + // {{{ + assign S_AXI_RVALID = s_axi_rvalid; + assign S_AXI_RDATA = s_axi_rdata; + assign S_AXI_RRESP = s_axi_rresp; + assign S_AXI_RLAST = s_axi_rlast; + assign S_AXI_RID = s_axi_rid; + // }}} + // }}} + end else begin : NO_READ_SUPPORT // if (!OPT_READS) + // {{{ + assign M_AXI_ARVALID= 0; + assign M_AXI_ARADDR = 0; + assign M_AXI_ARPROT = 0; + assign M_AXI_RREADY = 0; + // + assign S_AXI_ARREADY= 0; + assign S_AXI_RVALID = 0; + assign S_AXI_RDATA = 0; + assign S_AXI_RRESP = 0; + assign S_AXI_RLAST = 0; + assign S_AXI_RID = 0; + + // + assign skids_arvalid = S_AXI_ARVALID; + assign skids_arready = S_AXI_ARREADY; + assign skids_arid = S_AXI_ARID; + assign skids_araddr = S_AXI_ARADDR; + assign skids_arlen = S_AXI_ARLEN; + assign skids_arsize = S_AXI_ARSIZE; + assign skids_arburst = S_AXI_ARBURST; + // + assign skidm_rvalid = M_AXI_RVALID; + assign skidm_rready = M_AXI_RREADY; + assign skidm_rdata = M_AXI_RDATA; + assign skidm_rresp = M_AXI_RRESP; + // + // + always @(*) + begin + axi_arlen = 0; + + rcounts = 0; + rid = 0; + + end + assign rfifo_empty = 1; + assign rfifo_full = 0; + assign rfifo_count = 0; + + // Make Verilator happy + // {{{ + // Verilator lint_off UNUSED + wire unused_read_signals; + assign unused_read_signals = &{ 1'b0, M_AXI_ARREADY, + S_AXI_RREADY }; + // Verilator lint_on UNUSED + // }}} + + // }}} + end endgenerate + // }}} + // Make Verilator happy + // {{{ + // Verilator lint_off UNUSED + wire [35-1:0] unused; + assign unused = { + S_AXI_AWLOCK, S_AXI_AWCACHE, S_AXI_AWPROT, S_AXI_AWQOS, + skids_wlast, wfifo_count, + S_AXI_ARLOCK, S_AXI_ARCACHE, S_AXI_ARPROT, S_AXI_ARQOS, + rfifo_count }; + // Verilator lint_on UNUSED + // }}} + +endmodule diff --git a/EDA-3236/rtl/axi_addr.v b/EDA-3236/rtl/axi_addr.v new file mode 100644 index 00000000..1d712c70 --- /dev/null +++ b/EDA-3236/rtl/axi_addr.v @@ -0,0 +1,240 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: axi_addr.v +// {{{ +// Project: WB2AXIPSP: bus bridges and other odds and ends +// +// Purpose: The AXI (full) standard has some rather complicated addressing +// modes, where the address can either be FIXED, INCRementing, or +// even where it can WRAP around some boundary. When in either INCR or +// WRAP modes, the next address must always be aligned. In WRAP mode, +// the next address calculation needs to wrap around a given value, and +// that value is dependent upon the burst size (i.e. bytes per beat) and +// length (total numbers of beats). Since this calculation can be +// non-trivial, and since it needs to be done multiple times, the logic +// below captures it for every time it might be needed. +// +// 20200918 - modified to accommodate (potential) AXI3 burst lengths +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// }}} +// Copyright (C) 2019-2022, Gisselquist Technology, LLC +// {{{ +// This file is part of the WB2AXIP project. +// +// The WB2AXIP project contains free software and gateware, licensed under the +// Apache License, Version 2.0 (the "License"). You may not use this project, +// or 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. +// +//////////////////////////////////////////////////////////////////////////////// +// +// +`default_nettype none +// }}} +module axi_addr #( + // {{{ + parameter AW = 32, + DW = 32, + // parameter [0:0] OPT_AXI3 = 1'b0, + localparam LENB = 8 + // }}} + ) ( + // {{{ + input wire [AW-1:0] i_last_addr, + input wire [2:0] i_size, // 1b, 2b, 4b, 8b, etc + input wire [1:0] i_burst, // fixed, incr, wrap, reserved + input wire [LENB-1:0] i_len, + output reg [AW-1:0] o_next_addr + // }}} + ); + + // Parameter/register declarations + // {{{ + localparam DSZ = $clog2(DW)-3; + localparam [1:0] FIXED = 2'b00; + // localparam [1:0] INCREMENT = 2'b01; + // localparam [1:0] WRAP = 2'b10; + + reg [AW-1:0] wrap_mask, increment; + // }}} + + // Address increment + // {{{ + always @(*) + begin + increment = 0; + if (i_burst != 0) + begin + // Addresses increment from one beat to the next + // {{{ + if (DSZ == 0) + increment = 1; + else if (DSZ == 1) + increment = (i_size[0]) ? 2 : 1; + else if (DSZ == 2) + increment = (i_size[1]) ? 4 : ((i_size[0]) ? 2 : 1); + else if (DSZ == 3) + case(i_size[1:0]) + 2'b00: increment = 1; + 2'b01: increment = 2; + 2'b10: increment = 4; + 2'b11: increment = 8; + endcase + else + increment = (1< 12) + wrap_mask[(AW-1):((AW>12)? 12:(AW-1))] = 0; + end + // }}} + + // o_next_addr + // {{{ + always @(*) + begin + o_next_addr = i_last_addr + increment; + if (i_burst != FIXED) + begin + // Align subsequent beats in any burst + // {{{ + // + // We use the bus size here to simplify the logic + // required in case the bus is smaller than the + // maximum. This depends upon AxSIZE being less than + // $clog2(DATA_WIDTH/8). + if (DSZ < 2) + begin + // {{{ + // Align any subsequent address + if (i_size[0]) + o_next_addr[0] = 0; + // }}} + end else if (DSZ < 4) + begin + // {{{ + // Align any subsequent address + case(i_size[1:0]) + 2'b00: o_next_addr = o_next_addr; + 2'b01: o_next_addr[ 0] = 0; + 2'b10: o_next_addr[(AW-1>1) ? 1 : (AW-1):0]= 0; + 2'b11: o_next_addr[(AW-1>2) ? 2 : (AW-1):0]= 0; + endcase + // }}} + end else begin + // {{{ + // Align any subsequent address + case(i_size) + 3'b001: o_next_addr[ 0] = 0; + 3'b010: o_next_addr[(AW-1>1) ? 1 : (AW-1):0]=0; + 3'b011: o_next_addr[(AW-1>2) ? 2 : (AW-1):0]=0; + 3'b100: o_next_addr[(AW-1>3) ? 3 : (AW-1):0]=0; + 3'b101: o_next_addr[(AW-1>4) ? 4 : (AW-1):0]=0; + 3'b110: o_next_addr[(AW-1>5) ? 5 : (AW-1):0]=0; + 3'b111: o_next_addr[(AW-1>6) ? 6 : (AW-1):0]=0; + default: o_next_addr = o_next_addr; + endcase + // }}} + end + // }}} + end + + // WRAP addressing + // {{{ + if (i_burst[1]) + begin + // WRAP! + o_next_addr[AW-1:0] = (i_last_addr & ~wrap_mask) + | (o_next_addr & wrap_mask); + end + // }}} + + // Guarantee only the bottom 12 bits change + // {{{ + // This is really a logic simplification. AXI bursts aren't + // allowed to cross 4kB boundaries. Given that's the case, + // we don't have to suffer from the propagation across all + // AW bits, and can limit any address propagation to just the + // lower 12 bits + if (AW > 12) + o_next_addr[AW-1:((AW>12)? 12:(AW-1))] + = i_last_addr[AW-1:((AW>12) ? 12:(AW-1))]; + // }}} + end + // }}} + + // Make Verilator happy + // {{{ + // Verilator lint_off UNUSED + wire unused; + assign unused = (LENB <= 4) ? &{1'b0, i_len[0] } + : &{ 1'b0, i_len[LENB-1:4], i_len[0] }; + // Verilator lint_on UNUSED + // }}} +endmodule diff --git a/EDA-3236/rtl/axil_interconnect.v b/EDA-3236/rtl/axil_interconnect.v new file mode 100644 index 00000000..d682a67d --- /dev/null +++ b/EDA-3236/rtl/axil_interconnect.v @@ -0,0 +1,568 @@ +/* + +Copyright (c) 2018 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * AXI4 lite interconnect + */ +module axil_interconnect # +( + parameter IP_TYPE = "ALIN", + parameter IP_VERSION = 32'h1, + parameter IP_ID = 32'h2591801, + + // Number of AXI inputs (slave interfaces) + parameter S_COUNT = 4, + // Number of AXI outputs (master interfaces) + parameter M_COUNT = 4, + // Width of data bus in bits + parameter DATA_WIDTH = 32, + // Width of address bus in bits + parameter ADDR_WIDTH = 32, + // Width of wstrb (width of data bus in words) + parameter STRB_WIDTH = (DATA_WIDTH/8), + // Number of regions per master interface + parameter M_REGIONS = 1, + // Master interface base addresses + // M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits + // set to zero for default addressing based on M_ADDR_WIDTH + parameter M_BASE_ADDR = 0, + // Master interface address widths + // M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits + parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}}, + // Read connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}}, + // Write connections between interfaces + // M_COUNT concatenated fields of S_COUNT bits + parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}}, + // Secure master (fail operations based on awprot/arprot) + // M_COUNT bits + parameter M_SECURE = {M_COUNT{1'b0}} +) +( + input wire clk, + input wire rst, + + /* + * AXI lite slave interfaces + */ + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axil_awaddr, + input wire [S_COUNT*3-1:0] s_axil_awprot, + input wire [S_COUNT-1:0] s_axil_awvalid, + output wire [S_COUNT-1:0] s_axil_awready, + input wire [S_COUNT*DATA_WIDTH-1:0] s_axil_wdata, + input wire [S_COUNT*STRB_WIDTH-1:0] s_axil_wstrb, + input wire [S_COUNT-1:0] s_axil_wvalid, + output wire [S_COUNT-1:0] s_axil_wready, + output wire [S_COUNT*2-1:0] s_axil_bresp, + output wire [S_COUNT-1:0] s_axil_bvalid, + input wire [S_COUNT-1:0] s_axil_bready, + input wire [S_COUNT*ADDR_WIDTH-1:0] s_axil_araddr, + input wire [S_COUNT*3-1:0] s_axil_arprot, + input wire [S_COUNT-1:0] s_axil_arvalid, + output wire [S_COUNT-1:0] s_axil_arready, + output wire [S_COUNT*DATA_WIDTH-1:0] s_axil_rdata, + output wire [S_COUNT*2-1:0] s_axil_rresp, + output wire [S_COUNT-1:0] s_axil_rvalid, + input wire [S_COUNT-1:0] s_axil_rready, + + /* + * AXI lite master interfaces + */ + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axil_awaddr, + output wire [M_COUNT*3-1:0] m_axil_awprot, + output wire [M_COUNT-1:0] m_axil_awvalid, + input wire [M_COUNT-1:0] m_axil_awready, + output wire [M_COUNT*DATA_WIDTH-1:0] m_axil_wdata, + output wire [M_COUNT*STRB_WIDTH-1:0] m_axil_wstrb, + output wire [M_COUNT-1:0] m_axil_wvalid, + input wire [M_COUNT-1:0] m_axil_wready, + input wire [M_COUNT*2-1:0] m_axil_bresp, + input wire [M_COUNT-1:0] m_axil_bvalid, + output wire [M_COUNT-1:0] m_axil_bready, + output wire [M_COUNT*ADDR_WIDTH-1:0] m_axil_araddr, + output wire [M_COUNT*3-1:0] m_axil_arprot, + output wire [M_COUNT-1:0] m_axil_arvalid, + input wire [M_COUNT-1:0] m_axil_arready, + input wire [M_COUNT*DATA_WIDTH-1:0] m_axil_rdata, + input wire [M_COUNT*2-1:0] m_axil_rresp, + input wire [M_COUNT-1:0] m_axil_rvalid, + output wire [M_COUNT-1:0] m_axil_rready +); + +parameter CL_S_COUNT = $clog2(S_COUNT); +parameter CL_M_COUNT = $clog2(M_COUNT); + +// default address computation +function [M_COUNT*M_REGIONS*ADDR_WIDTH-1:0] calcBaseAddrs(input [31:0] dummy); + integer i; + reg [ADDR_WIDTH-1:0] base; + reg [ADDR_WIDTH-1:0] width; + reg [ADDR_WIDTH-1:0] size; + reg [ADDR_WIDTH-1:0] mask; + begin + calcBaseAddrs = {M_COUNT*M_REGIONS*ADDR_WIDTH{1'b0}}; + base = 0; + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + width = M_ADDR_WIDTH[i*32 +: 32]; + mask = {ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - width); + size = mask + 1; + if (width > 0) begin + if ((base & mask) != 0) begin + base = base + size - (base & mask); // align + end + calcBaseAddrs[i * ADDR_WIDTH +: ADDR_WIDTH] = base; + base = base + size; // increment + end + end + end +endfunction + +parameter M_BASE_ADDR_INT = M_BASE_ADDR ? M_BASE_ADDR : calcBaseAddrs(0); + +integer i, j; + +// check configuration +initial begin + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < $clog2(STRB_WIDTH) || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin + $error("Error: address width out of range (instance %m)"); + $finish; + end + end + + $display("Addressing configuration for axil_interconnect instance %m"); + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32]) begin + //$display("%2d (%2d): %x / %02d -- %x-%x", + // i/M_REGIONS, i%M_REGIONS, + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + // M_ADDR_WIDTH[i*32 +: 32], + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + //); + end + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + if ((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & (2**M_ADDR_WIDTH[i*32 +: 32]-1)) != 0) begin + // $display("Region not aligned:"); + // $display("%2d (%2d): %x / %2d -- %x-%x", + // i/M_REGIONS, i%M_REGIONS, + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + // M_ADDR_WIDTH[i*32 +: 32], + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + // ); + // $error("Error: address range not aligned (instance %m)"); + // $finish; + end + end + + for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin + for (j = i+1; j < M_COUNT*M_REGIONS; j = j + 1) begin + if (M_ADDR_WIDTH[i*32 +: 32] && M_ADDR_WIDTH[j*32 +: 32]) begin + if (((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32])) <= (M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])))) + && ((M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32])) <= (M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))))) begin + // $display("Overlapping regions:"); + // $display("%2d (%2d): %x / %2d -- %x-%x", + // i/M_REGIONS, i%M_REGIONS, + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH], + // M_ADDR_WIDTH[i*32 +: 32], + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), + // M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])) + // ); + // $display("%2d (%2d): %x / %2d -- %x-%x", + // j/M_REGIONS, j%M_REGIONS, + // M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH], + // M_ADDR_WIDTH[j*32 +: 32], + // M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32]), + // M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])) + // ); + // $error("Error: address ranges overlap (instance %m)"); + // $finish; + end + end + end + end +end + +localparam [2:0] + STATE_IDLE = 3'd0, + STATE_DECODE = 3'd1, + STATE_WRITE = 3'd2, + STATE_WRITE_RESP = 3'd3, + STATE_WRITE_DROP = 3'd4, + STATE_READ = 3'd5, + STATE_WAIT_IDLE = 3'd6; + +reg [2:0] state_reg = STATE_IDLE, state_next; + +reg match; + +reg [CL_M_COUNT-1:0] m_select_reg = 2'd0, m_select_next; +reg [ADDR_WIDTH-1:0] axil_addr_reg = {ADDR_WIDTH{1'b0}}, axil_addr_next; +reg axil_addr_valid_reg = 1'b0, axil_addr_valid_next; +reg [2:0] axil_prot_reg = 3'b000, axil_prot_next; +reg [DATA_WIDTH-1:0] axil_data_reg = {DATA_WIDTH{1'b0}}, axil_data_next; +reg [STRB_WIDTH-1:0] axil_wstrb_reg = {STRB_WIDTH{1'b0}}, axil_wstrb_next; +reg [1:0] axil_resp_reg = 2'b00, axil_resp_next; + +reg [S_COUNT-1:0] s_axil_awready_reg = 0, s_axil_awready_next; +reg [S_COUNT-1:0] s_axil_wready_reg = 0, s_axil_wready_next; +reg [S_COUNT-1:0] s_axil_bvalid_reg = 0, s_axil_bvalid_next; +reg [S_COUNT-1:0] s_axil_arready_reg = 0, s_axil_arready_next; +reg [S_COUNT-1:0] s_axil_rvalid_reg = 0, s_axil_rvalid_next; + +reg [M_COUNT-1:0] m_axil_awvalid_reg = 0, m_axil_awvalid_next; +reg [M_COUNT-1:0] m_axil_wvalid_reg = 0, m_axil_wvalid_next; +reg [M_COUNT-1:0] m_axil_bready_reg = 0, m_axil_bready_next; +reg [M_COUNT-1:0] m_axil_arvalid_reg = 0, m_axil_arvalid_next; +reg [M_COUNT-1:0] m_axil_rready_reg = 0, m_axil_rready_next; + +assign s_axil_awready = s_axil_awready_reg; +assign s_axil_wready = s_axil_wready_reg; +assign s_axil_bresp = {S_COUNT{axil_resp_reg}}; +assign s_axil_bvalid = s_axil_bvalid_reg; +assign s_axil_arready = s_axil_arready_reg; +assign s_axil_rdata = {S_COUNT{axil_data_reg}}; +assign s_axil_rresp = {S_COUNT{axil_resp_reg}}; +assign s_axil_rvalid = s_axil_rvalid_reg; + +assign m_axil_awaddr = {M_COUNT{axil_addr_reg}}; +assign m_axil_awprot = {M_COUNT{axil_prot_reg}}; +assign m_axil_awvalid = m_axil_awvalid_reg; +assign m_axil_wdata = {M_COUNT{axil_data_reg}}; +assign m_axil_wstrb = {M_COUNT{axil_wstrb_reg}}; +assign m_axil_wvalid = m_axil_wvalid_reg; +assign m_axil_bready = m_axil_bready_reg; +assign m_axil_araddr = {M_COUNT{axil_addr_reg}}; +assign m_axil_arprot = {M_COUNT{axil_prot_reg}}; +assign m_axil_arvalid = m_axil_arvalid_reg; +assign m_axil_rready = m_axil_rready_reg; + +// slave side mux +wire [(CL_S_COUNT > 0 ? CL_S_COUNT-1 : 0):0] s_select; + +wire [ADDR_WIDTH-1:0] current_s_axil_awaddr = s_axil_awaddr[s_select*ADDR_WIDTH +: ADDR_WIDTH]; +wire [2:0] current_s_axil_awprot = s_axil_awprot[s_select*3 +: 3]; +wire current_s_axil_awvalid = s_axil_awvalid[s_select]; +wire current_s_axil_awready = s_axil_awready[s_select]; +wire [DATA_WIDTH-1:0] current_s_axil_wdata = s_axil_wdata[s_select*DATA_WIDTH +: DATA_WIDTH]; +wire [STRB_WIDTH-1:0] current_s_axil_wstrb = s_axil_wstrb[s_select*STRB_WIDTH +: STRB_WIDTH]; +wire current_s_axil_wvalid = s_axil_wvalid[s_select]; +wire current_s_axil_wready = s_axil_wready[s_select]; +wire [1:0] current_s_axil_bresp = s_axil_bresp[s_select*2 +: 2]; +wire current_s_axil_bvalid = s_axil_bvalid[s_select]; +wire current_s_axil_bready = s_axil_bready[s_select]; +wire [ADDR_WIDTH-1:0] current_s_axil_araddr = s_axil_araddr[s_select*ADDR_WIDTH +: ADDR_WIDTH]; +wire [2:0] current_s_axil_arprot = s_axil_arprot[s_select*3 +: 3]; +wire current_s_axil_arvalid = s_axil_arvalid[s_select]; +wire current_s_axil_arready = s_axil_arready[s_select]; +wire [DATA_WIDTH-1:0] current_s_axil_rdata = s_axil_rdata[s_select*DATA_WIDTH +: DATA_WIDTH]; +wire [1:0] current_s_axil_rresp = s_axil_rresp[s_select*2 +: 2]; +wire current_s_axil_rvalid = s_axil_rvalid[s_select]; +wire current_s_axil_rready = s_axil_rready[s_select]; + +// master side mux +wire [ADDR_WIDTH-1:0] current_m_axil_awaddr = m_axil_awaddr[m_select_reg*ADDR_WIDTH +: ADDR_WIDTH]; +wire [2:0] current_m_axil_awprot = m_axil_awprot[m_select_reg*3 +: 3]; +wire current_m_axil_awvalid = m_axil_awvalid[m_select_reg]; +wire current_m_axil_awready = m_axil_awready[m_select_reg]; +wire [DATA_WIDTH-1:0] current_m_axil_wdata = m_axil_wdata[m_select_reg*DATA_WIDTH +: DATA_WIDTH]; +wire [STRB_WIDTH-1:0] current_m_axil_wstrb = m_axil_wstrb[m_select_reg*STRB_WIDTH +: STRB_WIDTH]; +wire current_m_axil_wvalid = m_axil_wvalid[m_select_reg]; +wire current_m_axil_wready = m_axil_wready[m_select_reg]; +wire [1:0] current_m_axil_bresp = m_axil_bresp[m_select_reg*2 +: 2]; +wire current_m_axil_bvalid = m_axil_bvalid[m_select_reg]; +wire current_m_axil_bready = m_axil_bready[m_select_reg]; +wire [ADDR_WIDTH-1:0] current_m_axil_araddr = m_axil_araddr[m_select_reg*ADDR_WIDTH +: ADDR_WIDTH]; +wire [2:0] current_m_axil_arprot = m_axil_arprot[m_select_reg*3 +: 3]; +wire current_m_axil_arvalid = m_axil_arvalid[m_select_reg]; +wire current_m_axil_arready = m_axil_arready[m_select_reg]; +wire [DATA_WIDTH-1:0] current_m_axil_rdata = m_axil_rdata[m_select_reg*DATA_WIDTH +: DATA_WIDTH]; +wire [1:0] current_m_axil_rresp = m_axil_rresp[m_select_reg*2 +: 2]; +wire current_m_axil_rvalid = m_axil_rvalid[m_select_reg]; +wire current_m_axil_rready = m_axil_rready[m_select_reg]; + +// arbiter instance +wire [S_COUNT*2-1:0] request; +wire [S_COUNT*2-1:0] acknowledge; +wire [S_COUNT*2-1:0] grant; +wire grant_valid; +wire [CL_S_COUNT:0] grant_encoded; + +wire read = grant_encoded[0]; +assign s_select = grant_encoded >> 1; + +arbiter #( + .PORTS(S_COUNT*2), + .ARB_TYPE_ROUND_ROBIN(1), + .ARB_BLOCK(1), + .ARB_BLOCK_ACK(1), + .ARB_LSB_HIGH_PRIORITY(1) +) +arb_inst ( + .clk(clk), + .rst(rst), + .request(request), + .acknowledge(acknowledge), + .grant(grant), + .grant_valid(grant_valid), + .grant_encoded(grant_encoded) +); + +genvar n; + +// request generation +generate +for (n = 0; n < S_COUNT; n = n + 1) begin + assign request[2*n] = s_axil_awvalid[n]; + assign request[2*n+1] = s_axil_arvalid[n]; +end +endgenerate + +// acknowledge generation +generate +for (n = 0; n < S_COUNT; n = n + 1) begin + assign acknowledge[2*n] = grant[2*n] && s_axil_bvalid[n] && s_axil_bready[n]; + assign acknowledge[2*n+1] = grant[2*n+1] && s_axil_rvalid[n] && s_axil_rready[n]; +end +endgenerate + +always @* begin + state_next = STATE_IDLE; + + match = 1'b0; + + m_select_next = m_select_reg; + axil_addr_next = axil_addr_reg; + axil_addr_valid_next = axil_addr_valid_reg; + axil_prot_next = axil_prot_reg; + axil_data_next = axil_data_reg; + axil_wstrb_next = axil_wstrb_reg; + axil_resp_next = axil_resp_reg; + + s_axil_awready_next = 0; + s_axil_wready_next = 0; + s_axil_bvalid_next = s_axil_bvalid_reg & ~s_axil_bready; + s_axil_arready_next = 0; + s_axil_rvalid_next = s_axil_rvalid_reg & ~s_axil_rready; + + m_axil_awvalid_next = m_axil_awvalid_reg & ~m_axil_awready; + m_axil_wvalid_next = m_axil_wvalid_reg & ~m_axil_wready; + m_axil_bready_next = 0; + m_axil_arvalid_next = m_axil_arvalid_reg & ~m_axil_arready; + m_axil_rready_next = 0; + + case (state_reg) + STATE_IDLE: begin + // idle state; wait for arbitration + + if (grant_valid) begin + + axil_addr_valid_next = 1'b1; + + if (read) begin + // reading + axil_addr_next = current_s_axil_araddr; + axil_prot_next = current_s_axil_arprot; + s_axil_arready_next[s_select] = 1'b1; + end else begin + // writing + axil_addr_next = current_s_axil_awaddr; + axil_prot_next = current_s_axil_awprot; + s_axil_awready_next[s_select] = 1'b1; + end + + state_next = STATE_DECODE; + end else begin + state_next = STATE_IDLE; + end + end + STATE_DECODE: begin + // decode state; determine master interface + + match = 1'b0; + for (i = 0; i < M_COUNT; i = i + 1) begin + for (j = 0; j < M_REGIONS; j = j + 1) begin + if (M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32] && (!M_SECURE[i] || !axil_prot_reg[1]) && ((read ? M_CONNECT_READ : M_CONNECT_WRITE) & (1 << (s_select+i*S_COUNT))) && (axil_addr_reg >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32]) == (M_BASE_ADDR_INT[(i*M_REGIONS+j)*ADDR_WIDTH +: ADDR_WIDTH] >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32])) begin + m_select_next = i; + match = 1'b1; + end + end + end + + if (match) begin + if (read) begin + // reading + m_axil_rready_next[m_select_next] = 1'b1; + state_next = STATE_READ; + end else begin + // writing + s_axil_wready_next[s_select] = 1'b1; + state_next = STATE_WRITE; + end + end else begin + // no match; return decode error + axil_data_next = {DATA_WIDTH{1'b0}}; + axil_resp_next = 2'b11; + if (read) begin + // reading + s_axil_rvalid_next[s_select] = 1'b1; + state_next = STATE_WAIT_IDLE; + end else begin + // writing + s_axil_wready_next[s_select] = 1'b1; + state_next = STATE_WRITE_DROP; + end + end + end + STATE_WRITE: begin + // write state; store and forward write data + s_axil_wready_next[s_select] = 1'b1; + + if (axil_addr_valid_reg) begin + m_axil_awvalid_next[m_select_reg] = 1'b1; + end + axil_addr_valid_next = 1'b0; + + if (current_s_axil_wready && current_s_axil_wvalid) begin + s_axil_wready_next[s_select] = 1'b0; + axil_data_next = current_s_axil_wdata; + axil_wstrb_next = current_s_axil_wstrb; + m_axil_wvalid_next[m_select_reg] = 1'b1; + m_axil_bready_next[m_select_reg] = 1'b1; + state_next = STATE_WRITE_RESP; + end else begin + state_next = STATE_WRITE; + end + end + STATE_WRITE_RESP: begin + // write response state; store and forward write response + m_axil_bready_next[m_select_reg] = 1'b1; + + if (current_m_axil_bready && current_m_axil_bvalid) begin + m_axil_bready_next[m_select_reg] = 1'b0; + axil_resp_next = current_m_axil_bresp; + s_axil_bvalid_next[s_select] = 1'b1; + state_next = STATE_WAIT_IDLE; + end else begin + state_next = STATE_WRITE_RESP; + end + end + STATE_WRITE_DROP: begin + // write drop state; drop write data + s_axil_wready_next[s_select] = 1'b1; + + axil_addr_valid_next = 1'b0; + + if (current_s_axil_wready && current_s_axil_wvalid) begin + s_axil_wready_next[s_select] = 1'b0; + s_axil_bvalid_next[s_select] = 1'b1; + state_next = STATE_WAIT_IDLE; + end else begin + state_next = STATE_WRITE_DROP; + end + end + STATE_READ: begin + // read state; store and forward read response + m_axil_rready_next[m_select_reg] = 1'b1; + + if (axil_addr_valid_reg) begin + m_axil_arvalid_next[m_select_reg] = 1'b1; + end + axil_addr_valid_next = 1'b0; + + if (current_m_axil_rready && current_m_axil_rvalid) begin + m_axil_rready_next[m_select_reg] = 1'b0; + axil_data_next = current_m_axil_rdata; + axil_resp_next = current_m_axil_rresp; + s_axil_rvalid_next[s_select] = 1'b1; + state_next = STATE_WAIT_IDLE; + end else begin + state_next = STATE_READ; + end + end + STATE_WAIT_IDLE: begin + // wait for idle state; wait untl grant valid is deasserted + + if (!grant_valid || acknowledge) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_WAIT_IDLE; + end + end + endcase +end + +always @(posedge clk) begin + if (rst) begin + state_reg <= STATE_IDLE; + + s_axil_awready_reg <= 0; + s_axil_wready_reg <= 0; + s_axil_bvalid_reg <= 0; + s_axil_arready_reg <= 0; + s_axil_rvalid_reg <= 0; + + m_axil_awvalid_reg <= 0; + m_axil_wvalid_reg <= 0; + m_axil_bready_reg <= 0; + m_axil_arvalid_reg <= 0; + m_axil_rready_reg <= 0; + end else begin + state_reg <= state_next; + + s_axil_awready_reg <= s_axil_awready_next; + s_axil_wready_reg <= s_axil_wready_next; + s_axil_bvalid_reg <= s_axil_bvalid_next; + s_axil_arready_reg <= s_axil_arready_next; + s_axil_rvalid_reg <= s_axil_rvalid_next; + + m_axil_awvalid_reg <= m_axil_awvalid_next; + m_axil_wvalid_reg <= m_axil_wvalid_next; + m_axil_bready_reg <= m_axil_bready_next; + m_axil_arvalid_reg <= m_axil_arvalid_next; + m_axil_rready_reg <= m_axil_rready_next; + end + + m_select_reg <= m_select_next; + axil_addr_reg <= axil_addr_next; + axil_addr_valid_reg <= axil_addr_valid_next; + axil_prot_reg <= axil_prot_next; + axil_data_reg <= axil_data_next; + axil_wstrb_reg <= axil_wstrb_next; + axil_resp_reg <= axil_resp_next; +end + +endmodule + +`resetall diff --git a/EDA-3236/rtl/axil_slave.v b/EDA-3236/rtl/axil_slave.v new file mode 100644 index 00000000..4df2fb39 --- /dev/null +++ b/EDA-3236/rtl/axil_slave.v @@ -0,0 +1,212 @@ +// start of the code + +module axil_slave # + ( + parameter integer C_S_AXI_DATA_WIDTH = 32, + parameter integer C_S_AXI_ADDR_WIDTH = 7, + parameter integer NO_OF_IN_PROBE_REGS = 4, + parameter integer NO_OF_OUT_PROBE_REGS = 4 + ) + ( + input wire S_AXI_ACLK, + input wire S_AXI_ARESETN, + + + input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + input wire [2 : 0] S_AXI_AWPROT, + input wire S_AXI_AWVALID, + output wire S_AXI_AWREADY, + input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, + input wire S_AXI_WVALID, + output wire S_AXI_WREADY, + output wire [1 : 0] S_AXI_BRESP, + output wire S_AXI_BVALID, + input wire S_AXI_BREADY, + input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + input wire [2 : 0] S_AXI_ARPROT, + input wire S_AXI_ARVALID, + output wire S_AXI_ARREADY, + output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + output wire [1 : 0] S_AXI_RRESP, + output wire S_AXI_RVALID, + input wire S_AXI_RREADY, + + output wire AXI_WREN, + output wire AXI_RDEN, + input wire [C_S_AXI_DATA_WIDTH-1:0] AXI_DAT_IN + ); + + // AXI4LITE signals + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; + reg axi_awready; + reg axi_wready; + reg [1 : 0] axi_bresp; + reg axi_bvalid; + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; + reg axi_arready; + reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; + reg [1 : 0] axi_rresp; + reg axi_rvalid; + + reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; + reg aw_en; + + integer byte_index; + + assign S_AXI_AWREADY = axi_awready; + assign S_AXI_WREADY = axi_wready; + assign S_AXI_BRESP = axi_bresp; + assign S_AXI_BVALID = axi_bvalid; + assign S_AXI_ARREADY = axi_arready; + assign S_AXI_RDATA = axi_rdata; + assign S_AXI_RRESP = axi_rresp; + assign S_AXI_RVALID = axi_rvalid; + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awready <= 1'b0; + aw_en <= 1'b1; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) + begin + axi_awready <= 1'b1; + aw_en <= 1'b0; + end + else if (S_AXI_BREADY && axi_bvalid) + begin + aw_en <= 1'b1; + axi_awready <= 1'b0; + end + else + begin + axi_awready <= 1'b0; + end + end + end + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_awaddr <= 0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) + begin + axi_awaddr <= S_AXI_AWADDR; + end + end + end + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_wready <= 1'b0; + end + else + begin + if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en ) + begin + axi_wready <= 1'b1; + end + else + begin + axi_wready <= 1'b0; + end + end + end + + assign AXI_WREN = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_bvalid <= 0; + axi_bresp <= 2'b0; + end + else + begin + if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) + begin + axi_bvalid <= 1'b1; + axi_bresp <= 2'b0; // 'OKAY' response + end // work error responses in future + else + begin + if (S_AXI_BREADY && axi_bvalid) + begin + axi_bvalid <= 1'b0; + end + end + end + end + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_arready <= 1'b0; + axi_araddr <= 32'b0; + end + else + begin + if (~axi_arready && S_AXI_ARVALID) + begin + axi_arready <= 1'b1; + axi_araddr <= S_AXI_ARADDR; + end + else + begin + axi_arready <= 1'b0; + end + end + end + + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rvalid <= 0; + axi_rresp <= 0; + end + else + begin + if (axi_arready && S_AXI_ARVALID && ~axi_rvalid) + begin + axi_rvalid <= 1'b1; + axi_rresp <= 2'b0; // 'OKAY' response + end + else if (axi_rvalid && S_AXI_RREADY) + begin + axi_rvalid <= 1'b0; + end + end + end + + assign AXI_RDEN = axi_arready & S_AXI_ARVALID & ~axi_rvalid; + + // Output register or memory read data + always @( posedge S_AXI_ACLK ) + begin + if ( S_AXI_ARESETN == 1'b0 ) + begin + axi_rdata <= 0; + end + else + begin + if (AXI_RDEN) + axi_rdata <= AXI_DAT_IN; // register read data + else + axi_rdata <= 0; + end + end + +endmodule \ No newline at end of file diff --git a/EDA-3236/rtl/bscell.sv b/EDA-3236/rtl/bscell.sv new file mode 100644 index 00000000..001d5d17 --- /dev/null +++ b/EDA-3236/rtl/bscell.sv @@ -0,0 +1,45 @@ +// start of the boundry scan cell code + +module bscell + ( + // inputs + input logic clk_i, // clock for flops (??) + input logic rst_ni, // reset (??) + input logic mode_i, // Mode + input logic enable_i, // n/a + input logic shift_dr_i, // ShiftDR + input logic capture_dr_i, // + input logic update_dr_i, // UpdateDR + input logic scan_in_i, // From last cell + input logic jtagreg_in_i, // From system pin + + // outputs + output logic scan_out_o, // To next cell + output logic jtagreg_out_o // To system logic + ); + + logic r_dataout; + logic r_datasample; + logic s_datasample_next; + + always_ff @ (negedge rst_ni, posedge clk_i) + begin + if (~rst_ni) + begin + r_datasample <= 1'b0; + r_dataout <= 1'b0; + end + else + begin + if((shift_dr_i | capture_dr_i) & enable_i) + r_datasample <= s_datasample_next; + if(update_dr_i & enable_i) + r_dataout <= r_datasample; + end + end + + assign s_datasample_next = (shift_dr_i) ? scan_in_i : jtagreg_in_i; + assign jtagreg_out_o = (mode_i) ? r_dataout : jtagreg_in_i; + assign scan_out_o = r_datasample; +// assign scan_out_o = r_dataout; +endmodule diff --git a/EDA-3236/rtl/eio_top.v b/EDA-3236/rtl/eio_top.v new file mode 100644 index 00000000..52114d04 --- /dev/null +++ b/EDA-3236/rtl/eio_top.v @@ -0,0 +1,345 @@ +////////////////////////////////////////////////////////////////////////////////// +// Company: Rapid Silicon +// Engineer: Fawad Ahmad +// +// Create Date: 11/29/2022 03:59:03 PM +// Design Name: Emulate-IO +// Module Name: eio_top +// Project Name: Soft IP Development +// Target Devices: Gemini +// Tool Versions: Raptor +// Description: This IP emulates inputs and outputs ports that can be used in FPGA design without actually consuming on-chip IO pins. +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: In progress. +// +////////////////////////////////////////////////////////////////////////////////// + +module eio_top # +( +parameter IP_TYPE = "EIO", +parameter IP_VERSION = 32'h1, +parameter IP_ID = 32'h2591655, + +// AXI-L related parameters +parameter integer C_S_AXI_DATA_WIDTH = 32, +parameter integer C_S_AXI_ADDR_WIDTH = 32, +// width of in and out probes (max 512 probes each) +parameter integer INPUT_PROBE_WIDTH = 100, +parameter integer OUTPUT_PROBE_WIDTH = 100, +// whether the in/out clocks are synced with AXI clock or not +parameter AXI_IN_CLOCKS_SYNCED = 0, +parameter AXI_OUT_CLOCKS_SYNCED = 0 +) +( +// Design clock +input wire IP_CLK, +input wire OP_CLK, + +// AXIL clock and reset +input wire S_AXI_ACLK, +input wire S_AXI_ARESETN, + +// AXIL write address channel +input wire [16-1 : 0] S_AXI_AWADDR, +input wire [2 : 0] S_AXI_AWPROT, +input wire S_AXI_AWVALID, +output wire S_AXI_AWREADY, +// AXIL write data channel +input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, +input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, +input wire S_AXI_WVALID, +output wire S_AXI_WREADY, +// AXIL write response channel +output wire [1 : 0] S_AXI_BRESP, +output wire S_AXI_BVALID, +input wire S_AXI_BREADY, +// AXIL read address channel +input wire [16-1 : 0] S_AXI_ARADDR, +input wire [2 : 0] S_AXI_ARPROT, +input wire S_AXI_ARVALID, +output wire S_AXI_ARREADY, +// AXIL read data channel +output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, +output wire [1 : 0] S_AXI_RRESP, +output wire S_AXI_RVALID, +input wire S_AXI_RREADY, + +// input and output probes +input [INPUT_PROBE_WIDTH-1 : 0] probe_in, +output [OUTPUT_PROBE_WIDTH-1 : 0] probe_out +); + +// paramters +localparam NO_OF_IN_PROBE_REGS = (INPUT_PROBE_WIDTH)/C_S_AXI_DATA_WIDTH + ((INPUT_PROBE_WIDTH % C_S_AXI_DATA_WIDTH) != 0); +localparam NO_OF_OUT_PROBE_REGS = (OUTPUT_PROBE_WIDTH)/C_S_AXI_DATA_WIDTH + ((OUTPUT_PROBE_WIDTH % C_S_AXI_DATA_WIDTH) != 0); +localparam ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1; +localparam ADDR_MSB = $clog2(NO_OF_IN_PROBE_REGS) + 2 ; //Added 2 for catering IP type, name version registers +localparam spare_input_probes = (INPUT_PROBE_WIDTH % C_S_AXI_DATA_WIDTH) == 0 ? C_S_AXI_DATA_WIDTH : INPUT_PROBE_WIDTH % C_S_AXI_DATA_WIDTH; +localparam spare_output_probes = OUTPUT_PROBE_WIDTH % C_S_AXI_DATA_WIDTH; +localparam output_probe_addr_width = $clog2(NO_OF_OUT_PROBE_REGS) ; + +// calculation for no. of registers +reg [C_S_AXI_DATA_WIDTH-1 : 0] input_probe_reg_i [NO_OF_IN_PROBE_REGS-1 : 0]; // 32/64-bit input registers +reg [C_S_AXI_DATA_WIDTH-1 : 0] input_probe_reg_o [NO_OF_IN_PROBE_REGS-1 : 0]; +reg [C_S_AXI_DATA_WIDTH-1 : 0] output_probe_reg [NO_OF_OUT_PROBE_REGS-1 : 0]; // 32/64-bit output registers +wire [INPUT_PROBE_WIDTH-1 : 0] probe_in_tmp; + +// AXIL-S interal signals +wire AXI_WREN; +wire AXI_RDEN; +reg [C_S_AXI_DATA_WIDTH-1 : 0] AXI_DAT_IN = {C_S_AXI_DATA_WIDTH{1'b0}}; +reg [C_S_AXI_DATA_WIDTH-1 : 0] CONTROL_REG; + +reg [C_S_AXI_DATA_WIDTH-1 : 0] ip_type = IP_TYPE; // 0x4 +reg [C_S_AXI_DATA_WIDTH-1 : 0] ip_version = IP_VERSION; // 0x8 +reg [C_S_AXI_DATA_WIDTH-1 : 0] ip_id = IP_ID; // 0xC +reg [output_probe_addr_width-1:0] output_probe_addr; + +integer strb_index = 0; +integer probe_index; +integer t_index; + +/********************************************************************************** +* * +* AXI-Slave instantiation * +* * +**********************************************************************************/ +axil_slave # ( + .C_S_AXI_DATA_WIDTH (C_S_AXI_DATA_WIDTH), + .C_S_AXI_ADDR_WIDTH (16), + .NO_OF_IN_PROBE_REGS (NO_OF_IN_PROBE_REGS), + .NO_OF_OUT_PROBE_REGS (NO_OF_OUT_PROBE_REGS) + ) + EIO_AXIL_INTF + ( + // AXIL clock and reset + .S_AXI_ACLK (S_AXI_ACLK), + .S_AXI_ARESETN (S_AXI_ARESETN), + + // AXIL write address channel + .S_AXI_AWADDR (S_AXI_AWADDR), + .S_AXI_AWPROT (S_AXI_AWPROT), + .S_AXI_AWVALID (S_AXI_AWVALID), + .S_AXI_AWREADY (S_AXI_AWREADY), + // AXIL write data channel + .S_AXI_WDATA (S_AXI_WDATA), + .S_AXI_WSTRB (S_AXI_WSTRB), + .S_AXI_WVALID (S_AXI_WVALID), + .S_AXI_WREADY (S_AXI_WREADY), + // AXIL write response channel + .S_AXI_BRESP (S_AXI_BRESP), + .S_AXI_BVALID (S_AXI_BVALID), + .S_AXI_BREADY (S_AXI_BREADY), + // AXIL read address channel + .S_AXI_ARADDR (S_AXI_ARADDR), + .S_AXI_ARPROT (S_AXI_ARPROT), + .S_AXI_ARVALID (S_AXI_ARVALID), + .S_AXI_ARREADY (S_AXI_ARREADY), + // AXIL read data channel + .S_AXI_RDATA (S_AXI_RDATA), + .S_AXI_RRESP (S_AXI_RRESP), + .S_AXI_RVALID (S_AXI_RVALID), + .S_AXI_RREADY (S_AXI_RREADY), + + .AXI_WREN (AXI_WREN), + .AXI_RDEN (AXI_RDEN), + .AXI_DAT_IN (AXI_DAT_IN) + ); + +/********************************************************************************** +* * +* Synchronizers * +* * +**********************************************************************************/ +// ------------ outputs ------------ +genvar odfs_index; +generate +for (odfs_index = 0 ; odfs_index < NO_OF_OUT_PROBE_REGS ; odfs_index = odfs_index+1) +begin +if (odfs_index == (NO_OF_OUT_PROBE_REGS-1) && (spare_output_probes != 0)) +begin + +ff_sync_eio # +( + .DATA_SIZE (spare_output_probes), + .SYNC (!AXI_OUT_CLOCKS_SYNCED) +) + out_probe_synchronizer +( + .destination_clk (OP_CLK), + .destination_rstn (S_AXI_ARESETN), + .async_data_in (output_probe_reg[odfs_index][spare_output_probes-1 : 0]), + .sync_data_out (probe_out[odfs_index*C_S_AXI_DATA_WIDTH +: spare_output_probes]) +); +end +else +begin +ff_sync_eio # +( + .DATA_SIZE (C_S_AXI_DATA_WIDTH), + .SYNC (!AXI_OUT_CLOCKS_SYNCED) +) + out_probe_synchronizer +( + .destination_clk (OP_CLK), + .destination_rstn (S_AXI_ARESETN), + .async_data_in (output_probe_reg[odfs_index]), + .sync_data_out (probe_out[odfs_index*C_S_AXI_DATA_WIDTH +: C_S_AXI_DATA_WIDTH]) +); +end +end +endgenerate + +// ----------- inputs ------------ +genvar idfs_index; +generate +for (idfs_index = 0 ; idfs_index < NO_OF_IN_PROBE_REGS ; idfs_index = idfs_index+1) +begin +if (idfs_index == (NO_OF_IN_PROBE_REGS-1) && (spare_input_probes != 0)) +begin +ff_sync_eio # +( + .DATA_SIZE (spare_input_probes), + .SYNC (!AXI_IN_CLOCKS_SYNCED) +) + in_probe_synchronizer +( + .destination_clk (S_AXI_ACLK), + .destination_rstn (S_AXI_ARESETN), + .async_data_in (input_probe_reg_i[idfs_index][spare_input_probes-1 : 0]), + .sync_data_out (probe_in_tmp[idfs_index*C_S_AXI_DATA_WIDTH +: spare_input_probes]) +); +end +else +begin +ff_sync_eio # +( + .DATA_SIZE (C_S_AXI_DATA_WIDTH), + .SYNC (!AXI_IN_CLOCKS_SYNCED) +) + in_probe_synchronizer +( + .destination_clk (S_AXI_ACLK), + .destination_rstn (S_AXI_ARESETN), + .async_data_in (input_probe_reg_i[idfs_index]), + .sync_data_out (probe_in_tmp[idfs_index*C_S_AXI_DATA_WIDTH +: C_S_AXI_DATA_WIDTH]) +); +end +end +endgenerate + +/********************************************************************************** +* * +* Reading registers through AXI * +* * +**********************************************************************************/ + +always @ (*) +begin + case (S_AXI_ARADDR[(ADDR_LSB+ADDR_MSB) : ADDR_LSB]) + 2'h0 : AXI_DAT_IN <= CONTROL_REG; + 2'h1 : AXI_DAT_IN <= ip_type; + 2'h2 : AXI_DAT_IN <= ip_version; + 2'h3 : AXI_DAT_IN <= ip_id; + default : begin + AXI_DAT_IN <= input_probe_reg_o[((S_AXI_ARADDR - 32'h00000010) >> ADDR_LSB)]; + end + endcase +end + +/********************************************************************************** +* * +* Writing registers through AXI * +* * +**********************************************************************************/ + + +always @( posedge S_AXI_ACLK or negedge S_AXI_ARESETN ) +begin + if (!S_AXI_ARESETN) + begin + CONTROL_REG <= 0; + end + else begin + if (AXI_WREN) + begin + case ( S_AXI_AWADDR[ADDR_LSB + ADDR_MSB:ADDR_LSB] ) + 2'h0: + for (strb_index = 0 ; strb_index <= (C_S_AXI_DATA_WIDTH/8)-1 ; strb_index = strb_index+1) + begin + if (S_AXI_WSTRB[strb_index] == 1) + CONTROL_REG[(strb_index*8) +: 8] <= S_AXI_WDATA[(strb_index*8) +: 8]; + end + 2'h1: ip_type = ip_type; + 2'h2: ip_version = ip_version; + 2'h3: ip_id = ip_id; + default : begin + output_probe_addr = (S_AXI_AWADDR - 32'h10) >> ADDR_LSB; + for (strb_index = 0 ; strb_index <= (C_S_AXI_DATA_WIDTH/8)-1 ; strb_index = strb_index+1) + begin + if (S_AXI_WSTRB[strb_index] == 1) + output_probe_reg[((output_probe_addr[output_probe_addr_width-1 : 0]))][(strb_index*8) +: 8] <= S_AXI_WDATA[(strb_index*8) +: 8]; + end end + endcase + end + end +end + + + + + +/********************************************************************************** +* * +* Sampling inputs non-stop on input-clock * +* * +**********************************************************************************/ +always @ (posedge IP_CLK or negedge S_AXI_ARESETN) +begin +if(!S_AXI_ARESETN) +begin +for (probe_index = 0 ; probe_index <= NO_OF_IN_PROBE_REGS-1 ; probe_index = probe_index+1) +input_probe_reg_i[probe_index] <= {C_S_AXI_DATA_WIDTH{1'b0}}; +end +else +begin +for (probe_index = 0 ; probe_index <= NO_OF_IN_PROBE_REGS-1 ; probe_index = probe_index+1) +begin +if (probe_index == (NO_OF_IN_PROBE_REGS-1)) + input_probe_reg_i[probe_index] <= probe_in[(probe_index*C_S_AXI_DATA_WIDTH) +: spare_input_probes]; // here +else + input_probe_reg_i[probe_index] <= probe_in[(probe_index*C_S_AXI_DATA_WIDTH) +: C_S_AXI_DATA_WIDTH]; +end +end +end + +/********************************************************************************** +* * +* Syncing and copying inputs to AXI memory mapped registers * +* * +**********************************************************************************/ +always @ (posedge S_AXI_ACLK or negedge S_AXI_ARESETN) +begin +if(!S_AXI_ARESETN) +begin +for (probe_index = 0 ; probe_index <= NO_OF_IN_PROBE_REGS-1 ; probe_index = probe_index+1) +input_probe_reg_o[probe_index] <= {C_S_AXI_DATA_WIDTH{1'b0}}; +end +else +begin +for (probe_index = 0 ; probe_index <= NO_OF_IN_PROBE_REGS-1 ; probe_index = probe_index+1) +begin +if (probe_index == (NO_OF_IN_PROBE_REGS-1)) + input_probe_reg_o[probe_index] <= probe_in_tmp[(probe_index*C_S_AXI_DATA_WIDTH) +: spare_input_probes]; // here +else + input_probe_reg_o[probe_index] <= probe_in_tmp[(probe_index*C_S_AXI_DATA_WIDTH) +: C_S_AXI_DATA_WIDTH]; +end +end +end + +endmodule + \ No newline at end of file diff --git a/EDA-3236/rtl/ff_sync.sv b/EDA-3236/rtl/ff_sync.sv new file mode 100644 index 00000000..9992a8ba --- /dev/null +++ b/EDA-3236/rtl/ff_sync.sv @@ -0,0 +1,44 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 11/04/2022 12:58:01 PM +// Design Name: +// Module Name: ff_sync +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module ff_sync( + input destination_clk, + input destination_rstn, + input async_data_in, + output reg sync_data_out + ); + + reg stage1_ff; + + always @ (posedge destination_clk or negedge destination_rstn) + begin + if(!destination_rstn) + begin + {sync_data_out, stage1_ff} <= {1'b0, 1'b0}; + end + else + begin + {sync_data_out, stage1_ff} <= {stage1_ff, async_data_in}; + end + end + +endmodule \ No newline at end of file diff --git a/EDA-3236/rtl/ff_sync_eio.v b/EDA-3236/rtl/ff_sync_eio.v new file mode 100644 index 00000000..e72dff20 --- /dev/null +++ b/EDA-3236/rtl/ff_sync_eio.v @@ -0,0 +1,59 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 11/04/2022 12:58:01 PM +// Design Name: +// Module Name: ff_sync +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module ff_sync_eio # + ( + parameter DATA_SIZE = 1, + parameter SYNC = 1 + ) + ( + input destination_clk, + input destination_rstn, + input [DATA_SIZE-1 : 0] async_data_in, + output [DATA_SIZE-1 : 0] sync_data_out + ); + + reg [DATA_SIZE-1 : 0] stage2_ff; + reg [DATA_SIZE-1 : 0] stage1_ff; + + generate + if (SYNC) + begin + // generate the sync flops + always @ (posedge destination_clk or negedge destination_rstn) + begin + if(!destination_rstn) + {stage2_ff, stage1_ff} <= {{DATA_SIZE{1'b0}}, {DATA_SIZE{1'b0}}}; + else + {stage2_ff, stage1_ff} <= {stage1_ff, async_data_in}; + end + + // assignment of output stage + assign sync_data_out = stage2_ff; + end + else + begin + assign sync_data_out = async_data_in; + end + endgenerate + +endmodule \ No newline at end of file diff --git a/EDA-3236/rtl/jtag_axi_wrap.sv b/EDA-3236/rtl/jtag_axi_wrap.sv new file mode 100644 index 00000000..86f70c99 --- /dev/null +++ b/EDA-3236/rtl/jtag_axi_wrap.sv @@ -0,0 +1,250 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. + + +//typedef enum logic [2:0] {idle, request, readdata, storedata, ack} FSMState; + +module jtag_axi_wrap # + ( + parameter integer C_S_AXI_ID_WIDTH = 4, + parameter integer C_S_AXI_DATA_WIDTH = 64, + parameter integer C_S_AXI_ADDR_WIDTH = 32, + parameter integer C_S_AXI_AWUSER_WIDTH = 4, + parameter integer C_S_AXI_ARUSER_WIDTH = 4, + parameter integer C_S_AXI_WUSER_WIDTH = 4, + parameter integer C_S_AXI_RUSER_WIDTH = 4, + parameter integer C_S_AXI_BUSER_WIDTH = 4 + ) + ( + // inputs + input logic update, + input logic [(C_S_AXI_DATA_WIDTH + C_S_AXI_ADDR_WIDTH + 2) - 1 : 0] axireg_i, // doesn't include other signals yet + input logic aclk, + input logic aresetn, + + output logic [2:0] state_axi_fsm, + output logic [(C_S_AXI_DATA_WIDTH + 2) - 1 : 0] axireg_o, + // AXI_BUS.Master jtag_master + + // write address channel + output logic [C_S_AXI_ID_WIDTH-1 : 0] aw_id, + output logic [C_S_AXI_ADDR_WIDTH-1 : 0] aw_addr, + output logic aw_lock, + output logic [3:0] aw_cache, + output logic [2:0] aw_prot, + output logic [3:0] aw_region, + output logic [C_S_AXI_AWUSER_WIDTH-1 : 0] aw_user, + output logic [3:0] aw_qos, + output logic aw_valid, + input logic aw_ready, + output logic [1:0] aw_burst, + output logic [2:0] aw_size, + output logic [7:0] aw_len, + + // read address channel + output logic [C_S_AXI_ID_WIDTH-1 : 0] ar_id, + output logic [C_S_AXI_ADDR_WIDTH-1 : 0] ar_addr, + output logic ar_lock, + output logic [3:0] ar_cache, + output logic [2:0] ar_prot, + output logic [3:0] ar_region, + output logic [C_S_AXI_ARUSER_WIDTH-1 : 0] ar_user, + output logic [3:0] ar_qos, + output logic ar_valid, + input logic ar_ready, + output logic [1:0] ar_burst, + output logic [2:0] ar_size, + output logic [7:0] ar_len, + + // write data channel + output logic [C_S_AXI_DATA_WIDTH-1 : 0] w_data, + output logic [(C_S_AXI_DATA_WIDTH/8)-1 : 0] w_strb, + output logic w_last, + output logic [C_S_AXI_WUSER_WIDTH-1 : 0] w_user, + output logic w_valid, + input logic w_ready, + + // read data channel + input logic [C_S_AXI_DATA_WIDTH-1 : 0] r_data, + input logic r_last, + input logic r_valid, + input logic [1:0] r_resp, + output logic r_ready, + input logic [C_S_AXI_RUSER_WIDTH-1 : 0] r_user, + + // write response channel + input logic [1:0] b_resp, + input logic b_valid, + output logic b_ready, + input logic [C_S_AXI_BUSER_WIDTH-1 : 0] b_user + ); + + localparam idle = 3'b000; + localparam request = 3'b001; + localparam readdata = 3'b010; + localparam storedata = 3'b011; + localparam ack = 3'b100; + + logic [2:0] state_dp, state_dn; + logic [(C_S_AXI_DATA_WIDTH + 2) - 1 : 0] axireg_n, axireg_p; + + logic axi_request; + logic loadstore; + logic [1:0] burst_type; + + assign state_axi_fsm = state_dp; + assign axi_request = axireg_i[0]; + assign loadstore = axireg_i[1]; // set for write, clear for read + + //always_comb + always@(*) + begin + state_dn = state_dp; + + axireg_n = axireg_p; + axireg_o = axireg_p; + + // default assignments + aw_id = '0; // write address ID. set to 0 + aw_addr = '0; // write address + aw_lock = '0; // write lock type (00 for normal access) + aw_cache = '0; // write attributes for caching (0000 for noncacheable and nunbufferable) + aw_prot = '0; // no idea + aw_region = '0; // optional 000 + aw_user = '0; // dunno + aw_qos = '0; // dunno + aw_valid = '0; // write address valid + + ar_id = '0; + ar_addr = '0; + ar_lock = '0; + ar_cache = '0; + ar_prot = '0; + ar_region = '0; + ar_user = '0; + ar_qos = '0; + ar_valid = '0; + + w_data = '0; + w_strb = '0; + w_last = '0; + w_user = '0; + w_valid = '0; + + // constant signals + aw_burst = 1'b0; // incremental burst // modified + ar_burst = 1'b0; // incremental burst // modified + aw_size = (C_S_AXI_DATA_WIDTH == 'd64) ? 3'b011 : 3'b010; // store 8 bytes + ar_size = (C_S_AXI_DATA_WIDTH == 'd64) ? 3'b011 : 3'b010; // read 8 bytes + aw_len = 4'b0; // single burst + ar_len = 4'b0; // single burst + + b_ready = 1'b1; // master can accept resp. information + r_ready = '0; // read ready. 1 master ready/ 0 master not ready + + case (state_dp) + idle: + begin + if (update) + state_dn = request; + end + + // Write/Read Address State + request: + begin + if (axi_request) + begin + if (loadstore) // 1: write, 0: read + begin // store data +// aw_addr = {axireg_i[33:4] , 2'b0}; + aw_addr = {axireg_i[33 : (C_S_AXI_DATA_WIDTH/32 + 1 + 2)] , {(C_S_AXI_DATA_WIDTH/32 + 1){1'b0}}}; + aw_valid = 1'b1; + + if (aw_ready) + state_dn = storedata; + else + state_dn = request; + end + else + begin // read data +// ar_addr = {axireg_i[33:4] , 2'b0}; + ar_addr = {axireg_i[33 : (C_S_AXI_DATA_WIDTH/32 + 1 + 2)] , {(C_S_AXI_DATA_WIDTH/32 + 1){1'b0}}}; + ar_valid = 1'b1; + + if (ar_ready) + state_dn = readdata; + else + state_dn = request; + end + end + else + state_dn = idle; // nothing to send or receive + end + + // Read Data State + readdata: + begin + r_ready = 1'b1; + + if (r_valid & r_last) + begin + axireg_n[C_S_AXI_DATA_WIDTH-1 : 0] = r_data; + axireg_n[(C_S_AXI_DATA_WIDTH+1):(C_S_AXI_DATA_WIDTH)] = r_resp; + state_dn = idle; + end + else + state_dn = readdata; + end + + // Write Data State + storedata: + begin + w_data = axireg_i[(C_S_AXI_DATA_WIDTH+34)-1 : 34]; + w_valid = 1'b1; + w_last = 1'b1; + w_strb = 8'hff; + + if (w_ready) + state_dn = ack; + else + state_dn = storedata; + end + + // Write Response State + ack: + begin + if (b_valid) + begin + state_dn = idle; + axireg_n[(C_S_AXI_DATA_WIDTH+1):(C_S_AXI_DATA_WIDTH)] = b_resp; + end + else + state_dn = ack; + end + + endcase // case (state_dp) + end + + always_ff @ (posedge aclk, negedge aresetn) + begin + if (~aresetn) + begin + state_dp <= idle; + axireg_p <= {{2'b0}, {C_S_AXI_DATA_WIDTH{1'b0}}}; + end + else + begin + state_dp <= state_dn; + axireg_p <= axireg_n; + end + end + + +endmodule // jtag_axi_wrap diff --git a/EDA-3236/rtl/jtag_to_axi_top.sv b/EDA-3236/rtl/jtag_to_axi_top.sv new file mode 100644 index 00000000..385c22a2 --- /dev/null +++ b/EDA-3236/rtl/jtag_to_axi_top.sv @@ -0,0 +1,521 @@ +////////////////////////////////////////////////////////////////////////////////// +// Company: Rapid Silicon +// Engineer: Fawad Ahmad +// +// Create Date: 11/02/2022 05:47:37 PM +// Design Name: JTAG-to-AXI +// Module Name: jtag_to_axi_top +// Project Name: +// Target Devices: RS Gemini devices +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +`default_nettype wire + +module jtag_to_axi_top #( + parameter integer C_S_AXI_ID_WIDTH = 4, + parameter integer C_S_AXI_DATA_WIDTH = 32, + parameter integer C_S_AXI_ADDR_WIDTH = 32, + parameter integer C_S_AXI_AWUSER_WIDTH = 0, + parameter integer C_S_AXI_ARUSER_WIDTH = 0, + parameter integer C_S_AXI_WUSER_WIDTH = 0, + parameter integer C_S_AXI_RUSER_WIDTH = 0, + parameter integer C_S_AXI_BUSER_WIDTH = 0 + ) + ( + // AXI-Master interface + input ACLK, // 50-100MHz variable + input ARESETN, + // AXI_BUS.Master axi_m_jtag, + + output logic [C_S_AXI_ID_WIDTH-1 : 0] aw_id, + output logic [C_S_AXI_ADDR_WIDTH-1 : 0] aw_addr, + output logic aw_lock, + output logic [3:0] aw_cache, + output logic [2:0] aw_prot, + output logic [3:0] aw_region, + output logic [C_S_AXI_AWUSER_WIDTH-1 : 0] aw_user, + output logic [3:0] aw_qos, + output logic aw_valid, + input logic aw_ready, + output logic [1:0] aw_burst, + output logic [2:0] aw_size, + output logic [7:0] aw_len, + + // read address channel + output logic [C_S_AXI_ID_WIDTH-1 : 0] ar_id, + output logic [C_S_AXI_ADDR_WIDTH-1 : 0] ar_addr, + output logic ar_lock, + output logic [3:0] ar_cache, + output logic [2:0] ar_prot, + output logic [3:0] ar_region, + output logic [C_S_AXI_ARUSER_WIDTH-1 : 0] ar_user, + output logic [3:0] ar_qos, + output logic ar_valid, + input logic ar_ready, + output logic [1:0] ar_burst, + output logic [2:0] ar_size, + output logic [7:0] ar_len, + + // write data channel + output logic [C_S_AXI_DATA_WIDTH-1 : 0] w_data, + output logic [(C_S_AXI_DATA_WIDTH/8)-1 : 0] w_strb, + output logic w_last, + output logic [C_S_AXI_WUSER_WIDTH-1 : 0] w_user, + output logic w_valid, + input logic w_ready, + + // read data channel + output logic [C_S_AXI_ID_WIDTH-1 : 0] r_id, + input logic [C_S_AXI_DATA_WIDTH-1 : 0] r_data, + input logic r_last, + input logic r_valid, + input logic [1:0] r_resp, + output logic r_ready, + input logic [C_S_AXI_RUSER_WIDTH-1 : 0] r_user, + + // write response channel + output logic [C_S_AXI_ID_WIDTH-1 : 0] b_id, + input logic [1:0] b_resp, + input logic b_valid, + output logic b_ready, + input logic [C_S_AXI_BUSER_WIDTH-1 : 0] b_user, + + // JTAG interface + input JTAG_TCK, // 30MHz max. + input JTAG_TMS, + input JTAG_TDI, + output reg JTAG_TDO, + input JTAG_TRST + ); + + localparam idle = 3'b000; + localparam request = 3'b001; + localparam readdata = 3'b010; + localparam storedata = 3'b011; + localparam ack = 3'b100; + + localparam REG_AXI_IN_LENGTH = C_S_AXI_DATA_WIDTH + C_S_AXI_ADDR_WIDTH + 4; + localparam REG_AXI_OUT_LENGTH = C_S_AXI_DATA_WIDTH + 2; + + // top level FSM states + typedef enum logic [2:0] {IDLE, WAIT_AND_STORE, STORE_IN_JTAG_REG, GENERATE_TRIGGER, STORE_DATA_RESP} TopFSMState; + TopFSMState top_state; + + logic [2:0] axi_state; + + // TAP controller signals for AXI registers + logic tapc_shiftdr; + logic tapc_capturedr; + logic tapc_updatedr; + logic tapc_tdo; + + // TAP controller signals for AXI registers + logic tapc_axi_in_sel; + logic tapc_axi_out_sel; + logic tapc_axi_in_cta; + logic tapc_axi_out_cta; + + // synchronized cta and update signals for AXI clock domain + logic sync_tapc_axi_in_cta; + logic sync_tapc_axi_out_cta; + + logic sync_tapc_axi_in_sel; + logic sync_tapc_axi_out_sel; + + logic sync_tapc_updatedr; + + // TAP controller inputs from AXI registers + logic tapc_axi_in_tdo; + logic tapc_axi_out_tdo; + + // AXI read data from slave + wire [(C_S_AXI_DATA_WIDTH + 2) - 1 : 0] axi_slave_dat; + wire axi_m_trans_trig; + + // parallel input/output for AXI registers + reg [REG_AXI_IN_LENGTH - 1 : 0] pi_axi_data_in; + reg [REG_AXI_OUT_LENGTH - 1 : 0] pi_axi_data_out; + wire [REG_AXI_IN_LENGTH - 1 : 0] po_axi_data_in; + wire [REG_AXI_OUT_LENGTH - 1 : 0] po_axi_data_out; + + // contents of the AXI registers + reg [REG_AXI_IN_LENGTH - 1 : 0] axi_data_in_dat; + reg [REG_AXI_OUT_LENGTH - 1 : 0] axi_data_out_dat; + + // mode selects for AXI registers + reg mode_axi_in = 1'b1; + reg mode_axi_out = 1'b1; + + // misc. + wire updatedr_falling; + wire sync_updatedr_falling; + reg [REG_AXI_OUT_LENGTH - 1 : 0] pi_axi_data_out_temp; + reg first_read_done; + + wire [1:0] burst_type; + wire [C_S_AXI_DATA_WIDTH-1 : 0] jtag_to_axi_data; + + assign burst_type = po_axi_data_in[REG_AXI_IN_LENGTH-1 : REG_AXI_IN_LENGTH-2]; + assign jtag_to_axi_data = po_axi_data_in[(C_S_AXI_DATA_WIDTH+34)-1 : 34]; + + // AXI-Master trigger gen + wire axi_m_trans_trig_edge; + reg axi_m_trans_trig_prev; + wire axi_rw; + reg [2:0] axi_state_prev; + wire axi_trans_done_detect; + reg trig; + wire axi_master_update_trigger; + + wire axi_out_read; + reg axi_out_read_prev; + wire axi_out_read_edge; + + // ---------------------------------------- assigns --------------------------------------- + // transaction trigger: generate as soon as the axi_in register is updated (to initiate the r/w transaction) + assign axi_m_trans_trig = sync_updatedr_falling & sync_tapc_axi_in_sel; + // trigger edge detector: keep track of rising edge of axi transaction trigger, the 'trig' is manual trigger generated in the "GENERATE_TRIGGER" state + assign axi_m_trans_trig_edge = ((axi_m_trans_trig_prev == 0) & (axi_m_trans_trig == 1)) | trig; + assign axi_rw = po_axi_data_in[1]; + assign axi_trans_done_detect = (axi_state == idle) & ((axi_state_prev == ack) | (axi_state_prev == readdata)); + assign axi_master_update_trigger = axi_m_trans_trig_edge & sync_tapc_axi_in_cta; + + assign axi_out_read = sync_updatedr_falling & sync_tapc_axi_out_sel; + assign axi_out_read_edge = (axi_out_read_prev == 0) & (axi_out_read == 1); + + // address selection for axi master + reg [C_S_AXI_ADDR_WIDTH - 1 : 0] axi_generated_addr; + wire [C_S_AXI_ADDR_WIDTH - 1 : 0] axi_read_address; + assign axi_read_address = ((burst_type == 2'b10) & (top_state != IDLE)) ? axi_generated_addr : po_axi_data_in[33:2]; + + // -------------------------------------- TAP instance -------------------------------------- + tap_top JTAG_TAP( + // jtag + .tms_i (JTAG_TMS), + .tck_i (JTAG_TCK), + .rst_ni (JTAG_TRST), + .td_i (JTAG_TDI), + .td_o (JTAG_TDO), + + // tap states + .shift_dr_o (tapc_shiftdr), + .update_dr_o (tapc_updatedr), + .capture_dr_o (tapc_capturedr), + + // tdo signal connected to tdi of sub modules + .scan_in_o(tapc_tdo), + + // select signals for boundary scan or mbist + .axi_data_in_sel_o (tapc_axi_in_sel), + .axi_data_out_sel_o (tapc_axi_out_sel), + + // tdi signals from sub modules + .axi_data_in_tdo (tapc_axi_in_tdo), + .axi_data_out_tdo (tapc_axi_out_tdo), + + .axi_in_cta (tapc_axi_in_cta), + .axi_out_cta (tapc_axi_out_cta), + + .updatedr_fedge(updatedr_falling) + ); + + // -------------------------------------- AXI-MASTER instance -------------------------------------- + jtag_axi_wrap # ( + .C_S_AXI_ID_WIDTH (C_S_AXI_ID_WIDTH), + .C_S_AXI_DATA_WIDTH (C_S_AXI_DATA_WIDTH), + .C_S_AXI_ADDR_WIDTH (C_S_AXI_ADDR_WIDTH), + .C_S_AXI_AWUSER_WIDTH (C_S_AXI_AWUSER_WIDTH), + .C_S_AXI_ARUSER_WIDTH (C_S_AXI_ARUSER_WIDTH), + .C_S_AXI_WUSER_WIDTH (C_S_AXI_WUSER_WIDTH), + .C_S_AXI_RUSER_WIDTH (C_S_AXI_RUSER_WIDTH), + .C_S_AXI_BUSER_WIDTH (C_S_AXI_BUSER_WIDTH) + ) + AXI_M_INTF + ( + // inputs + .update (axi_master_update_trigger), + .axireg_i ({po_axi_data_in[(C_S_AXI_DATA_WIDTH+34)-1 : 34], axi_read_address, po_axi_data_in[1:0]}), + .aclk (ACLK), + .aresetn (ARESETN), + + .state_axi_fsm (axi_state), + .axireg_o (axi_slave_dat), + // .jtag_master (axi_m_jtag) + + .aw_id (aw_id), + .aw_addr (aw_addr), + .aw_lock (aw_lock), + .aw_cache (aw_cache), + .aw_prot (aw_prot), + .aw_region (aw_region), + .aw_user (aw_user), + .aw_qos (aw_qos), + .aw_valid (aw_valid), + .aw_ready (aw_ready), + .aw_burst (aw_burst), + .aw_size (aw_size), + .aw_len (aw_len), + + // read address channel + .ar_id (ar_id), + .ar_addr (ar_addr), + .ar_lock (ar_lock), + .ar_cache (ar_cache), + .ar_prot (ar_prot), + .ar_region (ar_region), + .ar_user (ar_user), + .ar_qos (ar_qos), + .ar_valid (ar_valid), + .ar_ready (ar_ready), + .ar_burst (ar_burst), + .ar_size (ar_size), + .ar_len (ar_len), + + // write data channel + .w_data (w_data), + .w_strb (w_strb), + .w_last (w_last), + .w_user (w_user), + .w_valid (w_valid), + .w_ready (w_ready), + + // read data channel + .r_data (r_data), + .r_last (r_last), + .r_valid (r_valid), + .r_resp (r_resp), + .r_ready (r_ready), + .r_user (r_user), + + // write response channel + .b_resp (b_resp), + .b_valid (b_valid), + .b_ready (b_ready), + .b_user (b_user) + ); + + // -------------------------------------- AXI Data-in Reg -------------------------------------- + jtagreg #( + .JTAGREGSIZE(REG_AXI_IN_LENGTH), // 1 bit for r/w, 2 bits for incr burst, fixed burst and no burst + .SYNC(0) + ) + AXI_DATA_IN_REG + ( + .clk_i (JTAG_TCK), + .rst_ni (JTAG_TRST), + .enable_i (tapc_axi_in_sel), + .capture_dr_i (tapc_capturedr), + .shift_dr_i (tapc_shiftdr), + .update_dr_i (tapc_updatedr), + .jtagreg_in_i (pi_axi_data_in), + .mode_i (mode_axi_in), + .scan_in_i (tapc_tdo), + .scan_out_o (tapc_axi_in_tdo), + .jtagreg_out_o (po_axi_data_in) + ); + + // -------------------------------------- AXI Data-out Reg -------------------------------------- + jtagreg #( + .JTAGREGSIZE(REG_AXI_OUT_LENGTH), + .SYNC(0) + ) + AXI_DATA_OUT_REG + ( + .clk_i (JTAG_TCK), + .rst_ni (JTAG_TRST), + .enable_i (tapc_axi_out_sel), + .capture_dr_i (tapc_capturedr), + .shift_dr_i (tapc_shiftdr), + .update_dr_i (tapc_updatedr), + .jtagreg_in_i (pi_axi_data_out), + .mode_i (mode_axi_out), + .scan_in_i (1'b0), + .scan_out_o (tapc_axi_out_tdo), + .jtagreg_out_o (po_axi_data_out) + ); + + // -------------------------------------- Synchronizers -------------------------------------- + ff_sync axi_in_cta_synchronizer( + .destination_clk (ACLK), + .destination_rstn (ARESETN), + .async_data_in (tapc_axi_in_cta), + .sync_data_out (sync_tapc_axi_in_cta) + ); + + ff_sync axi_out_cta_synchronizer( + .destination_clk (ACLK), + .destination_rstn (ARESETN), + .async_data_in (tapc_axi_out_cta), + .sync_data_out (sync_tapc_axi_out_cta) + ); + + ff_sync axi_in_updatedr_synchronizer( + .destination_clk (ACLK), + .destination_rstn (ARESETN), + .async_data_in (updatedr_falling), + .sync_data_out (sync_updatedr_falling) + ); + + ff_sync axi_in_sel_synchronizer( + .destination_clk (ACLK), + .destination_rstn (ARESETN), + .async_data_in (tapc_axi_in_sel), + .sync_data_out (sync_tapc_axi_in_sel) + ); + + ff_sync axi_out_sel_synchronizer( + .destination_clk (ACLK), + .destination_rstn (ARESETN), + .async_data_in (tapc_axi_out_sel), + .sync_data_out (sync_tapc_axi_out_sel) + ); + + + //******************************************************************************************// + // // + // JTAG and AXI-M data sync and exchange logic // + // // + //******************************************************************************************// + + always @ (posedge ACLK or negedge ARESETN) + begin + if(!ARESETN) + begin + axi_m_trans_trig_prev <= 1'b0; + axi_state_prev <= 3'b000; + axi_out_read_prev <= 1'b0; + end + else + begin + axi_m_trans_trig_prev <= axi_m_trans_trig; + axi_state_prev <= axi_state; + axi_out_read_prev <= axi_out_read; + end + end + + // Top FSM + + always @ (posedge ACLK or negedge ARESETN) + begin + if(!ARESETN) + begin + pi_axi_data_in <= {REG_AXI_IN_LENGTH{1'b0}}; + pi_axi_data_out <= {REG_AXI_OUT_LENGTH{1'b0}}; + first_read_done <= 1'b0; + + axi_data_in_dat <= {REG_AXI_IN_LENGTH{1'b0}}; + axi_data_out_dat <= {REG_AXI_OUT_LENGTH{1'b0}}; + + axi_generated_addr <= {C_S_AXI_ADDR_WIDTH{1'b0}}; + + pi_axi_data_out_temp <= {REG_AXI_OUT_LENGTH{1'b0}}; + trig <= 0; + + top_state <= IDLE; + end + else + begin + case (top_state) + // idling, no transaction underway + IDLE: + begin + if (axi_state == request) + begin + axi_generated_addr <= po_axi_data_in[33:2]; + top_state <= WAIT_AND_STORE; + end + else + begin + top_state <= IDLE; + end + end + + // waiting for an ongoing transaction to finish + WAIT_AND_STORE: + begin + trig <= 0; + + if (!sync_tapc_axi_in_cta) // if axi-in is being accessed externally + begin + top_state <= IDLE; + end + else if (axi_trans_done_detect) // wait till the ongoing axi transaction completes + begin + top_state <= STORE_IN_JTAG_REG; + + if (!axi_rw) // if read op + pi_axi_data_out_temp <= axi_slave_dat; // store received read data and response in temp register + else // if write op + pi_axi_data_out_temp <= {{axi_slave_dat[(C_S_AXI_DATA_WIDTH + 2) - 1 : (C_S_AXI_DATA_WIDTH + 2) - 2]}, {C_S_AXI_DATA_WIDTH{1'b0}}}; // store write data and response in temp register + end + else + top_state <= WAIT_AND_STORE; + end + + // storing the read data/response when axi_out is clear to access + STORE_IN_JTAG_REG: + begin + pi_axi_data_out <= pi_axi_data_out_temp; // :mod_n2: + if(!sync_tapc_axi_in_cta | axi_rw) // if write op or axi-in is being externally accessed + begin + top_state <= IDLE; + end + // if a read op on axi-out has been made through jtag -OR- first read has not been done -OR- there is not burst mode selected +// else if((sync_tapc_axi_out_cta & axi_out_read_edge) | (first_read_done == 1'b0) | (burst_type == 2'b00 | burst_type == 2'b11)) // :mod_o1: + else if((sync_tapc_axi_out_cta & axi_out_read_edge) | (burst_type == 2'b00 | burst_type == 2'b11)) // :mod_n1: + begin + // store the temporary value from temp to axi-out register +// pi_axi_data_out <= pi_axi_data_out_temp; // :mod_o2: + top_state <= GENERATE_TRIGGER; + end + else + top_state <= STORE_IN_JTAG_REG; + end + + // forcing a trigger to start another read in case of burst + GENERATE_TRIGGER: + begin + if(!axi_rw & sync_tapc_axi_in_cta) // if read op and axi-in reg is not being accessed by JTAG + begin + if(burst_type == 3'b00 | burst_type == 3'b11) // if no burst + begin + top_state <= IDLE; + end + else if(burst_type == 3'b01) // if fixed burst + begin + trig <= 1; + top_state <= WAIT_AND_STORE; + first_read_done <= 1'b1; + end + else // if incremental burst + begin + trig <= 1; + top_state <= WAIT_AND_STORE; + axi_generated_addr <= axi_generated_addr + {{1'b1}, {(C_S_AXI_DATA_WIDTH/32 + 1){1'b0}}}; + first_read_done <= 1'b1; + end + end + else // if write op + begin + top_state <= IDLE; + end + end + + default: + begin + top_state <= IDLE; + end + endcase + end + end + + +endmodule diff --git a/EDA-3236/rtl/jtagreg.sv b/EDA-3236/rtl/jtagreg.sv new file mode 100644 index 00000000..d2f95dc6 --- /dev/null +++ b/EDA-3236/rtl/jtagreg.sv @@ -0,0 +1,104 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this 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. + +module jtagreg +#( + parameter JTAGREGSIZE = 16, + parameter SYNC = 0 +) +( + // inputs + input logic clk_i, + input logic rst_ni, // already synched + input logic enable_i, // rising edge of tck + input logic capture_dr_i, // capture&sel + input logic shift_dr_i, // shift&sel + input logic update_dr_i, // update&sel + input logic [JTAGREGSIZE-1:0] jtagreg_in_i, + input logic mode_i, + input logic scan_in_i, + + // outputs + output logic scan_out_o, + output logic [JTAGREGSIZE-1:0] jtagreg_out_o +); + + logic [JTAGREGSIZE-2:0] s_scanbit; + logic scan_in_syn; + + bscell reg_bit_last + ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .mode_i (mode_i), + .enable_i (enable_i), + .shift_dr_i (shift_dr_i), + .capture_dr_i (capture_dr_i), + .update_dr_i (update_dr_i), + .scan_in_i (scan_in_syn), + .jtagreg_in_i (jtagreg_in_i[JTAGREGSIZE-1]), + .scan_out_o (s_scanbit[0]), + .jtagreg_out_o (jtagreg_out_o[JTAGREGSIZE-1]) + ); + + generate + for (genvar i=1 ; i 32 ? (NO_OF_PROBES / 32) +((NO_OF_PROBES - $floor(NO_OF_PROBES / 32) * 32 )== 0 ? 0:1):1; + // number of 32 bit words in which probes can be divided + //localparam PROBE_BITS = 32 - int'(REM_BITS); + localparam [31:0] PROBE_BITS = 32 - REM_BITS; + //localparam WORD_CHUNK_CNTR_WIDTH = WORD_CHUNKS> 1? int'($clog2(WORD_CHUNKS)):1; + + localparam WORD_CHUNK_CNTR_WIDTH = WORD_CHUNKS> 1? ($clog2(WORD_CHUNKS)):1; + + // --------------------------------------------------------------- + // Dual Synchronizer flop + // --------------------------------------------------------------- + + localparam REG_WIDTH = 1; // Dual synchronizer width + + // --------------------------------------------------------------- + // Sampler buffer + // --------------------------------------------------------------- + + localparam BUFFER_STAGES = 4; // Buffer registers + + + // --------------------------------------------------------------- + // OCLA Memory Controller + // --------------------------------------------------------------- + + localparam SYNC_STAGES = 2; // synchronizer flops + localparam COUNTER_WIDHT = $clog2(MEM_DEPTH); // counter WIDTH + + // --------------------------------------------------------------- + // OCLA Controller + // --------------------------------------------------------------- + + localparam MEMORY_DEPTH_HALF = MEM_DEPTH/2; + localparam SAMPLE_COUNTER_WIDTH = COUNTER_WIDHT; + + // --------------------------------------------------------------- + // Trigger Control Unit + // --------------------------------------------------------------- + + localparam TRIGGER_SIGNAL_SELECT_RANGE = NO_OF_PROBES; + localparam SELECT_MUX_WIDTH = NO_OF_PROBES <= 1 ? 1 : $clog2(TRIGGER_SIGNAL_SELECT_RANGE); // mux select line WIDTH to select trigger signal + + + // --------------------------------------------------------------- + + logic sampling_en; + logic trigger_event; + logic data_wen; + logic wr_full; + logic [NO_OF_PROBES-1:0] data_accumulate; + logic [NO_OF_PROBES-1:0] read_accumulated_data; + logic mem_read; + logic mem_empty; + + + logic [AXI_DATA_WIDTH-1:0] TMTR_OUT; + logic [AXI_DATA_WIDTH-1:0] OCCR_OUT; + logic [AXI_DATA_WIDTH-1:0] TBDR_IN; + + logic [AXI_DATA_WIDTH-1:0] TSSR0_OUT; + logic [AXI_DATA_WIDTH-1:0] TSSR1_OUT; + logic [AXI_DATA_WIDTH-1:0] TSSR2_OUT; + logic [AXI_DATA_WIDTH-1:0] TSSR3_OUT; + + logic [AXI_DATA_WIDTH-1:0] TCUR0_OUT; + logic [AXI_DATA_WIDTH-1:0] TCUR1_OUT; + logic [AXI_DATA_WIDTH-1:0] TCUR2_OUT; + logic [AXI_DATA_WIDTH-1:0] TCUR3_OUT; + + logic [AXI_DATA_WIDTH-1:0] TDCR0_OUT; + logic [AXI_DATA_WIDTH-1:0] TDCR1_OUT; + logic [AXI_DATA_WIDTH-1:0] TDCR2_OUT; + logic [AXI_DATA_WIDTH-1:0] TDCR3_OUT; + + + logic [AXI_DATA_WIDTH-1:0] MASK0_OUT; + logic [AXI_DATA_WIDTH-1:0] MASK1_OUT; + logic [AXI_DATA_WIDTH-1:0] MASK2_OUT; + logic [AXI_DATA_WIDTH-1:0] MASK3_OUT; + + + + logic read_trace_mem_en; + + logic mem_empty_sync; + logic mem_valid_data; + logic reset_fifo_pntr; + logic reset_fifo_wr_pntr_sync; + logic start_process; + logic TMTR_REG_port_strt_bit_sync; + + logic sampling_done_ff; + logic done_sampling_ff_sync; + + // ---------------------------------------------------------------// + // Synchronizer flop instance for // + // for sampling done signal from sampling clock domain // + // to axi clock domain // + // ---------------------------------------------------------------// + + ddff_sync #( + .REG_WIDTH(REG_WIDTH) + ) data_available_inmem ( + .clk(S_AXI_ACLK), + .rstn(S_AXI_ARESETN), + .D(sampling_done_ff), + .Q(done_sampling_ff_sync) + ); + + // ---------------------------------------------------------------// + // Sampler buffer module instance // + // // + // // + // ---------------------------------------------------------------// + + sampler_buffer #( + .PROBE_DATA_WIDTH(NO_OF_PROBES), + .BUFFERS(BUFFER_STAGES) + ) sampler_buffer_inst ( + .sample_clk(sample_clk), + .rstn(rstn), + .probes(probes), + .sampling_en(sampling_en), + .data_wen(data_wen), + .data_accumulate(data_accumulate) + ); + + // ---------------------------------------------------------------// + // Synchronizer flop instance for // + // for memory empty signal from axi clock domain // + // to sampling clock domain // + // ---------------------------------------------------------------// + + ddff_sync #( + .REG_WIDTH(REG_WIDTH) + ) synchronizer_flop ( + .clk(sample_clk), + .rstn(rstn), + .D(mem_empty), + .Q(mem_empty_sync) + ); + + + // ---------------------------------------------------------------// + // Synchronizer flop instance for // + // for TMTR_REG register data from axi clock domain // + // to sampling clock domain // + // ---------------------------------------------------------------// + + ddff_sync #( + .REG_WIDTH(1) + ) TMTR_REG_bits_sync ( + .clk(sample_clk), + .rstn(rstn), + .D(OCCR_OUT[0]), + .Q(TMTR_REG_port_strt_bit_sync) + ); + + // ---------------------------------------------------------------// + // On chip logic analyzer controller's instance // + // // + // // + // ---------------------------------------------------------------// + + + ocla_controller #( + .SAMPLE_CNTER_WIDTH(SAMPLE_COUNTER_WIDTH), + .MEM_DPTH_HALF(MEMORY_DEPTH_HALF) + ) ocla_controller_inst ( + .sample_clk(sample_clk), + .rstn(rstn), + .trigger_event(trigger_event), + .trigger_mode(TMTR_OUT[1:0]), + .mem_full(wr_full), + .start_process(TMTR_REG_port_strt_bit_sync), + .fixnosamples_en(TMTR_OUT[4]), + //.noofsamples({'b0,TMTR_REG_port[4+:(SAMPLE_COUNTER_WIDTH>10?10:SAMPLE_COUNTER_WIDTH)]}), + .noofsamples({1'b0,TMTR_OUT[12+:(SAMPLE_COUNTER_WIDTH>10?10:SAMPLE_COUNTER_WIDTH)]}), + .sampling_done_ff(sampling_done_ff), + .mem_empty(mem_empty_sync), + .sample_again(reset_fifo_wr_pntr_sync), + .sampling_en(sampling_en) + ); + + // ---------------------------------------------------------------// + // Trigger control unit instance // + // // + // // + // ---------------------------------------------------------------// + logic start_cap; + trigger_control_unit #( + .NPROBES(NO_OF_PROBES), + .SELECT_MUX_WIDTH(SELECT_MUX_WIDTH), + .TRIGGER_SIGNAL_SELECT_RANGE(TRIGGER_SIGNAL_SELECT_RANGE) + ) trig_control_unit_inst ( + .sample_clk(sample_clk), + .rstn(rstn), + .in_signals(probes), + //.in_signals(probes), + .config_bits({TCUR3_OUT,TCUR2_OUT,TCUR1_OUT,TCUR0_OUT}), + .boolean_operator(TMTR_OUT[3:2]), + .probe_selector0(TSSR0_OUT), + .probe_selector1(TSSR1_OUT), + .probe_selector2(TSSR2_OUT), + .probe_selector3(TSSR3_OUT), + .compare_value0(TDCR0_OUT), + .compare_value1(TDCR1_OUT), + .compare_value2(TDCR2_OUT), + .compare_value3(TDCR3_OUT), + .mask0(MASK0_OUT), + .mask1(MASK1_OUT), + .mask2(MASK2_OUT), + .mask3(MASK3_OUT), + .start_cap(OCCR_OUT[0]), + .trigger_event(trigger_event) + ); + + // ---------------------------------------------------------------// + // Synchronizer flop instance for // + // for sampling done signal from axi clock domain // + // to sampling clock domain // + // ---------------------------------------------------------------// + + ddff_sync #( + .REG_WIDTH(REG_WIDTH) + ) rst_cntrl_signal_synchronizer_flop ( + .clk(sample_clk), + .rstn(rstn), + .D(reset_fifo_pntr), + .Q(reset_fifo_wr_pntr_sync) + ); + + // ---------------------------------------------------------------// + // OCLA sampling memory controller instance // + // // + // // + // ---------------------------------------------------------------// + + ocla_mem_controller #( + .DATASIZE(NO_OF_PROBES), + .ADDRSIZE(COUNTER_WIDHT), + .NOSAMPLE_WIDTH(SAMPLE_COUNTER_WIDTH), + .MEM_DEPTH(MEM_DEPTH), + .SYNC_STAGES(SYNC_STAGES) + ) ocla_mem_controller_inst ( + .rd_data(read_accumulated_data), + .rd_empty(mem_empty), + .wr_full(wr_full), + .wr_clk(sample_clk), + .rd_clk(S_AXI_ACLK), + .wr_rstn(rstn & !reset_fifo_wr_pntr_sync), + .rd_rstn(S_AXI_ARESETN & !reset_fifo_pntr), + .wr(data_wen), + .wr_data(data_accumulate), + .trigger_mode(TMTR_OUT[1:0]), + .rd(mem_read), + .nosamples(TMTR_OUT[12+:SAMPLE_COUNTER_WIDTH]), + .fixnosamples_en(TMTR_OUT[4]), + .sampling_done_ff(done_sampling_ff_sync) + ); + + // ---------------------------------------------------------------// + // stream_out_buffer instance // + // // + // // + // ---------------------------------------------------------------// + + stream_out_buffer #( + .WORD_CHUNK_COUNTER_WIDTH(WORD_CHUNK_CNTR_WIDTH), + .NUM_OFPROBES(NO_OF_PROBES), + .NUM_OF_WORD_CHUNKS(WORD_CHUNKS), + .PROBE_BITS(PROBE_BITS), + .AXI_DATA_WIDTH(AXI_DATA_WIDTH) + ) stream_out_buffer_inst ( + .S_AXI_ACLK(S_AXI_ACLK), + .S_AXI_ARESETN(S_AXI_ARESETN), + .read_accumulated_data(read_accumulated_data), + .mem_empty(mem_empty), + .read_data_en(read_trace_mem_en), + .mem_read(mem_read), + .read_ready(S_AXI_RREADY), + .read_valid(mem_valid_data), + .read_data(TBDR_IN) + ); + + + // ---------------------------------------------------------------// + // Axi Lite Slave instance // + // // + // // + // ---------------------------------------------------------------// + axi_slv_lite # ( + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .IP_ID(IP_ID), + .NO_OF_PROBES(NO_OF_PROBES), + .MEM_DEPTH(MEM_DEPTH), + .C_S_AXI_DATA_WIDTH(32), + .C_S_AXI_ADDR_WIDTH(32) + ) + axi_slv_lite_inst ( + .TBDR_IN(TBDR_IN), + .mem_valid_data(mem_valid_data), + .mem_empty(mem_empty), + .data_avaible_inmem(done_sampling_ff_sync), + .read_trace_mem_en(read_trace_mem_en), + .TMTR_OUT(TMTR_OUT), + .OCCR_OUT(OCCR_OUT), + .TSSR0_OUT(TSSR0_OUT), + .TSSR1_OUT(TSSR1_OUT), + .TSSR2_OUT(TSSR2_OUT), + .TSSR3_OUT(TSSR3_OUT), + .TCUR0_OUT(TCUR0_OUT), + .TCUR1_OUT(TCUR1_OUT), + .TCUR2_OUT(TCUR2_OUT), + .TCUR3_OUT(TCUR3_OUT), + .TDCR0_OUT(TDCR0_OUT), + .TDCR1_OUT(TDCR1_OUT), + .TDCR2_OUT(TDCR2_OUT), + .TDCR3_OUT(TDCR3_OUT), + .MASK0_OUT(MASK0_OUT), + .MASK1_OUT(MASK1_OUT), + .MASK2_OUT(MASK2_OUT), + .MASK3_OUT(MASK3_OUT), + .reset_fifo_wr_pntr(reset_fifo_pntr), + .S_AXI_ACLK(S_AXI_ACLK), + .S_AXI_ARESETN(S_AXI_ARESETN), + .S_AXI_AWADDR(S_AXI_AWADDR), + .S_AXI_AWPROT(S_AXI_AWPROT), + .S_AXI_AWVALID(S_AXI_AWVALID), + .S_AXI_AWREADY(S_AXI_AWREADY), + .S_AXI_WDATA(S_AXI_WDATA), + .S_AXI_WSTRB(S_AXI_WSTRB), + .S_AXI_WVALID(S_AXI_WVALID), + .S_AXI_WREADY(S_AXI_WREADY), + .S_AXI_BRESP(S_AXI_BRESP), + .S_AXI_BVALID(S_AXI_BVALID), + .S_AXI_BREADY(S_AXI_BREADY), + .S_AXI_ARADDR(S_AXI_ARADDR), + .S_AXI_ARPROT(S_AXI_ARPROT), + .S_AXI_ARVALID(S_AXI_ARVALID), + .S_AXI_ARREADY(S_AXI_ARREADY), + .S_AXI_RDATA(S_AXI_RDATA), + .S_AXI_RRESP(S_AXI_RRESP), + .S_AXI_RVALID(S_AXI_RVALID), + .S_AXI_RREADY(S_AXI_RREADY) + ); + + + +endmodule + + +// ***************************************************************** +// Dual Flop Synchronizer module +// +// +// ***************************************************************** + +module ddff_sync #( + parameter REG_WIDTH = 1 + ) ( + input logic clk, + input logic rstn, + input logic [REG_WIDTH-1:0] D, + output logic [REG_WIDTH-1:0] Q + ); + + localparam stages = 2; + logic [REG_WIDTH-1:0] sync[stages-1:0]; + + assign Q = sync[stages-1]; + + always @(posedge clk or negedge rstn) + begin + if (!rstn) + begin + sync[0] <= 0; + end + else + begin + sync[0] <= D; + end + end + + genvar a; + + generate + for (a = 0; a < (stages - 1); a = a + 1) + begin + always @(posedge clk or negedge rstn) + begin + if (!rstn) + begin + sync[a+1] <= 0; + end + else + begin + sync[a+1] <= sync[a]; + end + end + end + endgenerate + +endmodule + +// ***************************************************************** +// Trigger Control Unit +// +// +// ***************************************************************** +module trigger_control_unit #( + parameter NPROBES = 32, + parameter SELECT_MUX_WIDTH = 10, + parameter TRIGGER_SIGNAL_SELECT_RANGE = 32 ) ( + input logic sample_clk, + input logic rstn, + + input logic [(NPROBES)-1:0] in_signals, + //input logic [(NPROBES)-1:0] in_signals, + input logic [127:0] config_bits, // config bits from both tcur registers. + input logic [1:0] boolean_operator, + input logic [31:0]probe_selector0, + input logic [31:0]probe_selector1, + input logic [31:0]probe_selector2, + input logic [31:0]probe_selector3, + + + input logic [32-1:0] compare_value0, + input logic [32-1:0] compare_value1, + input logic [32-1:0] compare_value2, + input logic [32-1:0] compare_value3, + + input logic [32-1:0] mask0, + input logic [32-1:0] mask1, + input logic [32-1:0] mask2, + input logic [32-1:0] mask3, + + input logic start_cap, + output logic trigger_event + + ); + + logic out_trig1; + + logic [32-1:0] compare_in0; + logic [32-1:0] compare_in1; + logic [32-1:0] compare_in2; + logic [32-1:0] compare_in3; + + logic [31:0] tcur0_reg; + logic [31:0] tcur1_reg; + logic [31:0] tcur2_reg; + logic [31:0] tcur3_reg; + + logic [31:0] tssr0_reg; + logic [31:0] tssr1_reg; + logic [31:0] tssr2_reg; + logic [31:0] tssr3_reg; + + + logic [TRIGGER_SIGNAL_SELECT_RANGE-1:0] trigger_select; + assign trigger_select = in_signals[TRIGGER_SIGNAL_SELECT_RANGE-1:0]; + + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + begin + tcur0_reg <= 'b0; + tcur1_reg <= 'b0; + tcur2_reg <= 'b0; + tcur3_reg <= 'b0; + tssr0_reg <= 'b0; + tssr1_reg <= 'b0; + tssr2_reg <= 'b0; + tssr3_reg <= 'b0; + + // compare_in0 <= 'b0; + // compare_in1 <= 'b0; + // compare_in2 <= 'b0; + // compare_in3 <= 'b0; + + end + else + begin + tcur0_reg <= config_bits[31:0]; + tcur1_reg <= config_bits[63:32]; + tcur2_reg <= config_bits[95:64]; + tcur3_reg <= config_bits[127:94]; + + tssr0_reg <= probe_selector0; + tssr1_reg <= probe_selector1; + tssr2_reg <= probe_selector2; + tssr3_reg <= probe_selector3; + + /* compare_in0 <= compare_in0; + compare_in1 <= compare_in1; + compare_in2 <= compare_in2; + compare_in3 <= compare_in3; */ + + end + end + + logic in_sig0; + always @(*) + begin + case(tssr0_reg[28:24]) + 5'd0: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 1]; + 5'd1: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 2]; + 5'd2: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 3]; + 5'd3: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 4]; + 5'd4: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 5]; + 5'd5: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 6]; + 5'd6: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 7]; + 5'd7: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 8]; + 5'd8: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 9]; + 5'd9: + compare_in0 = trigger_select[tssr0_reg[9:0] +:10]; + 5'd10: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 11]; + 5'd11: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 12]; + 5'd12: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 13]; + 5'd13: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 14]; + 5'd14: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 15]; + 5'd15: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 16]; + 5'd16: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 17]; + 5'd17: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 18]; + 5'd18: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 19]; + 5'd19: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 20]; + 5'd20: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 21]; + 5'd21: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 22]; + 5'd22: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 23]; + 5'd23: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 24]; + 5'd24: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 25]; + 5'd25: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 26]; + 5'd26: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 27]; + 5'd27: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 28]; + 5'd28: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 29]; + 5'd29: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 30]; + 5'd30: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 31]; + 8'd31: + compare_in0 = trigger_select[tssr0_reg[9:0] +: 32]; + default: + compare_in0 = 32'd0; + + endcase + end + logic [32-1:0] mask0_result; + + assign mask0_result = compare_in0 & mask0; + assign in_sig0 = trigger_select[tssr0_reg[9:0]]; + + trigger_unit trig_unit_a_inst ( + .sample_clk(sample_clk), + .rstn(rstn), + .in_sig(in_sig0), + .bits_size(tssr0_reg[28:24]), + .config_bits(tcur0_reg), + .compare_in_signal(mask0_result), + .compare_value(compare_value0), + .start_cap(start_cap), + .trigger_event(out_trig1) + ); + + + logic out_trig2; + logic out_trig_bool; + + always @(*) + begin + case(tssr1_reg[28:24]) + 5'd0: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 1]; + 5'd1: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 2]; + 5'd2: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 3]; + 5'd3: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 4]; + 5'd4: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 5]; + 5'd5: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 6]; + 5'd6: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 7]; + 5'd7: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 8]; + 5'd8: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 9]; + 5'd9: + compare_in1 = trigger_select[tssr1_reg[9:0] +:10]; + 5'd10: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 11]; + 5'd11: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 12]; + 5'd12: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 13]; + 5'd13: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 14]; + 5'd14: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 15]; + 5'd15: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 16]; + 5'd16: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 17]; + 5'd17: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 18]; + 5'd18: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 19]; + 5'd19: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 20]; + 5'd20: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 21]; + 5'd21: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 22]; + 5'd22: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 23]; + 5'd23: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 24]; + 5'd24: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 25]; + 5'd25: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 26]; + 5'd26: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 27]; + 5'd27: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 28]; + 5'd28: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 29]; + 5'd29: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 30]; + 5'd30: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 31]; + 5'd31: + compare_in1 = trigger_select[tssr1_reg[9:0] +: 32]; + default: + compare_in1 = 32'd0; + + + endcase + end + + logic [32-1:0] mask1_result; + + assign mask1_result = compare_in1 & mask1; + logic in_sig1; + assign in_sig1 = trigger_select[tssr1_reg[9:0]]; + + trigger_unit trig_unit_b_inst ( + .sample_clk(sample_clk), + .rstn(rstn), + .in_sig(in_sig1), + .bits_size(tssr1_reg[28:24]), + .config_bits(tcur1_reg), + .compare_in_signal(mask1_result), + .compare_value(compare_value1), + .start_cap(start_cap), + .trigger_event(out_trig2) + ); + + + /**********************************************/ + logic in_sig3; + logic out_trig3,out_trig4; + + always @(*) + begin + case(tssr2_reg[28:24]) + 5'd0: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 1]; + 5'd1: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 2]; + 5'd2: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 3]; + 5'd3: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 4]; + 5'd4: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 5]; + 5'd5: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 6]; + 5'd6: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 7]; + 5'd7: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 8]; + 5'd8: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 9]; + 5'd9: + compare_in2 = trigger_select[tssr2_reg[9:0] +:10]; + 5'd10: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 11]; + 5'd11: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 12]; + 5'd12: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 13]; + 5'd13: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 14]; + 5'd14: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 15]; + 5'd15: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 16]; + 5'd16: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 17]; + 5'd17: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 18]; + 5'd18: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 19]; + 5'd19: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 20]; + 5'd20: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 21]; + 5'd21: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 22]; + 5'd22: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 23]; + 5'd23: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 24]; + 5'd24: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 25]; + 5'd25: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 26]; + 5'd26: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 27]; + 5'd27: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 28]; + 5'd28: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 29]; + 5'd29: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 30]; + 5'd30: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 31]; + 5'd31: + compare_in2 = trigger_select[tssr2_reg[9:0] +: 32]; + default: + compare_in2 = 32'd0; + + + endcase + end + logic in_sig2; + assign in_sig2 = trigger_select[tssr2_reg[9:0]]; + + always @(*) + begin + case(tssr3_reg[28:24]) + 5'd0: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 1]; + 5'd1: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 2]; + 5'd2: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 3]; + 5'd3: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 4]; + 5'd4: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 5]; + 5'd5: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 6]; + 5'd6: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 7]; + 5'd7: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 8]; + 5'd8: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 9]; + 5'd9: + compare_in3 = trigger_select[tssr3_reg[9:0] +:10]; + 5'd10: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 11]; + 5'd11: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 12]; + 5'd12: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 13]; + 5'd13: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 14]; + 5'd14: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 15]; + 5'd15: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 16]; + 5'd16: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 17]; + 5'd17: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 18]; + 5'd18: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 19]; + 5'd19: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 20]; + 5'd20: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 21]; + 5'd21: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 22]; + 5'd22: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 23]; + 5'd23: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 24]; + 5'd24: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 25]; + 5'd25: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 26]; + 5'd26: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 27]; + 5'd27: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 28]; + 5'd28: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 29]; + 5'd29: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 30]; + 5'd30: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 31]; + 5'd31: + compare_in3 = trigger_select[tssr3_reg[9:0] +: 32]; + default: + compare_in3 = 32'd0; + + + endcase + end + + logic [32-1:0] mask2_result; + assign mask2_result = compare_in2 & mask2; + + logic [32-1:0] mask3_result; + assign mask3_result = compare_in3 & mask3; + + assign in_sig3 = trigger_select[tcur3_reg[9:0]]; + + + trigger_unit trig_unit_c_inst ( + .sample_clk(sample_clk), + .rstn(rstn), + .in_sig(in_sig2), + .bits_size(tssr2_reg[28:24]), + .config_bits(tcur2_reg), + .compare_in_signal(mask2_result), + .compare_value(compare_value2), + .start_cap(start_cap), + .trigger_event(out_trig3) + ); + + + trigger_unit trig_unit_d_inst ( + .sample_clk(sample_clk), + .rstn(rstn), + .in_sig(in_sig3), + .bits_size(tssr3_reg[28:24]), + .config_bits(tcur3_reg), + .compare_in_signal(mask3_result), + .compare_value(compare_value3), + .start_cap(start_cap), + .trigger_event(out_trig4) + ); + + + /*********************************************/ + + boolean_comparator bool_comp ( + .in_sig1(out_trig1), + .in_sig2(out_trig2), + .in_sig3(out_trig3), + .in_sig4(out_trig4), + //.config_bits(config_bits_ff[16:15]), + .config_bits(boolean_operator), + .trigger_event(out_trig_bool) + ); + + assign trigger_event = out_trig_bool; + // assign trigger_event = config_bits_ff[0] ? out_trig_bool : (out_trig1 | out_trig2 | out_trig3 | out_trig4); + // assign trigger_event = out_trig1; + +endmodule + +// ***************************************************************** +// Boolean Compare +// +// +// ***************************************************************** +module boolean_comparator ( + + input logic in_sig1, + input logic in_sig2, + input logic in_sig3, + input logic in_sig4, + + //input logic [1:0] config_bits, + input logic [1:0] config_bits, + output logic trigger_event + ); + + logic in_sig_ff; + logic out_sig; + + assign trigger_event = out_sig; + + //always_comb begin + always @(*) + begin + case (config_bits) + 2'b00: + out_sig = in_sig1 || in_sig2 || in_sig3 || in_sig4; // Global OR + 2'b01: + out_sig = (in_sig1 & in_sig2 & in_sig3 & in_sig4) || (in_sig1 & in_sig2) || (in_sig1 & in_sig3) || (in_sig1 & in_sig4) || (in_sig2 & in_sig3) || (in_sig2 & in_sig4) || (in_sig3 & in_sig4); // Global AND + 2'b10: + out_sig = in_sig1 || in_sig2 || in_sig3 || in_sig4; // Global OR + 2'b11: + out_sig = in_sig1 ^ in_sig2 ^ in_sig3 ^ in_sig4; // Global XOR + default: + out_sig = 1'b0; // default + endcase + end + +endmodule + +// ***************************************************************** +// Trigger Unit +// +// +// ***************************************************************** +module trigger_unit ( + + input logic sample_clk, + input logic rstn, + input logic in_sig, + input logic [4:0]bits_size, + input logic [31:0] config_bits, + input logic [32-1:0] compare_in_signal, + input logic [32-1:0] compare_value, + input logic start_cap, + output logic trigger_event + + ); + + logic trigger_event_ed; + + logic trigger_event_vc; + logic trigger_event_lvl; + logic out_sig; + + dflop dff_out_sig ( + .sample_clk(sample_clk), + .rstn(rstn), + .D(out_sig), + .Q(trigger_event) + ); + + // always_comb begin + always @(*) + begin + case (config_bits[1:0]) + 2'b00: + out_sig = 1'b0; // no trigger + 2'b01: + out_sig = trigger_event_ed; // edge detect + 2'b10: + out_sig = trigger_event_lvl; // level detect + 2'b11: + out_sig = trigger_event_vc; // value compare + default: + out_sig = 1'b0; // default + endcase + end + + edge_detector ed ( + .sample_clk(sample_clk), + .rstn(rstn), + .en(config_bits[1:0] == 2'b01), + .in_sig(in_sig), + .config_bits(config_bits[3:2]), + .edge_trigger_event(trigger_event_ed) + ); + level_detect lvld ( + .sample_clk(sample_clk), + + .rstn(rstn), + .in_sig(in_sig), + .en(config_bits[1:0] == 2'b10), + .config_bits(config_bits[5:4]), + .start_cap(start_cap), + .lvl_trigger_event(trigger_event_lvl) + ); + value_compare vc ( + .sample_clk(sample_clk), + .rstn(rstn), + .en(config_bits[1:0] == 2'b11), + .bits_size(bits_size), + .in_sig(compare_in_signal), + .reg_value(compare_value), + .config_bits(config_bits[7:6]), + .vc_trigger_event(trigger_event_vc) + ); + +endmodule + +module edge_detector ( + input logic sample_clk, + input logic rstn, + input logic en, + input logic in_sig, + input logic [1:0] config_bits, + output logic edge_trigger_event + ); + + logic in_sig_ff; + logic out_sig; + + dflop dff_in_sig ( + .sample_clk(sample_clk), + .rstn(rstn), + .D(in_sig), + .Q(in_sig_ff) + ); + dflop dff_out_sig ( + .sample_clk(sample_clk), + .rstn(rstn), + .D(out_sig), + .Q(edge_trigger_event) + ); + + always_comb + begin + if (en) + begin + case (config_bits) + 2'b00: + out_sig = 1'b0; // no trigger + 2'b01: + out_sig = in_sig & !(in_sig_ff); // rising edge detect + 2'b10: + out_sig = !(in_sig) & in_sig_ff; // falling edge detect + 2'b11: + out_sig = in_sig ^ in_sig_ff; // either edge detec + default: + out_sig = 1'b0; // default + endcase + end + else + out_sig = 1'b0; + end + +endmodule + + +// ***************************************************************** +// Value Compare Module +// +// +// ***************************************************************** +module value_compare ( + input logic sample_clk, + input logic rstn, + input logic en, + input logic [4:0] bits_size, + input logic [32-1:0] in_sig, + input logic [32-1:0] reg_value, + input logic [1:0] config_bits, + output logic vc_trigger_event + ); + + logic out_sig0, out_sig1, out_sig2, out_sig3; + + // dflop dff_out_sig (.sample_clk(sample_clk),.rstn(rstn),.D(out_sig),.Q(vc_trigger_event)); + + //always_comb + always@(*) + begin + if (en) + begin + case (config_bits) + 2'b00: begin // no trigger + out_sig0 = 1'b0; out_sig1 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + + 2'b01: // equal to detect + case(bits_size) + 5'd0:begin + out_sig1 = reg_value[0] == in_sig[0];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd1:begin + out_sig1 = reg_value[0+:2] == in_sig[0+:2];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd2:begin + out_sig1 = reg_value[0+:3] == in_sig[0+:3];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd3:begin + out_sig1 = reg_value[0+:4] == in_sig[0+:4];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd4:begin + out_sig1 = reg_value[0+:5] == in_sig[0+:5];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd5:begin + out_sig1 = reg_value[0+:6] == in_sig[0+:6];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd6:begin + out_sig1 = reg_value[0+:7] == in_sig[0+:7];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd7:begin + out_sig1 = reg_value[0+:8] == in_sig[0+:8];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd8:begin + out_sig1 = reg_value[0+:9] == in_sig[0+:9];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd9:begin + out_sig1 = reg_value[0+:10] == in_sig[0+:10];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd10:begin + out_sig1 = reg_value[0+:11] == in_sig[0+:11];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd11:begin + out_sig1 = reg_value[0+:12] == in_sig[0+:12];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd12:begin + out_sig1 = reg_value[0+:13] == in_sig[0+:13];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd13:begin + out_sig1 = reg_value[0+:14] == in_sig[0+:14];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd14:begin + out_sig1 = reg_value[0+:15] == in_sig[0+:15];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd15:begin + out_sig1 = reg_value[0+:16] == in_sig[0+:16];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd16:begin + out_sig1 = reg_value[0+:17] == in_sig[0+:17];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd17:begin + out_sig1 = reg_value[0+:18] == in_sig[0+:18];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd18:begin + out_sig1 = reg_value[0+:19] == in_sig[0+:19];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd19:begin + out_sig1 = reg_value[0+:20] == in_sig[0+:20];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd20:begin + out_sig1 = reg_value[0+:21] == in_sig[0+:21];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd21:begin + out_sig1 = reg_value[0+:22] == in_sig[0+:22];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd22:begin + out_sig1 = reg_value[0+:23] == in_sig[0+:23];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd23:begin + out_sig1 = reg_value[0+:24] == in_sig[0+:24];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd24:begin + out_sig1 = reg_value[0+:25] == in_sig[0+:25];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd25:begin + out_sig1 = reg_value[0+:26] == in_sig[0+:26];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd26:begin + out_sig1 = reg_value[0+:27] == in_sig[0+:27];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd27:begin + out_sig1 = reg_value[0+:28] == in_sig[0+:28];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd28:begin + out_sig1 = reg_value[0+:29] == in_sig[0+:29];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd29:begin + out_sig1 = reg_value[0+:30] == in_sig[0+:30];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd30:begin + out_sig1 = reg_value[0+:31] == in_sig[0+:31];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + 5'd31:begin + out_sig1 = reg_value[0+:32] == in_sig[0+:32];out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0;end + default:begin + out_sig1 = 1'b0; out_sig0 = 1'b0;out_sig2 = 1'b0;out_sig3 = 1'b0; end // default + + endcase + + 2'b10: // less than detect + case(bits_size) + 5'd0: begin + out_sig2 = reg_value[0] > in_sig[0]; out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0; end + 5'd1:begin + out_sig2 = reg_value[0+:2] > in_sig[0+:2];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd2:begin + out_sig2 = reg_value[0+:3] > in_sig[0+:3];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd3:begin + out_sig2 = reg_value[0+:4] > in_sig[0+:4];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd4:begin + out_sig2 = reg_value[0+:5] > in_sig[0+:5];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd5:begin + out_sig2 = reg_value[0+:6] > in_sig[0+:6];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd6:begin + out_sig2 = reg_value[0+:7] > in_sig[0+:7];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd7:begin + out_sig2 = reg_value[0+:8] > in_sig[0+:8];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd8:begin + out_sig2 = reg_value[0+:9] > in_sig[0+:9];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd9:begin + out_sig2 = reg_value[0+:10] > in_sig[0+:10];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd10:begin + out_sig2 = reg_value[0+:11] > in_sig[0+:11];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd11:begin + out_sig2 = reg_value[0+:12] > in_sig[0+:12];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd12:begin + out_sig2 = reg_value[0+:13] > in_sig[0+:13];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd13:begin + out_sig2 = reg_value[0+:14] > in_sig[0+:14];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd14:begin + out_sig2 = reg_value[0+:15] > in_sig[0+:15];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd15:begin + out_sig2 = reg_value[0+:16] > in_sig[0+:16];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd16:begin + out_sig2 = reg_value[0+:17] > in_sig[0+:17];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd17:begin + out_sig2 = reg_value[0+:18] > in_sig[0+:18];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd18:begin + out_sig2 = reg_value[0+:19] > in_sig[0+:19];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd19:begin + out_sig2 = reg_value[0+:20] > in_sig[0+:20];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd20:begin + out_sig2 = reg_value[0+:21] > in_sig[0+:21];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd21:begin + out_sig2 = reg_value[0+:22] > in_sig[0+:22];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd22:begin + out_sig2 = reg_value[0+:23] > in_sig[0+:23];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd23:begin + out_sig2 = reg_value[0+:24] > in_sig[0+:24];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd24:begin + out_sig2 = reg_value[0+:25] > in_sig[0+:25];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd25:begin + out_sig2 = reg_value[0+:26] > in_sig[0+:26];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd26:begin + out_sig2 = reg_value[0+:27] > in_sig[0+:27];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd27:begin + out_sig2 = reg_value[0+:28] > in_sig[0+:28];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd28:begin + out_sig2 = reg_value[0+:29] > in_sig[0+:29];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd29:begin + out_sig2 = reg_value[0+:30] > in_sig[0+:30];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd30:begin + out_sig2 = reg_value[0+:31] > in_sig[0+:31];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + 5'd31:begin + out_sig2 = reg_value[0+:32] > in_sig[0+:32];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0;end + default:begin + out_sig2 = 1'b0; out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig3 = 1'b0; end// default + endcase + + 2'b11: // greater than detect + + case(bits_size) + 5'd0: begin + out_sig3 = reg_value[0] < in_sig[0]; out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0; end + 5'd1:begin + out_sig3 = reg_value[0+:2] < in_sig[0+:2];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd2:begin + out_sig3 = reg_value[0+:3] < in_sig[0+:3];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd3:begin + out_sig3 = reg_value[0+:4] < in_sig[0+:4];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd4:begin + out_sig3 = reg_value[0+:5] < in_sig[0+:5];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd5:begin + out_sig3 = reg_value[0+:6] < in_sig[0+:6];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd6:begin + out_sig3 = reg_value[0+:7] < in_sig[0+:7];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd7:begin + out_sig3 = reg_value[0+:8] < in_sig[0+:8];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd8:begin + out_sig3 = reg_value[0+:9] < in_sig[0+:9];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd9:begin + out_sig3 = reg_value[0+:10] < in_sig[0+:10];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd10:begin + out_sig3 = reg_value[0+:11] < in_sig[0+:11];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd11:begin + out_sig3 = reg_value[0+:12] < in_sig[0+:12];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd12:begin + out_sig3 = reg_value[0+:13] < in_sig[0+:13];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd13:begin + out_sig3 = reg_value[0+:14] < in_sig[0+:14];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd14:begin + out_sig3 = reg_value[0+:15] < in_sig[0+:15];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd15:begin + out_sig3 = reg_value[0+:16] < in_sig[0+:16];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd16:begin + out_sig3 = reg_value[0+:17] < in_sig[0+:17];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd17:begin + out_sig3 = reg_value[0+:18] < in_sig[0+:18];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd18:begin + out_sig3 = reg_value[0+:19] < in_sig[0+:19];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd19:begin + out_sig3 = reg_value[0+:20] < in_sig[0+:20];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd20:begin + out_sig3 = reg_value[0+:21] < in_sig[0+:21];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd21:begin + out_sig3 = reg_value[0+:22] < in_sig[0+:22];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd22:begin + out_sig3 = reg_value[0+:23] < in_sig[0+:23];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd23:begin + out_sig3 = reg_value[0+:24] < in_sig[0+:24];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd24:begin + out_sig3 = reg_value[0+:25] < in_sig[0+:25];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd25:begin + out_sig3 = reg_value[0+:26] < in_sig[0+:26];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd26:begin + out_sig3 = reg_value[0+:27] < in_sig[0+:27];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd27:begin + out_sig3 = reg_value[0+:28] < in_sig[0+:28];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd28:begin + out_sig3 = reg_value[0+:29] < in_sig[0+:29];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd29:begin + out_sig3 = reg_value[0+:30] < in_sig[0+:30];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd30:begin + out_sig3 = reg_value[0+:31] < in_sig[0+:31];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + 5'd31:begin + out_sig3 = reg_value[0+:32] < in_sig[0+:32];out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0;end + default:begin + out_sig3 = 1'b0; out_sig0 = 1'b0;out_sig1 = 1'b0;out_sig2 = 1'b0; end// default + endcase + default: + begin + out_sig3 = 1'b0; + out_sig0 = 1'b0; + out_sig1 = 1'b0; + out_sig2 = 1'b0; + end // default + endcase + end + else + begin + out_sig0 = 1'b0; + out_sig1 = 1'b0; + out_sig2 = 1'b0; + + out_sig3 = 1'b0; + + end + end + + + + lvl2pulse level2pulse ( + .sample_clk(sample_clk), + .rstn(rstn), + //.in_sig (out_sig0 | out_sig1 | out_sig2 | out_sig3), + .in_sig (out_sig0), + .out_sig(vc_trigger_event) + ); + +endmodule + +// ***************************************************************** +// Level Detector +// +// +// ***************************************************************** +module level_detect ( + input logic sample_clk, + input logic rstn, + input logic en, + input logic in_sig, + input logic [1:0]config_bits, + input logic start_cap, + output logic lvl_trigger_event + ); + + logic in_sig_ff; + logic out_sig; + + //dflop dff_out_sig (.sample_clk(sample_clk),.rstn(rstn),.D(out_sig),.Q(trigger_event)); + always_comb + begin + if (en & start_cap) + begin + case (config_bits) + 2'b00: + out_sig = !in_sig; // low level + 2'b01: + out_sig = in_sig; // high level + default: + out_sig = 1'b0; // default + endcase + end + else + out_sig = 1'b0; + end + + lvl2pulse level2pulse ( + .sample_clk(sample_clk), + .rstn(rstn), + .in_sig (out_sig), + .start_cap(start_cap), + .out_sig(lvl_trigger_event) + ); +endmodule + +// ***************************************************************** +// DFF +// +// +// ***************************************************************** +module dflop( + input logic sample_clk, + input logic rstn, + input logic D, + output logic Q + ); + + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + Q <= 1'b0; + else + Q <= D; + end +endmodule + +// ***************************************************************** +// Level to Pulse +// +// +// ***************************************************************** +module lvl2pulse ( + input logic sample_clk, + input logic rstn, + input logic in_sig, + input logic start_cap, + output logic out_sig + ); + logic r1, r2, r3; + + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + begin + r1 <= 1'b0; + r2 <= 1'b0; + r3 <= 1'b0; + + end + else + begin + r1 <= in_sig; // first reg in synchronizer + r2 <= r1; // second reg in synchronizer, output is in sync! + r3 <= r2; // remembers previous state of button + end + end + // rising edge = old value is 0, new value is 1 + // assign out_sig = ~r3 & r2; + assign out_sig = r2; +endmodule + +// ***************************************************************** +// AXI Slave Interface +// +// +// ***************************************************************** + +module axi_slv_lite #( + // Users to add parameters here + + // User parameters ends + // Do not modify the parameters beyond this line + + // IP Type parameters + + parameter IP_TYPE = "ocla", + parameter IP_VERSION = 32'h1, + parameter IP_ID = 32'h3881734, + parameter NO_OF_PROBES = 32'd32, + parameter MEM_DEPTH =32, + + // WIDTH of S_AXI data bus + parameter integer C_S_AXI_DATA_WIDTH = 32, + // WIDTH of S_AXI address bus + parameter integer C_S_AXI_ADDR_WIDTH = 32 + ) ( + // Users to add ports here + input wire [C_S_AXI_DATA_WIDTH-1:0] TBDR_IN, + input wire mem_valid_data, + input wire mem_empty, + input wire data_avaible_inmem, + output wire read_trace_mem_en, + + output wire [C_S_AXI_DATA_WIDTH-1:0] TMTR_OUT, + + output wire [C_S_AXI_DATA_WIDTH-1:0] OCCR_OUT, + + output wire [C_S_AXI_DATA_WIDTH-1:0] TSSR0_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TSSR1_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TSSR2_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TSSR3_OUT, + + output wire [C_S_AXI_DATA_WIDTH-1:0] TCUR0_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TCUR1_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TCUR2_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TCUR3_OUT, + + output wire [C_S_AXI_DATA_WIDTH-1:0] TDCR0_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TDCR1_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TDCR2_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] TDCR3_OUT, + + + output wire [C_S_AXI_DATA_WIDTH-1:0] MASK0_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] MASK1_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] MASK2_OUT, + output wire [C_S_AXI_DATA_WIDTH-1:0] MASK3_OUT, + + output wire reset_fifo_wr_pntr, + + + // User ports ends + // Do not modify the ports beyond this line + + // Global Clock Signal + input wire S_AXI_ACLK, + // Global Reset Signal. This Signal is Active LOW + input wire S_AXI_ARESETN, + // Write address (issued by master, acceped by Slave) + input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, + // Write channel Protection type. This signal indicates the + // privilege and security level of the transaction, and whether + // the transaction is a data access or an instruction access. + input wire [2 : 0] S_AXI_AWPROT, + // Write address valid. This signal indicates that the master signaling + // valid write address and control information. + input wire S_AXI_AWVALID, + // Write address ready. This signal indicates that the slave is ready + // to accept an address and associated control signals. + output wire S_AXI_AWREADY, + // Write data (issued by master, acceped by Slave) + input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, + // Write strobes. This signal indicates which byte lanes hold + // valid data. There is one write strobe bit for each eight + // bits of the write data bus. + input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, + // Write valid. This signal indicates that valid write + // data and strobes are available. + input wire S_AXI_WVALID, + // Write ready. This signal indicates that the slave + // can accept the write data. + output wire S_AXI_WREADY, + // Write response. This signal indicates the status + // of the write transaction. + output wire [1 : 0] S_AXI_BRESP, + // Write response valid. This signal indicates that the channel + // is signaling a valid write response. + output wire S_AXI_BVALID, + // Response ready. This signal indicates that the master + // can accept a write response. + input wire S_AXI_BREADY, + // Read address (issued by master, acceped by Slave) + input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR, + // Protection type. This signal indicates the privilege + // and security level of the transaction, and whether the + // transaction is a data access or an instruction access. + input wire [2 : 0] S_AXI_ARPROT, + // Read address valid. This signal indicates that the channel + // is signaling valid read address and control information. + input wire S_AXI_ARVALID, + // Read address ready. This signal indicates that the slave is + // ready to accept an address and associated control signals. + output wire S_AXI_ARREADY, + // Read data (issued by slave) + output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA, + // Read response. This signal indicates the status of the + // read transfer. + output wire [1 : 0] S_AXI_RRESP, + // Read valid. This signal indicates that the channel is + // signaling the required read data. + output wire S_AXI_RVALID, + // Read ready. This signal indicates that the master can + // accept the read data and response information. + input wire S_AXI_RREADY + ); + + typedef enum logic [5:0] {IP_TYPE_REG_ADDR, IP_VERSION_REG_ADDR, IP_ID_REG_ADDR, RESERVED0,RESERVED1, + UDIP0_ADDR, UDIP1_ADDR, UDIP2_ADDR, OCSR_REG_ADDR,TMTR_REG_ADDR, + TBDR_ADDR, OCCR_REG_ADDR, TSSR0_REG_ADDR, TCUR0_REG_ADDR, TDCR0_REG_ADDR, MASK0_REG_ADDR, + TSSR1_REG_ADDR=24, TCUR1_REG_ADDR, TDCR1_REG_ADDR,MASK1_REG_ADDR, TSSR2_REG_ADDR=36, TCUR2_REG_ADDR, + TDCR2_REG_ADDR, MASK2_REG_ADDR, TSSR3_REG_ADDR=48, TCUR3_REG_ADDR, TDCR3_REG_ADDR, MASK3_REG_ADDR} Config_Registers_Addr; + + // AXI4LITE signals + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; + reg axi_awready; + reg axi_wready; + reg [1 : 0] axi_bresp; + reg axi_bvalid; + reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr; + reg axi_arready; + reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata; + reg [1 : 0] axi_rresp; + reg axi_rvalid; + + // Example-specific design signals + // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH + // ADDR_LSB is used for addressing 32/64 bit registers/memories + // ADDR_LSB = 2 for 32 bits (n downto 2) + // ADDR_LSB = 3 for 64 bits (n downto 3) + localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH / 32) + 1; + localparam integer OPT_MEM_ADDR_BITS = 5; + //---------------------------------------------- + //-- Signals for user logic register space example + //------------------------------------------------ + //-- Number of Slave Registers 4 + + reg [C_S_AXI_DATA_WIDTH-1:0] IP_TYPE_REG; // offset = 0x00 : Access "RO" : IP Type "ocla" + reg [C_S_AXI_DATA_WIDTH-1:0] IP_VERSION_REG; // offset = 0x04 : Access "RO" : IP Version "0x00000001" + reg [C_S_AXI_DATA_WIDTH-1:0] IP_ID_REG; // offset = 0x08 : Access "RO" : IP ID generated by IP configurator + reg [C_S_AXI_DATA_WIDTH-1:0] OCSR_REG; // offset = 0x0C : Access "RO" : OCLA Status Register + reg [C_S_AXI_DATA_WIDTH-1:0] UIDP0_REG; // offset = 0x0C : Access "RO" : OCLA Status Register + reg [C_S_AXI_DATA_WIDTH-1:0] UIDP1_REG; // offset = 0x0C : Access "RO" : OCLA Status Register + reg [C_S_AXI_DATA_WIDTH-1:0] UIDP2_REG; // offset = 0x0C : Access "RO" : OCLA Status Register + + reg [C_S_AXI_DATA_WIDTH-1:0] TMTR_REG; // offset = 0x10 : Access "RW" : Trigger Mode Type Register + //reg [C_S_AXI_DATA_WIDTH-1:0] TBDR; // offset = 0x14 : Access "RO" : Trace Buffer Data Register + reg [C_S_AXI_DATA_WIDTH-1:0] OCCR_REG; // offset = 0x18 : Access "RW" : OCLA Controll Register + + //------Trigger Source Selection Registers-----------// + + reg [C_S_AXI_DATA_WIDTH-1:0] TSSR0_REG; // offset = 0x1C : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TSSR1_REG; // offset = 0x20 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TSSR2_REG; // offset = 0x24 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TSSR3_REG; // offset = 0x28 : Access "RW" + + //------Trigger Controll Unit Registers-----------// + + reg [C_S_AXI_DATA_WIDTH-1:0] TCUR0_REG; // offset = 0x2C : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TCUR1_REG; // offset = 0x30 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TCUR2_REG; // offset = 0x34 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TCUR3_REG; // offset = 0x38 : Access "RW" + + //------Trigger Data Compare Registers-----------// + + reg [C_S_AXI_DATA_WIDTH-1:0] TDCR0_REG; // offset = 0x3C : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TDCR1_REG; // offset = 0x40 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TDCR2_REG; // offset = 0x44 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] TDCR3_REG; // offset = 0x48 : Access "RW" + + + reg [C_S_AXI_DATA_WIDTH-1:0] MASK0_REG; // offset = 0x3C : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] MASK1_REG; // offset = 0x40 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] MASK2_REG; // offset = 0x44 : Access "RW" + reg [C_S_AXI_DATA_WIDTH-1:0] MASK3_REG; // offset = 0x48 : Access "RW" + + + wire slv_reg_rden; + wire slv_reg_wren; + reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out; + integer byte_index; + reg aw_en; + + + // I/O Connections assignments + + assign S_AXI_AWREADY = axi_awready; + assign S_AXI_WREADY = axi_wready; + assign S_AXI_BRESP = axi_bresp; + assign S_AXI_BVALID = axi_bvalid; + assign S_AXI_ARREADY = axi_arready; + assign S_AXI_RDATA = axi_rdata; + assign S_AXI_RRESP = axi_rresp; + assign S_AXI_RVALID = axi_rvalid; + + assign TMTR_OUT = TMTR_REG; + + assign OCCR_OUT = OCCR_REG; + + assign TSSR0_OUT = TSSR0_REG; + assign TSSR1_OUT = TSSR1_REG; + assign TSSR2_OUT = TSSR2_REG; + assign TSSR3_OUT = TSSR3_REG; + + assign TCUR0_OUT = TCUR0_REG; + assign TCUR1_OUT = TCUR1_REG; + assign TCUR2_OUT = TCUR2_REG; + assign TCUR3_OUT = TCUR3_REG; + + assign TDCR0_OUT = TDCR0_REG; + assign TDCR1_OUT = TDCR1_REG; + assign TDCR2_OUT = TDCR2_REG; + assign TDCR3_OUT = TDCR3_REG; + + + assign MASK0_OUT = MASK0_REG; + assign MASK1_OUT = MASK1_REG; + assign MASK2_OUT = MASK2_REG; + assign MASK3_OUT = MASK3_REG; + + assign reset_fifo_wr_pntr = axi_bvalid; + + initial + begin + UIDP0_REG = MEM_DEPTH; + UIDP1_REG = NO_OF_PROBES; + IP_TYPE_REG = IP_TYPE; + IP_VERSION_REG = IP_VERSION; + IP_ID_REG = IP_ID; + end + + // Implement axi_awready generation + // axi_awready is asserted for one S_AXI_ACLK clock cycle when both + // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is + // de-asserted when reset is low. + + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + axi_awready <= 1'b0; + aw_en <= 1'b1; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) + begin + // slave is ready to accept write address when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_awready <= 1'b1; + aw_en <= 1'b0; + end + else if (S_AXI_BREADY && axi_bvalid) + begin + aw_en <= 1'b1; + axi_awready <= 1'b0; + end + else + begin + axi_awready <= 1'b0; + end + end + end + + // Implement axi_awaddr latching + // This process is used to latch the address when both + // S_AXI_AWVALID and S_AXI_WVALID are valid. + + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + axi_awaddr <= 0; + end + else + begin + if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en) + begin + // Write Address latching + axi_awaddr <= S_AXI_AWADDR; + end + end + end + + // Implement axi_wready generation + // axi_wready is asserted for one S_AXI_ACLK clock cycle when both + // S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is + // de-asserted when reset is low. + + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + axi_wready <= 1'b0; + end + else + begin + if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en) + begin + // slave is ready to accept write data when + // there is a valid write address and write data + // on the write address and data bus. This design + // expects no outstanding transactions. + axi_wready <= 1'b1; + end + else + begin + axi_wready <= 1'b0; + end + end + end + + + assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID; + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + OCSR_REG <= 0; + end + else + begin + if(reset_fifo_wr_pntr || mem_empty ) + OCSR_REG <= {3'd0,5'd3,23'd0,1'b0}; + else + OCSR_REG <= {3'd0,5'd3,23'd0,data_avaible_inmem}; + end + end + + // Implement memory mapped register select and write logic generation + // The write data is accepted and written to memory mapped registers when + // axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to + // select byte enables of slave registers while writing. + // These registers are cleared when reset (active low) is applied. + // Slave register write enable is asserted when valid address and data are available + // and the slave is ready to accept the write address and write data. + + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + + TMTR_REG <= 0; + OCCR_REG <= 0; + + TSSR0_REG <= 0; + TSSR1_REG <= 0; + TSSR2_REG <= 0; + TSSR3_REG <= 0; + + TCUR0_REG <= 0; + TCUR1_REG <= 0; + TCUR2_REG <= 0; + TCUR3_REG <= 0; + + TDCR0_REG <= 0; + TDCR1_REG <= 0; + TDCR2_REG <= 0; + TDCR3_REG <= 0; + + MASK0_REG <= 32'hFFFFFFFF; + MASK1_REG <= 32'hFFFFFFFF; + MASK2_REG <= 32'hFFFFFFFF; + MASK3_REG <= 32'hFFFFFFFF; + + + end + else + begin + if (slv_reg_wren) + begin + case (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]) + + TMTR_REG_ADDR: + for (byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1;byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TMTR_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + OCCR_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + OCCR_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TSSR0_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TSSR0_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TCUR0_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TCUR0_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TDCR0_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TDCR0_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + + MASK0_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + MASK0_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TSSR1_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TSSR1_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TCUR1_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TCUR1_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TDCR1_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TDCR1_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + MASK1_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + MASK1_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TSSR2_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TSSR2_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TCUR2_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TCUR2_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TDCR2_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TDCR2_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + MASK2_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + MASK2_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TSSR3_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TSSR3_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TCUR3_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TCUR3_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + TDCR3_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + TDCR3_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + MASK3_REG_ADDR: + for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 ) + if ( S_AXI_WSTRB[byte_index] == 1 ) + begin + MASK3_REG[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8]; + end + + default: + begin + TMTR_REG <= TMTR_REG; + OCCR_REG <= OCCR_REG; + + TSSR0_REG <= TSSR0_REG; + TSSR1_REG <= TSSR1_REG; + TSSR2_REG <= TSSR2_REG; + TSSR3_REG <= TSSR3_REG; + + TCUR0_REG <= TCUR0_REG; + TCUR1_REG <= TCUR1_REG; + TCUR2_REG <= TCUR2_REG; + TCUR3_REG <= TCUR3_REG; + + TDCR0_REG <= TDCR0_REG; + TDCR1_REG <= TDCR1_REG; + TDCR2_REG <= TDCR2_REG; + TDCR3_REG <= TDCR3_REG; + + MASK0_REG <= MASK0_REG; + MASK1_REG <= MASK1_REG; + MASK2_REG <= MASK2_REG; + MASK3_REG <= MASK3_REG; + + end + endcase + end + else + begin + OCCR_REG[0] <= !OCSR_REG[0]? OCCR_REG[0]:1'b0; + end + ////////////////////// + // ADD LOGIC HERE + ////////////////////// + end + end + + // Implement write response logic generation + // The write response and response valid signals are asserted by the slave + // when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. + // This marks the acceptance of address and indicates the status of + // write transaction. + + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + axi_bvalid <= 0; + axi_bresp <= 2'b0; + end + else + begin + if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) + begin + // indicates a valid write response is available + axi_bvalid <= 1'b1; + axi_bresp <= 2'b0; // 'OKAY' response + end // work error responses in future + else + begin + if (S_AXI_BREADY && axi_bvalid) + //check if bready is asserted while bvalid is high) + //(there is a possibility that bready is always asserted high) + begin + axi_bvalid <= 1'b0; + end + end + end + end + + reg read_trace_mem_en_ff; + assign read_trace_mem_en = (S_AXI_ARADDR[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] == TBDR_ADDR) && S_AXI_ARVALID; + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + read_trace_mem_en_ff <= 0; + end + else + begin + if(~read_trace_mem_en_ff && ~mem_valid_data) + read_trace_mem_en_ff = read_trace_mem_en ; + else if (axi_rvalid) + read_trace_mem_en_ff = 1'b0; + end + end + + // Implement axi_arready generation + // axi_arready is asserted for one S_AXI_ACLK clock cycle when + // S_AXI_ARVALID is asserted. axi_awready is + // de-asserted when reset (active low) is asserted. + // The read address is also latched when S_AXI_ARVALID is + // asserted. axi_araddr is reset to zero on reset assertion. + + + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + axi_arready <= 1'b0; + axi_araddr <= 32'b0; + end + else + begin + // if (~axi_arready && S_AXI_ARVALID && ((read_trace_mem_en) ? mem_valid_data || mem_empty: 1)) begin + if ((~axi_arready && S_AXI_ARVALID) || read_trace_mem_en_ff) + begin + // indicates that the slave has acceped the valid read address + axi_arready <= 1'b1; + // Read address latching + axi_araddr <= S_AXI_ARADDR; + end + else + begin + axi_arready <= 1'b0; + end + end + end + reg mem_empty_ff; + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + mem_empty_ff <= 1'b0; + end + else + begin + mem_empty_ff <= mem_empty; + end + + end + + + + // Implement axi_arvalid generation + // axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both + // S_AXI_ARVALID and axi_arready are asserted. The slave registers + // data are available on the axi_rdata bus at this instance. The + // assertion of axi_rvalid marks the validity of read data on the + // bus and axi_rresp indicates the status of read transaction.axi_rvalid + // is deasserted on reset (active low). axi_rresp and axi_rdata are + // cleared to zero on reset (active low). + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + axi_rvalid <= 0; + axi_rresp <= 0; + end + else + begin + // if (axi_arready && S_AXI_ARVALID && ~axi_rvalid && ((read_trace_mem_en)? mem_valid_data || mem_empty:1)) begin + if (axi_arready && ~axi_rvalid && ((read_trace_mem_en_ff)? mem_valid_data || mem_empty_ff :1)) + begin + // Valid read data is available at the read data bus + axi_rvalid <= 1'b1; + axi_rresp <= 2'b0; // 'OKAY' response + end + else if (axi_rvalid && S_AXI_RREADY) + begin + // Read data is accepted by the master + axi_rvalid <= 1'b0; + end + else + begin + axi_rvalid <= 1'b0; + end + end + end + + // Implement memory mapped register select and read logic generation + // Slave register read enable is asserted when valid address is available + // and the slave is ready to accept the read address. + assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid || mem_valid_data; + + + always @(*) + begin + // Address decoding for reading registers + case (axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]) + + IP_TYPE_REG_ADDR : + reg_data_out = IP_TYPE_REG; + IP_VERSION_REG_ADDR : + reg_data_out = IP_VERSION_REG; + IP_ID_REG_ADDR : + reg_data_out = IP_ID_REG; + UDIP0_ADDR : + reg_data_out = UIDP0_REG; + UDIP1_ADDR : + reg_data_out = UIDP1_REG; + OCSR_REG_ADDR : + reg_data_out = OCSR_REG; + TMTR_REG_ADDR : + reg_data_out = TMTR_REG; + TBDR_ADDR : + reg_data_out = TBDR_IN; + OCCR_REG_ADDR : + reg_data_out = OCCR_REG; + TSSR0_REG_ADDR : + reg_data_out = TSSR0_REG; + TCUR0_REG_ADDR : + reg_data_out = TCUR0_REG; + TDCR0_REG_ADDR : + reg_data_out = TDCR0_REG; + MASK0_REG_ADDR : + reg_data_out = MASK0_REG; + TSSR1_REG_ADDR : + reg_data_out = TSSR1_REG; + TCUR1_REG_ADDR : + reg_data_out = TCUR1_REG; + TDCR1_REG_ADDR : + reg_data_out = TDCR1_REG; + MASK1_REG_ADDR : + reg_data_out = MASK1_REG; + TSSR2_REG_ADDR : + reg_data_out = TSSR2_REG; + TCUR2_REG_ADDR : + reg_data_out = TCUR2_REG; + TDCR2_REG_ADDR : + reg_data_out = TDCR2_REG; + MASK2_REG_ADDR : + reg_data_out = MASK2_REG; + TSSR3_REG_ADDR : + reg_data_out = TSSR3_REG; + TCUR3_REG_ADDR : + reg_data_out = TCUR3_REG; + TDCR3_REG_ADDR : + reg_data_out = TDCR3_REG; + MASK3_REG_ADDR : + reg_data_out = MASK3_REG; + default : + reg_data_out = 0; + endcase + end + + + // Output register or memory read data + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (S_AXI_ARESETN == 1'b0) + begin + axi_rdata <= 0; + end + else + begin + // When there is a valid read address (S_AXI_ARVALID) with + // acceptance of read address by the slave (axi_arready), + // output the read dada + if (slv_reg_rden) + begin + axi_rdata <= reg_data_out; // register read data + end + end + end + + +endmodule + +// ***************************************************************** +// OCLA Memory Controller +// +// +// ***************************************************************** + + +module ocla_mem_controller #( + parameter DATASIZE = 32, + parameter ADDRSIZE = 8, + parameter NOSAMPLE_WIDTH = 10, + parameter MEM_DEPTH = 256, + parameter SYNC_STAGES = 2 + ) ( + output [DATASIZE-1:0] rd_data, + output reg rd_empty, + output reg wr_full, + input wr_clk, + input rd_clk, + input wr_rstn, + input rd_rstn, + input wr, + input [DATASIZE-1:0] wr_data, + input rd, + + input [NOSAMPLE_WIDTH-1:0] nosamples, // to move the read pointer to the specified location + input fixnosamples_en, // indicates fix number of samples sampling mode is enabled + input [1:0] trigger_mode, // decides whether read pointer needs to be moved or not + input sampling_done_ff // indicates sampling is done + + + ); + wire wen; + wire ren; + wire [ ADDRSIZE:0] wr_gray_code; + wire [ ADDRSIZE:0] wr_binary_value; + wire [ ADDRSIZE:0] rptr_reg; + // reg wr_full; + reg [ ADDRSIZE:0] wptr; + reg [ ADDRSIZE:0] wr_cnt; + wire [ADDRSIZE-1:0] waddr; + + wire [ ADDRSIZE:0] rd_gray_code; + wire [ ADDRSIZE:0] rd_binary_value; + wire [ ADDRSIZE:0] wptr_reg; + //reg rd_empty; + reg [ ADDRSIZE:0] rptr; + reg [ ADDRSIZE:0] rd_cnt; + wire [ADDRSIZE-1:0] rdaddr; + + wire [ ADDRSIZE:0] wptr_bin; + + wire fifo_full; + reg fifo_full_ff; + reg rd_pntr_mvd; + wire fifo_empty; + + wire rpntr_mv; + + reg rd_ff; + /* write data to memory when wr is high */ + //assign wen = wr && (!wr_full); + assign wen = rpntr_mv ? wr && (!sampling_done_ff) : wr && (!wr_full); + assign ren = rd && (!rd_empty); + + /* write counter will increment only when their is a write operation request and fifo is not + full. Read counter will increment only when their is a request for read operation and fifo is + not empty */ + assign wr_binary_value = wr_cnt + wen; + assign rd_binary_value = rd_cnt + (rd && ~rd_empty); + + + /* Binary to Gray code conversion */ + assign wr_gray_code = (wr_binary_value >> 1) ^ wr_binary_value; + assign rd_gray_code = (rd_binary_value >> 1) ^ rd_binary_value; + + /* Memory address for write/read operation */ + assign waddr = wr_cnt[ADDRSIZE-1:0]; + assign rdaddr = rd_cnt[ADDRSIZE-1:0]; + + /* Checking condition for fifo full & empty */ + assign fifo_full = rd_pntr_mvd? 1'b0:(wr_gray_code == {~rptr_reg[ADDRSIZE:ADDRSIZE-1], rptr_reg[ADDRSIZE-2 : 0]}); + assign fifo_empty = fifo_full_ff? 1'b0: (rd_pntr_mvd & !rd_ff) ? 1'b0: (rd_gray_code == wptr_reg); + + always @(posedge wr_clk or negedge wr_rstn) + begin + if (!wr_rstn) + begin + wptr <= 0; + wr_cnt <= 0; + wr_full <= 0; + end + else + begin + wptr <= wr_gray_code; + wr_cnt <= wr_binary_value; + wr_full <= fifo_full; + end + end + + always @(posedge rd_clk or negedge rd_rstn) + begin + if (!rd_rstn) + begin + rptr <= 0; + rd_empty <= 0; + end + else + begin + rptr <= rd_gray_code; + rd_empty <= fifo_empty; + end + end + + + // to indicate trigger mode is post triggered or centered triggered + assign rpntr_mv = (trigger_mode == 2'b10 || trigger_mode == 2'b11); + + // Read pointer relocation logic + always @(posedge rd_clk or negedge rd_rstn) + begin + if (!rd_rstn) + begin + rd_cnt <= 0; + rd_pntr_mvd <= 0; + end + else + begin + if (sampling_done_ff & rpntr_mv & !rd_pntr_mvd) + begin + case ({ + fifo_full_ff, fixnosamples_en + }) + 2'b00: + begin + rd_cnt <= rd_binary_value; + rd_pntr_mvd <= 0; + end + 2'b01: + begin + if (trigger_mode == 2'b10) + begin // data sampling till trigger event occurs + if (wptr_bin > nosamples) + rd_cnt <= (wptr_bin - nosamples); + else + rd_cnt <= rd_binary_value ; + end + else + begin // center triggered condition + if (wptr_bin > 2 * nosamples) + rd_cnt <= wptr_bin - (2 * nosamples); + else + rd_cnt <= rd_binary_value; + end + rd_pntr_mvd <= 1; + end + 2'b10: + begin + rd_cnt <= wptr_bin + 1'b1; + rd_pntr_mvd <= 1; + end + 2'b11: + begin + if (trigger_mode == 2'b10) + begin + if (wptr_bin > nosamples) + rd_cnt <= (wptr_bin - nosamples) ; + else + rd_cnt <= ((MEM_DEPTH + wptr_bin) - nosamples ); + end + else + begin + if (wptr_bin > 2 * nosamples) + rd_cnt <= wptr_bin - (2 * nosamples); + else + rd_cnt <= (MEM_DEPTH + wptr_bin) - (2 * nosamples); + end + rd_pntr_mvd <= 1; + end + default: + begin + rd_cnt <= rd_binary_value; + rd_pntr_mvd <= 0; + end + + endcase + end + else + begin + rd_cnt <= rd_binary_value; + if(!sampling_done_ff) + rd_pntr_mvd <= 0; + end + end + end + + + // Registered fifo full condition + always @(posedge rd_clk or negedge rd_rstn) + begin + if (!rd_rstn) + begin + fifo_full_ff <= 0; + end + else + begin + if (fifo_full & ~fifo_full_ff) + begin + fifo_full_ff <= 1'b1; + end + else if (rd_pntr_mvd) + begin + fifo_full_ff <= 1'b0; + end + + end + end + + // Read operation started + always @(posedge rd_clk or negedge rd_rstn) + begin + if (!rd_rstn) + begin + rd_ff <= 0; + end + else + begin + if (rd_pntr_mvd & !rd_ff & rd) + begin + rd_ff <= rd; + end + // end else if (fifo_empty) begin + // rd_ff <= 1'b0; + // end + + end + end + + dual_port_ram #( + .DATASIZE(DATASIZE), + .ADDRSIZE(ADDRSIZE), + .DEPTH(MEM_DEPTH) + ) dual_port_ram ( + .rdata (rd_data), + .wr_clk(wr_clk), + .rd_clk(rd_clk), + .wen (wen), + .ren (ren), + .wdata (wr_data), + .waddr (waddr), + .raddr (rdaddr) + ); + + synchronizer #( + .SYNC_STAGES(SYNC_STAGES), + .ADDRSIZE (ADDRSIZE) + ) synchronizer ( + .wptr_reg(wptr_reg), + .rptr_reg(rptr_reg), + .wr_clk (wr_clk), + .rd_clk (rd_clk), + .wr_rstn (wr_rstn), + .rd_rstn (rd_rstn), + .wptr (wptr), + .rptr (rptr) + + ); + + gray2binary #( + .DATA_WIDTH(ADDRSIZE) + ) gray2binary_inst ( + .clk(rd_clk), + .rstn(rd_rstn), + //.enable(sampling_done_ff ), + .gray(wptr_reg), + .binary(wptr_bin) + ); + +endmodule + +// ***************************************************************** +// OCLA Controller +// +// +// ***************************************************************** + + +module ocla_controller #( + parameter SAMPLE_CNTER_WIDTH = 2, + parameter MEM_DPTH_HALF = 2 + + ) ( + + input logic sample_clk, + input logic rstn, + + input logic trigger_event, + input logic [1:0] trigger_mode, + input logic start_process, + input logic fixnosamples_en, + input logic [SAMPLE_CNTER_WIDTH-1:0] noofsamples, + + input logic mem_full, + input logic mem_empty, + + input logic sample_again, + + output logic sampling_en, + output logic sampling_done_ff + + ); + + logic [SAMPLE_CNTER_WIDTH-1:0] samples_count; + + logic triggered_occured_ff; + logic trigger_event_ff; + logic sampling_done; + + + // sampling is done and data is availale + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + sampling_done_ff <= 1'b0; + else + begin + if (sampling_done) + sampling_done_ff <= 1'b1; + else if (sample_again || mem_empty) + sampling_done_ff <= 1'b0; + end + end + + + // handles the trigger modes + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + begin + sampling_en <= 1'b0; + samples_count <= 'b0; + end + else + begin + if (!start_process || sample_again) + begin + sampling_en <= 1'b0; + samples_count <= 'b0; + end + else + begin + case (trigger_mode) + 2'b00: + begin // countinous + if (fixnosamples_en) + begin + samples_count <= samples_count + 1'b1; + end + sampling_en <= !sampling_done_ff & !sampling_done; + + end + + 2'b01: + begin // pre trigger + if ((trigger_event || triggered_occured_ff) & !sampling_done) + begin + sampling_en <= !sampling_done_ff & !sampling_done; + if (fixnosamples_en) + begin + samples_count <= samples_count + 1'b1; + end + else + begin + samples_count <= 'b0; + end + end + else + begin + sampling_en <= 1'b0; + end + end + 2'b10: + begin // post trigger + if (trigger_event_ff) + begin + sampling_en <= 1'b0; + end + else + begin + sampling_en <= !sampling_done_ff & !sampling_done; + end + end + 2'b11: + begin // center trigger + if (trigger_event || triggered_occured_ff) + begin + sampling_en <= !sampling_done_ff & !sampling_done; + samples_count <= samples_count + 1'b1; + end + else + begin + sampling_en <= !sampling_done_ff & !sampling_done; + samples_count <= 'b0; + end + end + + default: + begin // default + sampling_en <= 1'b0; + samples_count <= 'b0; + end + + endcase + end + end + end + + + // to generate sampling done signal + always_comb + begin + case (trigger_mode) + 2'b00: + begin + sampling_done = (mem_full) || (fixnosamples_en? (samples_count == noofsamples[SAMPLE_CNTER_WIDTH-1:0]):1'b0); + //if (mem_full || fixnosamples_en?samples_count == noofsamples[SAMPLE_CNTER_WIDTH-1:0]:1'b0 ) begin + // sampling_done = 1'b1; + //end else begin + // sampling_done = 1'b0; + //end + end + 2'b01: + begin + if (mem_full || fixnosamples_en?samples_count == noofsamples[SAMPLE_CNTER_WIDTH-1:0]:1'b0) + sampling_done = 1'b1; + else + sampling_done = 1'b0; + end + 2'b10: + begin + if (trigger_event_ff) + sampling_done = 1'b1; + else + begin + sampling_done = 1'b0; + end + end + 2'b11: + begin + if (fixnosamples_en) + begin + if (samples_count == noofsamples[SAMPLE_CNTER_WIDTH-1:0]) + sampling_done = 1'b1; + else + sampling_done = 1'b0; + end + else + begin + if (samples_count == MEM_DPTH_HALF) + sampling_done = 1'b1; + else + sampling_done = 1'b0; + end + end + default: + sampling_done = 1'b0; + endcase + end + + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + trigger_event_ff <= 1'b0; + else + trigger_event_ff <= trigger_event; + end + // flopped trigger event pulse + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + triggered_occured_ff <= 1'b0; + else + begin + if (!start_process || sample_again || sampling_done_ff) + triggered_occured_ff <= 1'b0; + else if (trigger_event & trigger_mode != 2'b10) + triggered_occured_ff <= 1'b1; + end + end + +endmodule + +// ***************************************************************** +// Dual Port Ram +// +// +// ***************************************************************** + +module dual_port_ram #( + parameter DATASIZE = 32, + parameter ADDRSIZE = 8, + parameter DEPTH = 256 + ) + ( + output reg [DATASIZE-1:0] rdata, + input wr_clk, + input rd_clk, + input wen, + input ren, + input [DATASIZE-1:0] wdata, + input [ADDRSIZE-1:0] waddr, + input [ADDRSIZE-1:0] raddr + ); + reg [DATASIZE-1:0] mem [0:DEPTH-1]; + + always @(posedge rd_clk) + begin + if (ren) + begin + rdata <= mem[raddr]; + end + end + + always @(posedge wr_clk) + begin + if (wen) + begin + mem[waddr] <= wdata; + end + end + + + +endmodule + + +// ***************************************************************** +// Gray to Binary Convertor +// +// +// ***************************************************************** +module gray2binary #( + parameter DATA_WIDTH = 4 + ) ( + input wire clk, + input wire rstn, + input wire [DATA_WIDTH:0] gray, + // input wire enable, + output reg [DATA_WIDTH:0] binary + ); + wire [DATA_WIDTH-1:0] binary_in; + genvar i; + generate + for (i = 0; i < DATA_WIDTH; i = i + 1) + begin + //assign binary_in[i] = enable ? ^gray[DATA_WIDTH-1:i] : 'b0; + assign binary_in[i] = ^(gray >> i); + + end + endgenerate + + always @(posedge clk or negedge rstn ) + begin + if(!rstn) + begin + binary <= 'b0; + end + else + begin + // if (enable) + binary <= {1'b0,binary_in}; + // else + // binary <= binary; + end + end + +endmodule + + + +// ***************************************************************** +// Sampler Buffer +// +// +// ***************************************************************** +module sampler_buffer #( + parameter PROBE_DATA_WIDTH = 32, + parameter BUFFERS = 4 + )( + input logic sample_clk, + input logic rstn, + input logic [PROBE_DATA_WIDTH-1:0] probes, + input logic sampling_en, + output logic data_wen, + output logic [PROBE_DATA_WIDTH-1:0] data_accumulate + + ); + + logic [PROBE_DATA_WIDTH-1:0] sync_register[0:BUFFERS-1]; + + + assign data_accumulate = sync_register[BUFFERS-1]; + //assign data_wen = sync_register[`BUFFER_STAGES-1][NO_OF_PROBES]; + assign data_wen = sampling_en; + // first buffer register + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + begin + sync_register[0] <= 'b0; + end + else + begin + // sync_register[0] <= {sampling_en, probes}; + sync_register[0] <= probes; + end + + end + + // buffer registers stages + genvar b; + generate + for (b = 0; b < (BUFFERS - 1); b = b + 1) + begin + always @(posedge sample_clk or negedge rstn) + begin + if (!rstn) + begin + sync_register[b+1] <= 0; + end + else + begin + sync_register[b+1] <= sync_register[b]; + end + end + end + endgenerate + +endmodule + + +// ***************************************************************** +// Stream Out Buffer +// +// +// ***************************************************************** + +module stream_out_buffer #( + parameter NUM_OFPROBES =2, + parameter WORD_CHUNK_COUNTER_WIDTH =2, + parameter NUM_OF_WORD_CHUNKS =2, + parameter PROBE_BITS =2, + parameter AXI_DATA_WIDTH = 32 + + ) ( + input logic S_AXI_ACLK, + input logic S_AXI_ARESETN, + input logic [NUM_OFPROBES-1:0] read_accumulated_data, + input logic mem_empty, + input logic read_data_en, + input logic read_ready, + output logic mem_read, + output logic read_valid, + + output logic [AXI_DATA_WIDTH-1:0] read_data + + ); + localparam mem_access = 1'b0; // mem access state + localparam data_out = 1'b1; // data out state + localparam PROBES_WORDS_WIDTH = NUM_OFPROBES <= 32 ? AXI_DATA_WIDTH : NUM_OF_WORD_CHUNKS * AXI_DATA_WIDTH; + + reg fetch_data; // fetch data from mem + reg state; // state variable + reg [WORD_CHUNK_COUNTER_WIDTH:0] word_count; // word chunk counter + + + reg [ PROBES_WORDS_WIDTH-1:0] mem_accumulated_data_reg; // mem data hold registor + reg mem_read_ff; + + // simple state machine to handle data fetch from memory and send word chunks to the axi slave interface + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + if (!S_AXI_ARESETN) + begin + state <= mem_access; + mem_read <= 1'b0; + mem_read_ff <= 1'b0; + end + else + begin + mem_read_ff <= mem_read; + case (state) + mem_access: + begin + if (read_data_en && !mem_empty) + begin + if (mem_read) + state <= data_out; + mem_read <= ~mem_read; + end + else + begin + state <= mem_access; + mem_read <= 1'b0; + end + end + data_out: + begin + if (!read_data_en & fetch_data) + begin + state <= mem_access; + end + else + begin + state <= data_out; + end + mem_read <= 1'b0; + + end + default: + begin // Fault Recovery + state <= mem_access; + end + endcase + end + + // this part handles word chunks transfer to the axi slave interface for read transactions + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (!S_AXI_ARESETN) + begin + read_data <= 'b0; + word_count <= 'b0; + read_valid <= 'b0; + fetch_data <= 'b0; + end + else + begin + if (state == data_out) + begin + if (word_count == 'b0 && !fetch_data) + begin + read_data <= read_accumulated_data; + //$display("PROBE_BITS chunk %d, %d, %d", NUM_OF_WORD_CHUNKS, PROBE_BITS,`REM_BITS ); + read_valid <= 'b1; + if (read_ready) + word_count <= word_count + 'b1; + if (word_count >= ((NUM_OF_WORD_CHUNKS) - 1)) + fetch_data <= 'b1; + else + fetch_data <= 'b0; + end + else if (word_count >= ((NUM_OF_WORD_CHUNKS) - 1) ) + begin + if (read_data_en && !mem_empty && !read_valid && !fetch_data) + begin + read_data <= mem_accumulated_data_reg[32*word_count+:PROBE_BITS]; + read_valid <= 'b1; + word_count <= 'b0; + fetch_data <= 'b1; + // $display("word chunk %d, %d", NUM_OF_WORD_CHUNKS, word_count); + end + else + begin + if (read_ready) + read_valid <= 'b0; + fetch_data <= 'b0; + end + end + else + begin + if ((read_data_en && !mem_empty && !read_valid )) + begin + word_count <= word_count + 'b1; + read_data <= mem_accumulated_data_reg[32*word_count+:AXI_DATA_WIDTH]; + read_valid <= 'b1; + fetch_data <= 'b0; + end + else + begin + if (read_ready) + read_valid <= 'b0; + end + end + end + else + begin + word_count <= 'b0; + if (read_ready ) + read_data <= 'b0; + read_valid <= 'b0; + fetch_data <= 'b0; + end + end + end + + // memory fetched data hold register + always @(posedge S_AXI_ACLK or negedge S_AXI_ARESETN) + begin + if (!S_AXI_ARESETN) + begin + mem_accumulated_data_reg <= 'b0; + end + else + begin + if (mem_read_ff) + mem_accumulated_data_reg <= read_accumulated_data; + // mem_accumulated_data_reg <= 'hAAAAAA32BBBBBB31ABCDEF39ABCDEF38ABCDEF37ABCDEF36ABCDEF35ABCDEF34ABCDEF33ABCDEF32ABCDEF31ABCDEF30ABCDEF29ABCDEF28ABCDEF27ABCDEF26ABCDEF25ABCDEF24ABCDEF23ABCDEF22ABCDEF22ABCDEF20ABCDEF19ABCDEF18ABCDEF17ABCDEF16ABCDEF15ABCDEF14ABCDEF13ABCDEF12ABCDEF11ABCDEF10; + end + end + +endmodule + +// ***************************************************************** +// Stream Out Buffer +// +// +// ***************************************************************** + +module synchronizer #( + parameter SYNC_STAGES = 2, + parameter ADDRSIZE = 4 + ) + ( + output [ADDRSIZE:0] wptr_reg, + output [ADDRSIZE:0] rptr_reg, + input wr_clk, + input rd_clk, + input wr_rstn, + input rd_rstn, + input [ADDRSIZE:0] wptr, + input [ADDRSIZE:0] rptr + + ); + + reg [ADDRSIZE:0] wr_sync_register[0:SYNC_STAGES-1]; + reg [ADDRSIZE:0] rd_sync_register[0:SYNC_STAGES-1]; + + + assign wptr_reg = wr_sync_register[SYNC_STAGES-1]; + assign rptr_reg = rd_sync_register[SYNC_STAGES-1]; + + always @(posedge rd_clk or negedge rd_rstn) + begin + if (!rd_rstn) + begin + wr_sync_register[0] <= 0; + end + else + begin + wr_sync_register[0] <= wptr; + end + end + + always @(posedge wr_clk or negedge wr_rstn) + begin + if (!wr_rstn) + begin + rd_sync_register[0] <= 0; + end + else + begin + rd_sync_register[0] <= rptr; + end + + end + + genvar i; + + generate + for(i=0; i<(SYNC_STAGES-1); i = i+1) + begin + always@(posedge rd_clk or negedge rd_rstn) + begin + if(!rd_rstn) + begin + wr_sync_register[i+1] <= 0; + + end + else + begin + wr_sync_register[i+1] <= wr_sync_register[i]; + end + end + always @(posedge wr_clk or negedge wr_rstn) + begin + if (!wr_rstn) + begin + rd_sync_register[i+1] <= 0; + end + else + begin + rd_sync_register[i+1] <= rd_sync_register[i]; + end + end + end + endgenerate +endmodule diff --git a/EDA-3236/rtl/ocla_debug_subsystem.sv b/EDA-3236/rtl/ocla_debug_subsystem.sv new file mode 100644 index 00000000..a797e547 --- /dev/null +++ b/EDA-3236/rtl/ocla_debug_subsystem.sv @@ -0,0 +1,912 @@ + +//////////////////////////////////////////////// +`default_nettype wire + + + + +module ocla_debug_subsystem #( + + /**********************IP Special Parameters*******************/ + + parameter IP_TYPE = "OCLA", + parameter IP_VERSION = 32'h1, + parameter IP_ID = 32'h3881734, + + /*************************************************************/ + + parameter Mode = "NATIVE", // NATIVE, AXI, NATIVE_AXI + parameter Axi_Type = "AXI4" , // AXI4, AXILite + parameter No_AXI_Bus = 1, // Total number of AXI bus: Range (1 -----> 4) + parameter EIO_Enable = 1, // EIO Enable = 1 -------- EIO Disable = 0 + parameter Sampling_Clk = "SINGLE", // SINGLE, MULTIPLE + parameter Cores = 1, // Number of OCLA Core used + + parameter No_Probes = 4'd5, // Total Number of Probes: Range (1 -----> 15) + parameter Probes_Sum = 14'd1, // Total probes width + parameter Mem_Depth = 11'd512, // Buffer size + + /**********************Width of each probe*******************/ + parameter Probe01_Width = 11'd0, + parameter Probe02_Width = 11'd0, + parameter Probe03_Width = 11'd0, + parameter Probe04_Width = 11'd0, + parameter Probe05_Width = 11'd0, + parameter Probe06_Width = 11'd0, + parameter Probe07_Width = 11'd0, + parameter Probe08_Width = 11'd0, + parameter Probe09_Width = 11'd0, + parameter Probe10_Width = 11'd0, + parameter Probe11_Width = 11'd0, + parameter Probe12_Width = 11'd0, + parameter Probe13_Width = 11'd0, + parameter Probe14_Width = 11'd0, + parameter Probe15_Width = 11'd0 , + + /*************************EIO IP Base Address**************************/ + + parameter EIO_BaseAddress = 32'h01000000, + + /*************************AXI Core Base Address************************/ + + parameter AXI_Core_BaseAddress = 32'h01000000, + + /************************* Native Cores Base Addresses******************/ + + parameter IF01_BaseAddress = 32'h01000000, + parameter IF02_BaseAddress = 32'h01000000, + parameter IF03_BaseAddress = 32'h01000000, + parameter IF04_BaseAddress = 32'h01000000, + parameter IF05_BaseAddress = 32'h01000000, + parameter IF06_BaseAddress = 32'h01000000, + parameter IF07_BaseAddress = 32'h01000000, + parameter IF08_BaseAddress = 32'h01000000, + parameter IF09_BaseAddress = 32'h01000000, + parameter IF10_BaseAddress = 32'h01000000, + parameter IF11_BaseAddress = 32'h01000000, + parameter IF12_BaseAddress = 32'h01000000, + parameter IF13_BaseAddress = 32'h01000000, + parameter IF14_BaseAddress = 32'h01000000, + parameter IF15_BaseAddress = 32'h01000000, + + /************ Holding Probes information of each Interface**************/ + + parameter IF01_Probes = 64'h0000000000000000, + parameter IF02_Probes = 64'h0000000000000000, + parameter IF03_Probes = 64'h0000000000000000, + parameter IF04_Probes = 64'h0000000000000000, + parameter IF05_Probes = 64'h0000000000000000, + parameter IF06_Probes = 64'h0000000000000000, + parameter IF07_Probes = 64'h0000000000000000, + parameter IF08_Probes = 64'h0000000000000000, + parameter IF09_Probes = 64'h0000000000000000, + parameter IF10_Probes = 64'h0000000000000000, + parameter IF11_Probes = 64'h0000000000000000, + parameter IF12_Probes = 64'h0000000000000000, + parameter IF13_Probes = 64'h0000000000000000, + parameter IF14_Probes = 64'h0000000000000000, + parameter IF15_Probes = 64'h0000000000000000, + + /*******************EIO Prameter********************/ + + parameter Input_Probe_Width = 10'd32, + parameter Output_Probe_Width = 10'd32, + parameter AXI_IN_CLOCKS_SYNCED = 0, + parameter AXI_OUT_CLOCKS_SYNCED = 0 + + + ) + ( + input wire RESETn, + input wire eio_ip_clk, + input wire eio_op_clk, + input wire ACLK, + +`ifdef single_sample_clock + input wire [Cores - 1 : 0] native_sampling_clk, +`else + input wire native_sampling_clk, +`endif + + input wire axi_sampling_clk, + input wire jtag_tck, + input wire jtag_tms, + input wire jtag_tdi, + output wire jtag_tdo, + input wire jtag_trst, + + input wire [Probes_Sum - 1 : 0] probes, + input wire [No_AXI_Bus*250 - 1 : 0] axi4_probes, + input wire [No_AXI_Bus*152 - 1 : 0] axiLite_probes, + + + input wire [Input_Probe_Width - 1 : 0] probes_in, + output wire [Output_Probe_Width - 1 : 0] probes_out + + ); + + + localparam AXI_TOATAL_PROBES = (Axi_Type == "AXI4") ? No_AXI_Bus *250 : No_AXI_Bus * 152; + + localparam M_Count = (Mode == "NATIVE") ? Cores +2 : Cores + 1; + localparam m_count = (Mode == "NATIVE") ? Cores : Cores - 1; + + + localparam Data_Width = 32; + localparam Addr_Width = 32; + localparam STRB_WIDTH = (Data_Width/8); + + localparam OCLA_COUNT = (Mode == "NATIVE_AXI")? Cores-1 :Cores; + + localparam [960-1:0]IF_Probes = {IF15_Probes,IF14_Probes,IF13_Probes,IF12_Probes,IF11_Probes,IF10_Probes,IF09_Probes,IF08_Probes,IF07_Probes,IF06_Probes,IF05_Probes,IF04_Probes,IF03_Probes,IF02_Probes,IF01_Probes}; + localparam [165-1:0]Probes_Size = {Probe15_Width,Probe14_Width,Probe13_Width,Probe12_Width,Probe11_Width,Probe10_Width,Probe09_Width,Probe08_Width,Probe07_Width,Probe06_Width,Probe05_Width,Probe04_Width,Probe03_Width,Probe02_Width,Probe01_Width}; + + localparam [543 : 0]InterconnectBaseAddress0 = {IF15_BaseAddress,IF14_BaseAddress,IF13_BaseAddress,IF12_BaseAddress,IF11_BaseAddress,IF10_BaseAddress,IF09_BaseAddress,IF08_BaseAddress,IF07_BaseAddress,IF06_BaseAddress,IF05_BaseAddress,IF04_BaseAddress,IF03_BaseAddress,IF02_BaseAddress,IF01_BaseAddress,AXI_Core_BaseAddress,EIO_BaseAddress}; + localparam [543 : 0]InterconnectBaseAddress1 = {IF15_BaseAddress,IF14_BaseAddress,IF13_BaseAddress,IF12_BaseAddress,IF11_BaseAddress,IF10_BaseAddress,IF09_BaseAddress,IF08_BaseAddress,IF07_BaseAddress,IF06_BaseAddress,IF05_BaseAddress,IF04_BaseAddress,IF03_BaseAddress,IF02_BaseAddress,IF01_BaseAddress,AXI_Core_BaseAddress,32'h010000000}; + localparam [543 : 0]InterconnectBaseAddress = (EIO_Enable == 1) ? InterconnectBaseAddress0 : InterconnectBaseAddress1; + // initial + // begin + // $display("M_Count = %0d",M_Count ); + // $display("Base Addresses are = %0x",InterconnectBaseAddress ); + // $display("AXI_TOATAL_PROBES = %0d",AXI_TOATAL_PROBES ); + // $display("OCLA_COUNT = %0d",OCLA_COUNT ); + // end + + //---------- Total no of Probes for each OCLA Core ----------------------// + + function [240-1:0] ProbesNo (input [31:0] dummy); + integer i,j,k; + reg [64-1:0] IF_NO ; + reg [4-1:0] PROBE_NO ; + reg [16-1:0] PROBE_SIZE; + reg [16-1:0] TOTAL_PROBE_SIZE; + + begin + ProbesNo = 0; + IF_NO = 0; + PROBE_NO = 0; + PROBE_SIZE = 0; + TOTAL_PROBE_SIZE = 0; + for (i = 0; i < 15; i = i + 1) + begin + IF_NO = IF_Probes[i*64 +: 64]; + for (j = 0; j < 16; j = j + 1) + begin + PROBE_NO = IF_NO[j*4 +: 4]; + if (PROBE_NO > 0) + begin + PROBE_SIZE = Probes_Size[((PROBE_NO*11)-11) +: 11]; + TOTAL_PROBE_SIZE = TOTAL_PROBE_SIZE + PROBE_SIZE; + end + end + ProbesNo[i*16 +: 16] = TOTAL_PROBE_SIZE; + TOTAL_PROBE_SIZE = 0; + end + + end + + endfunction + + localparam [240-1:0]Probes_No = ProbesNo(0); + + //localparam [240-1:0]Probes_No = {16'd1024,16'd8,16'd4}; + + + + //------------ Probe starting index for each OCLA Core-----------------// + + function [240-1:0] start_index(input [31:0] dummy); + integer i,j,k; + reg [16-1:0] PROBE_SIZE ; + reg [16-1:0] Probes_No_Reg ; + reg [16-1:0] Start_Index_Reg ; + + reg [240-1:0] TOTAL_PROBE_SIZE; + + begin + start_index = 240'd0; + PROBE_SIZE = 16'd0; + Probes_No_Reg = 16'd0; + Start_Index_Reg = 16'd0; + for (i = 0; i < 15; i = i + 1) + begin + if(i==0) + start_index[i*16 +: 16] = 0; + else + begin + Probes_No_Reg = Probes_No[(i-1)*16 +: 16]; + Start_Index_Reg = start_index[(i-1)*16 +: 16]; + start_index[i*16 +: 16] = Probes_No_Reg + Start_Index_Reg; + end + end + + end + + endfunction + + localparam [240-1:0] probe_start_index = start_index(0); + //localparam [240-1:0] probe_start_index = {16'd12,16'd4,16'd0}; + + + //------------ Probe Ending index for each OCLA Core-----------------// + + function [240-1:0] end_index(input [31:0] dummy); + integer i,j,k; + reg [16-1:0] PROBE_SIZE ; + reg [240-1:0] TOTAL_PROBE_SIZE; + + begin + end_index = 240'd0; + for (i = 0; i < 15; i = i + 1) + begin + + end_index[i*16 +: 16] = Probes_No[i*16 +: 16]; + + end + + end + + endfunction + + + localparam [240-1:0] probe_end_index = end_index(0); + //localparam [240-1:0] probe_end_index = {16'd1024,16'd8,16'd4}; + integer k; + //initial + //begin + // for ( k=0 ; k < 15 ; k= k+1) + // begin + // $display("No of probes = %0d",Probes_No[k*16 +: 16] ); + // end + // for ( k=0 ; k < 15 ; k= k+1) + // begin + // $display("starting index= %0d",probe_start_index [k*16 +: 16]); + // end + // for ( k=0 ; k < 15 ; k= k+1) + // begin + // $display("end index = %0d",probe_end_index [k*16 +: 16]); + // end + //end + + // clock signals + wire [OCLA_COUNT-1:0] core_sampling_clk; + + // JTAG_AXI Signals + wire r_m_axi_awvalid; + wire r_m_axi_awready; + wire [31 : 0] r_m_axi_awaddr; + wire [1 : 0] r_m_axi_awburst; + wire [7 : 0] r_m_axi_awlen; + wire [2 : 0] r_m_axi_awsize; + wire r_m_axi_awlock; + wire [2 : 0] r_m_axi_awprot; + wire [3 : 0] r_m_axi_awcache; + wire [3 : 0] r_m_axi_awqos; + wire [3 : 0] r_m_axi_awregion; + wire [3 : 0] r_m_axi_awid; + wire [1 : 0] r_m_axi_awuser; + wire r_m_axi_wvalid; + wire r_m_axi_wready; + wire r_m_axi_wlast; + wire [31 : 0] r_m_axi_wdata; + wire [3 : 0] r_m_axi_wstrb; + wire [1 : 0] r_m_axi_wuser; + wire r_m_axi_bvalid; + wire r_m_axi_bready; + wire [1 : 0] r_m_axi_bresp; + wire [3 : 0] r_m_axi_bid; + wire [1 : 0] r_m_axi_buser; + wire r_m_axi_arvalid; + wire r_m_axi_arready; + wire [31 : 0] r_m_axi_araddr; + wire [1 : 0] r_m_axi_arburst; + wire [7 : 0] r_m_axi_arlen; + wire [2 : 0] r_m_axi_arsize; + wire r_m_axi_arlock; + wire [2 : 0] r_m_axi_arprot; + wire [3 : 0] r_m_axi_arcache; + wire [3 : 0] r_m_axi_arqos; + wire [3 : 0] r_m_axi_arregion; + wire [3 : 0] r_m_axi_arid; + wire [1 : 0] r_m_axi_aruser; + wire r_m_axi_rvalid; + wire r_m_axi_rready; + wire r_m_axi_rlast; + wire [1 : 0] r_m_axi_rresp; + wire [31 : 0] r_m_axi_rdata; + wire [3 : 0] r_m_axi_rid; + wire [1 : 0] r_m_axi_ruser; + + + wire m_axi_awvalid; + wire m_axi_awready; + wire [31 : 0] m_axi_awaddr; + wire [2 : 0] m_axi_awprot; + wire m_axi_wvalid; + wire m_axi_wready; + wire [31 : 0] m_axi_wdata; + wire [3 : 0] m_axi_wstrb; + wire m_axi_bvalid; + wire m_axi_bready; + wire [1 : 0] m_axi_bresp; + wire m_axi_arvalid; + wire m_axi_arready; + wire [31 : 0] m_axi_araddr; + wire [2 : 0] m_axi_arprot; + wire m_axi_rvalid; + wire m_axi_rready; + wire [1 : 0] m_axi_rresp; + wire [31 : 0] m_axi_rdata; + + + //---------------------master interface signals generation---------------- + + wire [m_count-1:0] m_axil_arready; + wire [m_count-1:0] m_axil_awready; + wire [m_count*2-1:0] m_axil_bresp; + wire [m_count-1:0] m_axil_bvalid; + wire [m_count*Data_Width-1:0] m_axil_rdata; + wire [m_count*2-1:0] m_axil_rresp; + wire [m_count-1:0] m_axil_rvali; + wire [m_count*Addr_Width-1:0] m_axil_araddr; + wire [m_count*3-1:0] m_axil_arprot; + wire [m_count-1:0] m_axil_arvalid; + wire [m_count*Addr_Width-1:0] m_axil_awaddr; + wire [m_count*3-1:0] m_axil_awprot; + wire [m_count-1:0] m_axil_awvalid; + wire [m_count-1:0] m_axil_bready; + wire [m_count-1:0] m_axil_rready; + wire [m_count*Data_Width-1:0] m_axil_wdata; + wire [m_count-1:0] m_axil_wready; + wire [m_count*STRB_WIDTH-1:0] m_axil_wstrb; + wire [m_count-1:0] m_axil_wvalid; + wire [m_count-1:0] m_axil_rvalid; + + + wire S_AXI_ARREADY; + wire S_AXI_AWREADY; + wire [1 : 0] S_AXI_BRESP; + wire S_AXI_BVALID; + wire [31 : 0] S_AXI_RDATA; + wire [1 : 0] S_AXI_RRESP; + wire S_AXI_RVALID; + wire [31 : 0] S_AXI_ARADDR; + wire [2 : 0] S_AXI_ARPROT; + wire S_AXI_ARVALID; + wire [31 : 0] S_AXI_AWADDR; + wire [2 : 0] S_AXI_AWPROT; + wire S_AXI_AWVALID; + wire S_AXI_BREADY; + wire S_AXI_RREADY; + wire [31 : 0] S_AXI_WDATA; + wire S_AXI_WREADY; + wire [3 : 0] S_AXI_WSTRB; + wire S_AXI_WVALID; + + wire [31 : 0] ma_axil_awaddr; + wire [2 : 0] ma_axil_awprot; + wire ma_axil_awvalid; + wire ma_axil_awready; + wire [31 : 0] ma_axil_wdata; + wire [3 : 0] ma_axil_wstrb; + wire ma_axil_wvalid; + wire ma_axil_wready; + wire [1 : 0] ma_axil_bresp; + wire ma_axil_bvalid; + wire ma_axil_bready; + wire [31 : 0] ma_axil_araddr; + wire [2 : 0] ma_axil_arprot; + wire ma_axil_arvalid; + wire ma_axil_arready; + wire [31 : 0] ma_axil_rdata; + wire [1 : 0] ma_axil_rresp; + wire ma_axil_rvalid; + wire ma_axil_rready; + + + assign core_sampling_clk = (Sampling_Clk == "SINGLE") ? {OCLA_COUNT{native_sampling_clk}} : native_sampling_clk; + + //------------------------------------------------------------------------------ + // JTAG_AXI + + jtag_to_axi_top # ( + .C_S_AXI_ID_WIDTH(4), + .C_S_AXI_DATA_WIDTH(32), + .C_S_AXI_ADDR_WIDTH(32), + .C_S_AXI_AWUSER_WIDTH(2), + .C_S_AXI_ARUSER_WIDTH(2), + .C_S_AXI_WUSER_WIDTH(2), + .C_S_AXI_RUSER_WIDTH(2), + .C_S_AXI_BUSER_WIDTH(2) + ) + jtag_to_axi_top_inst ( + .ACLK(ACLK), + .ARESETN(RESETn), + .aw_id(r_m_axi_awid), + .aw_addr(r_m_axi_awaddr), + .aw_lock(r_m_axi_awlock), + .aw_cache(r_m_axi_awcache), + .aw_prot(r_m_axi_awprot), + .aw_region(r_m_axi_awregion), + .aw_user(r_m_axi_awuser), + .aw_qos(r_m_axi_awqos), + .aw_valid(r_m_axi_awvalid), + .aw_ready(r_m_axi_awready), + .aw_burst(r_m_axi_awburst), + .aw_size(r_m_axi_awsize), + .aw_len(r_m_axi_awlen), + .ar_id(r_m_axi_arid), + .ar_addr(r_m_axi_araddr), + .ar_lock(r_m_axi_arlock), + .ar_cache(r_m_axi_arcache), + .ar_prot(r_m_axi_arprot), + .ar_region(r_m_axi_arregion), + .ar_user(r_m_axi_aruser), + .ar_qos(r_m_axi_arqos), + .ar_valid(r_m_axi_arvalid), + .ar_ready(r_m_axi_arready), + .ar_burst(r_m_axi_arburst), + .ar_size(r_m_axi_arsize), + .ar_len(r_m_axi_arlen), + .w_data(r_m_axi_wdata), + .w_strb(r_m_axi_wstrb), + .w_last(r_m_axi_wlast), + .w_user(r_m_axi_wuser), + .w_valid(r_m_axi_wvalid), + .w_ready(r_m_axi_wready), + .r_id(r_m_axi_rid), + .r_data(r_m_axi_rdata), + .r_last(r_m_axi_rlast), + .r_valid(r_m_axi_rvalid), + .r_resp(r_m_axi_rresp), + .r_ready(r_m_axi_rready), + .r_user(r_m_axi_buser), + .b_id(r_m_axi_bid), + .b_resp(r_m_axi_bresp), + .b_valid(r_m_axi_bvalid), + .b_ready(r_m_axi_bready), + .b_user(r_m_axi_ruser), + .JTAG_TCK(jtag_tck), + .JTAG_TMS(jtag_tms), + .JTAG_TDI(jtag_tdi), + .JTAG_TDO(jtag_tdo), + .JTAG_TRST(jtag_trst) + ); + + + //------------------------------------------------------------------------------ + // axi2axilite_wrapper + + axi2axilite #( + .C_AXI_ADDR_WIDTH(32), + .C_AXI_DATA_WIDTH(32), + .C_AXI_ID_WIDTH(4) + ) axi2axilite ( + .M_AXI_ARREADY(m_axi_arready), + .M_AXI_AWREADY(m_axi_awready), + .M_AXI_BRESP(m_axi_bresp), + .M_AXI_BVALID(m_axi_bvalid), + .M_AXI_RDATA(m_axi_rdata), + .M_AXI_RRESP(m_axi_rresp), + .M_AXI_RVALID(m_axi_rvalid), + .M_AXI_WREADY(m_axi_wready), + .S_AXI_ACLK(ACLK), + .S_AXI_ARADDR(r_m_axi_araddr), + .S_AXI_ARBURST(r_m_axi_arburst), + .S_AXI_ARCACHE(r_m_axi_arcache), + .S_AXI_ARESETN(RESETn), + .S_AXI_ARID(r_m_axi_arid), + .S_AXI_ARLEN(r_m_axi_arlen), + .S_AXI_ARLOCK(r_m_axi_arlock), + .S_AXI_ARPROT(r_m_axi_arprot), + .S_AXI_ARQOS(r_m_axi_arqos), + .S_AXI_ARSIZE(r_m_axi_arsize), + .S_AXI_ARVALID(r_m_axi_arvalid), + .S_AXI_AWADDR(r_m_axi_awaddr), + .S_AXI_AWBURST(r_m_axi_awburst), + .S_AXI_AWCACHE(r_m_axi_awcache), + .S_AXI_AWID(r_m_axi_awid), + .S_AXI_AWLEN(r_m_axi_awlen), + .S_AXI_AWLOCK(r_m_axi_awlock), + .S_AXI_AWPROT(r_m_axi_awprot), + .S_AXI_AWQOS(r_m_axi_awqos), + .S_AXI_AWSIZE(r_m_axi_awsize), + .S_AXI_AWVALID(r_m_axi_awvalid), + .S_AXI_BREADY(r_m_axi_bready), + .S_AXI_RREADY(r_m_axi_rready), + .S_AXI_WDATA(r_m_axi_wdata), + .S_AXI_WLAST(r_m_axi_wlast), + .S_AXI_WSTRB(r_m_axi_wstrb), + .S_AXI_WVALID(r_m_axi_wvalid), + .M_AXI_ARADDR(m_axi_araddr), + .M_AXI_ARPROT(m_axi_arprot), + .M_AXI_ARVALID(m_axi_arvalid), + .M_AXI_AWADDR(m_axi_awaddr), + .M_AXI_AWPROT(m_axi_awprot), + .M_AXI_AWVALID(m_axi_awvalid), + .M_AXI_BREADY(m_axi_bready), + .M_AXI_RREADY(m_axi_rready), + .M_AXI_WDATA(m_axi_wdata), + .M_AXI_WSTRB(m_axi_wstrb), + .M_AXI_WVALID(m_axi_wvalid), + .S_AXI_ARREADY(r_m_axi_arready), + .S_AXI_AWREADY(r_m_axi_awready), + .S_AXI_BID(r_m_axi_bid), + .S_AXI_BRESP(r_m_axi_bresp), + .S_AXI_BVALID(r_m_axi_bvalid), + .S_AXI_RDATA(r_m_axi_rdata), + .S_AXI_RID(r_m_axi_rid), + .S_AXI_RLAST(r_m_axi_rlast), + .S_AXI_RRESP(r_m_axi_rresp), + .S_AXI_RVALID(r_m_axi_rvalid), + .S_AXI_WREADY(r_m_axi_wready) + ); + + //------------------------------------------------------------------------------ + // axil_interconnect_wrapper + + + axil_interconnect #( + + .ADDR_WIDTH(32), + .DATA_WIDTH(32), + .M_COUNT(M_Count), + .S_COUNT(1), + .M_BASE_ADDR(InterconnectBaseAddress) + ) axil_interconnect ( + .clk(ACLK), + .m_axil_arready({m_axil_arready,ma_axil_arready,S_AXI_ARREADY}), + .m_axil_awready({m_axil_awready,ma_axil_awready,S_AXI_AWREADY}), + .m_axil_bresp ({m_axil_bresp ,ma_axil_bresp,S_AXI_BRESP}), + .m_axil_bvalid ({m_axil_bvalid ,ma_axil_bvalid,S_AXI_BVALID}), + .m_axil_rdata ({m_axil_rdata ,ma_axil_rdata,S_AXI_RDATA}), + .m_axil_rresp ({m_axil_rresp ,ma_axil_rresp,S_AXI_RRESP}), + .m_axil_rvalid ({m_axil_rvalid ,ma_axil_rvalid,S_AXI_RVALID}), + .rst(!RESETn), + .s_axil_araddr(m_axi_araddr), + .s_axil_arprot(m_axi_arprot), + .s_axil_arvalid(m_axi_arvalid), + .s_axil_awaddr(m_axi_awaddr), + .s_axil_awprot(m_axi_awprot), + .s_axil_awvalid(m_axi_awvalid), + .s_axil_bready(m_axi_bready), + .s_axil_rready(m_axi_rready), + .s_axil_wdata(m_axi_wdata), + .s_axil_wstrb(m_axi_wstrb), + .s_axil_wvalid(m_axi_wvalid), + .m_axil_araddr ({m_axil_araddr ,ma_axil_araddr,S_AXI_ARADDR}), + .m_axil_arprot ({m_axil_arprot ,ma_axil_arprot,S_AXI_ARPROT}), + .m_axil_arvalid({m_axil_arvalid,ma_axil_arvalid,S_AXI_ARVALID}), + .m_axil_awaddr ({m_axil_awaddr ,ma_axil_awaddr,S_AXI_AWADDR}), + .m_axil_awprot ({m_axil_awprot ,ma_axil_awprot,S_AXI_AWPROT}), + .m_axil_awvalid({m_axil_awvalid,ma_axil_awvalid,S_AXI_AWVALID}), + .m_axil_bready ({m_axil_bready ,ma_axil_bready,S_AXI_BREADY}), + .m_axil_rready ({m_axil_rready ,ma_axil_rready,S_AXI_RREADY}), + .m_axil_wdata ({m_axil_wdata ,ma_axil_wdata,S_AXI_WDATA}), + .m_axil_wready ({m_axil_wready ,ma_axil_wready,S_AXI_WREADY}), + .m_axil_wstrb ({m_axil_wstrb ,ma_axil_wstrb,S_AXI_WSTRB}), + .m_axil_wvalid ({m_axil_wvalid ,ma_axil_wvalid,S_AXI_WVALID}), + .s_axil_arready(m_axi_arready ), + .s_axil_awready(m_axi_awready ), + .s_axil_bresp(m_axi_bresp), + .s_axil_bvalid(m_axi_bvalid), + .s_axil_rdata(m_axi_rdata), + .s_axil_rresp(m_axi_rresp), + .s_axil_rvalid(m_axi_rvalid), + .s_axil_wready(m_axi_wready) + ); + + + + + generate + begin + if (Mode == "NATIVE") + begin: OCLA_GEN_NATIVE + + genvar i; + for (i = 0; i < OCLA_COUNT; i = i + 1) + ocla # ( + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .IP_ID(IP_ID), + .NO_OF_PROBES(Probes_No[i*16 +:16]), + .MEM_DEPTH(Mem_Depth), + .AXI_DATA_WIDTH(Data_Width), + .AXI_ADDR_WIDTH(Addr_Width), + .INDEX(i) + ) + ocla_inst ( + .sample_clk(core_sampling_clk[i]), + .rstn(RESETn), + .S_AXI_ACLK(ACLK), + .S_AXI_ARESETN(RESETn), + .S_AXI_AWADDR(m_axil_awaddr[i*32 +:32]), + .S_AXI_AWPROT(m_axil_awprot[i*3 +:3]), + .S_AXI_AWVALID(m_axil_awvalid[i]), + .S_AXI_AWREADY(m_axil_awready[i]), + .S_AXI_WDATA(m_axil_wdata[i*32 +:32]), + .S_AXI_WSTRB(m_axil_wstrb[i*4 +:4]), + .S_AXI_WVALID(m_axil_wvalid[i]), + .S_AXI_WREADY(m_axil_wready[i]), + .S_AXI_BRESP(m_axil_bresp[i*2 +:2]), + .S_AXI_BVALID(m_axil_bvalid[i]), + .S_AXI_BREADY(m_axil_bready[i]), + .S_AXI_ARADDR(m_axil_araddr[i*32 +:32]), + .S_AXI_ARPROT(m_axil_arprot[i*3 +:3]), + .S_AXI_ARVALID(m_axil_arvalid[i]), + .S_AXI_ARREADY(m_axil_arready[i]), + .S_AXI_RDATA(m_axil_rdata[i*32 +:32]), + .S_AXI_RRESP(m_axil_rresp[i*2 +: 2]), + .S_AXI_RVALID(m_axil_rvalid[i]), + .S_AXI_RREADY(m_axil_rready[i]), + .probes(probes[probe_start_index[i*16 +:16] +: probe_end_index[i*16 +:16]]) + + ); + end + else if(Mode == "AXI" && Axi_Type == "AXI4" ) + begin: OCLA_GEN_AXI4 + ocla # ( + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .IP_ID(IP_ID), + .NO_OF_PROBES(AXI_TOATAL_PROBES), + .MEM_DEPTH(Mem_Depth), + .AXI_DATA_WIDTH(Data_Width), + .AXI_ADDR_WIDTH(Addr_Width), + .INDEX(0) + ) + ocla_inst ( + .sample_clk(axi_sampling_clk), + .rstn(RESETn), + .S_AXI_ACLK(ACLK), + .S_AXI_ARESETN(RESETn), + .S_AXI_AWADDR(ma_axil_awaddr), + .S_AXI_AWPROT(ma_axil_awprot), + .S_AXI_AWVALID(ma_axil_awvalid), + .S_AXI_AWREADY(ma_axil_awready), + .S_AXI_WDATA(ma_axil_wdata), + .S_AXI_WSTRB(ma_axil_wstrb), + .S_AXI_WVALID(ma_axil_wvalid), + .S_AXI_WREADY(ma_axil_wready), + .S_AXI_BRESP(ma_axil_bresp), + .S_AXI_BVALID(ma_axil_bvalid), + .S_AXI_BREADY(ma_axil_bready), + .S_AXI_ARADDR(ma_axil_araddr), + .S_AXI_ARPROT(ma_axil_arprot), + .S_AXI_ARVALID(ma_axil_arvalid), + .S_AXI_ARREADY(ma_axil_arready), + .S_AXI_RDATA(ma_axil_rdata), + .S_AXI_RRESP(ma_axil_rresp), + .S_AXI_RVALID(ma_axil_rvalid), + .S_AXI_RREADY(ma_axil_rready), + .probes (axi4_probes) + ); + end + else if(Mode == "AXI" && Axi_Type == "AXILite" ) + begin: OCLA_GEN_AXILite + ocla # ( + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .IP_ID(IP_ID), + .NO_OF_PROBES(AXI_TOATAL_PROBES), + .MEM_DEPTH(Mem_Depth), + .AXI_DATA_WIDTH(Data_Width), + .AXI_ADDR_WIDTH(Addr_Width), + .INDEX(0) + ) + ocla_inst ( + .sample_clk(axi_sampling_clk), + .rstn(RESETn), + .S_AXI_ACLK(ACLK), + .S_AXI_ARESETN(RESETn), + .S_AXI_AWADDR (ma_axil_awaddr), + .S_AXI_AWPROT (ma_axil_awprot), + .S_AXI_AWVALID (ma_axil_awvalid), + .S_AXI_AWREADY (ma_axil_awready), + .S_AXI_WDATA (ma_axil_wdata), + .S_AXI_WSTRB (ma_axil_wstrb), + .S_AXI_WVALID (ma_axil_wvalid), + .S_AXI_WREADY (ma_axil_wready), + .S_AXI_BRESP (ma_axil_bresp), + .S_AXI_BVALID (ma_axil_bvalid), + .S_AXI_BREADY (ma_axil_bready), + .S_AXI_ARADDR (ma_axil_araddr), + .S_AXI_ARPROT (ma_axil_arprot), + .S_AXI_ARVALID (ma_axil_arvalid), + .S_AXI_ARREADY (ma_axil_arready), + .S_AXI_RDATA (ma_axil_rdata), + .S_AXI_RRESP (ma_axil_rresp), + .S_AXI_RVALID (ma_axil_rvalid), + .S_AXI_RREADY (ma_axil_rready), + .probes (axiLite_probes) + ); + end + else + begin : OCLA_GEN_NATIVE_AXI + + genvar i; + for (i = 0; i < OCLA_COUNT; i = i + 1) + ocla # ( + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .IP_ID(IP_ID), + .NO_OF_PROBES(Probes_No[i*16 +:16]), + .MEM_DEPTH(Mem_Depth), + .AXI_DATA_WIDTH(Data_Width), + .AXI_ADDR_WIDTH(Addr_Width), + .INDEX(i) + ) + ocla_inst ( + .sample_clk(core_sampling_clk[i]), + .rstn(RESETn), + .S_AXI_ACLK(ACLK), + .S_AXI_ARESETN(RESETn), + .S_AXI_AWADDR(m_axil_awaddr[i*32 +:32]), + .S_AXI_AWPROT(m_axil_awprot[i*3 +:3]), + .S_AXI_AWVALID(m_axil_awvalid[i]), + .S_AXI_AWREADY(m_axil_awready[i]), + .S_AXI_WDATA(m_axil_wdata[i*32 +:32]), + .S_AXI_WSTRB(m_axil_wstrb[i*4 +:4]), + .S_AXI_WVALID(m_axil_wvalid[i]), + .S_AXI_WREADY(m_axil_wready[i]), + .S_AXI_BRESP(m_axil_bresp[i*2 +:2]), + .S_AXI_BVALID(m_axil_bvalid[i]), + .S_AXI_BREADY(m_axil_bready[i]), + .S_AXI_ARADDR(m_axil_araddr[i*32 +:32]), + .S_AXI_ARPROT(m_axil_arprot[i*3 +:3]), + .S_AXI_ARVALID(m_axil_arvalid[i]), + .S_AXI_ARREADY(m_axil_arready[i]), + .S_AXI_RDATA(m_axil_rdata[i*32 +:32]), + .S_AXI_RRESP(m_axil_rresp[i*2 +: 2]), + .S_AXI_RVALID(m_axil_rvalid[i]), + .S_AXI_RREADY(m_axil_rready[i]), + .probes(probes[probe_start_index[i*16 +:16] +: probe_end_index[i*16 +:16]]) + + ); + + if(Axi_Type == "AXILite" ) + begin: OCLA_GEN__NATIVE_AXILite + ocla # ( + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .IP_ID(IP_ID), + .NO_OF_PROBES(AXI_TOATAL_PROBES), + .MEM_DEPTH(Mem_Depth), + .AXI_DATA_WIDTH(Data_Width), + .AXI_ADDR_WIDTH(Addr_Width), + .INDEX(OCLA_COUNT) + ) + ocla_inst_Lite ( + .sample_clk(axi_sampling_clk), + .rstn(RESETn), + .S_AXI_ACLK(ACLK), + .S_AXI_ARESETN(RESETn), + .S_AXI_AWADDR (ma_axil_awaddr), + .S_AXI_AWPROT (ma_axil_awprot), + .S_AXI_AWVALID (ma_axil_awvalid), + .S_AXI_AWREADY (ma_axil_awready), + .S_AXI_WDATA (ma_axil_wdata), + .S_AXI_WSTRB (ma_axil_wstrb), + .S_AXI_WVALID (ma_axil_wvalid), + .S_AXI_WREADY (ma_axil_wready), + .S_AXI_BRESP (ma_axil_bresp), + .S_AXI_BVALID (ma_axil_bvalid), + .S_AXI_BREADY (ma_axil_bready), + .S_AXI_ARADDR (ma_axil_araddr), + .S_AXI_ARPROT (ma_axil_arprot), + .S_AXI_ARVALID (ma_axil_arvalid), + .S_AXI_ARREADY (ma_axil_arready), + .S_AXI_RDATA (ma_axil_rdata), + .S_AXI_RRESP (ma_axil_rresp), + .S_AXI_RVALID (ma_axil_rvalid), + .S_AXI_RREADY (ma_axil_rready), + .probes(axiLite_probes) + ); + end + else + begin: OCLA_GEN__NATIVE_AXI4 + ocla # ( + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .IP_ID(IP_ID), + .NO_OF_PROBES(AXI_TOATAL_PROBES), + .MEM_DEPTH(Mem_Depth), + .AXI_DATA_WIDTH(Data_Width), + .AXI_ADDR_WIDTH(Addr_Width), + .INDEX(OCLA_COUNT) + ) + ocla_inst_full ( + .sample_clk(axi_sampling_clk), + .rstn(RESETn), + .S_AXI_ACLK(ACLK), + .S_AXI_ARESETN(RESETn), + .S_AXI_AWADDR(ma_axil_awaddr), + .S_AXI_AWPROT(ma_axil_awprot), + .S_AXI_AWVALID(ma_axil_awvalid), + .S_AXI_AWREADY(ma_axil_awready), + .S_AXI_WDATA(ma_axil_wdata), + .S_AXI_WSTRB(ma_axil_wstrb), + .S_AXI_WVALID(ma_axil_wvalid), + .S_AXI_WREADY(ma_axil_wready), + .S_AXI_BRESP(ma_axil_bresp), + .S_AXI_BVALID(ma_axil_bvalid), + .S_AXI_BREADY(ma_axil_bready), + .S_AXI_ARADDR(ma_axil_araddr), + .S_AXI_ARPROT(ma_axil_arprot), + .S_AXI_ARVALID(ma_axil_arvalid), + .S_AXI_ARREADY(ma_axil_arready), + .S_AXI_RDATA(ma_axil_rdata), + .S_AXI_RRESP(ma_axil_rresp), + .S_AXI_RVALID(ma_axil_rvalid), + .S_AXI_RREADY(ma_axil_rready), + .probes(axi4_probes) + ); + end + + end + end + endgenerate + + + generate if (EIO_Enable == 1) + begin : EIO_GEN + + + + eio_top # ( + .C_S_AXI_DATA_WIDTH(Data_Width), + .C_S_AXI_ADDR_WIDTH(32), + .INPUT_PROBE_WIDTH(Input_Probe_Width), + .OUTPUT_PROBE_WIDTH(Output_Probe_Width), + .AXI_IN_CLOCKS_SYNCED(AXI_IN_CLOCKS_SYNCED), + .AXI_OUT_CLOCKS_SYNCED(AXI_OUT_CLOCKS_SYNCED) + ) + eio_top_inst ( + .IP_CLK(eio_ip_clk), + .OP_CLK(eio_op_clk), + .S_AXI_ACLK(ACLK), + .S_AXI_ARESETN(RESETn), + .S_AXI_AWADDR(S_AXI_AWADDR[15:0]), + .S_AXI_AWPROT(S_AXI_AWPROT), + .S_AXI_AWVALID(S_AXI_AWVALID), + .S_AXI_AWREADY(S_AXI_AWREADY), + .S_AXI_WDATA(S_AXI_WDATA), + .S_AXI_WSTRB(S_AXI_WSTRB), + .S_AXI_WVALID(S_AXI_WVALID), + .S_AXI_WREADY(S_AXI_WREADY), + .S_AXI_BRESP(S_AXI_BRESP), + .S_AXI_BVALID(S_AXI_BVALID), + .S_AXI_BREADY(S_AXI_BREADY), + .S_AXI_ARADDR(S_AXI_ARADDR[15:0]), + .S_AXI_ARPROT(S_AXI_ARPROT), + .S_AXI_ARVALID(S_AXI_ARVALID), + .S_AXI_ARREADY(S_AXI_ARREADY), + .S_AXI_RDATA(S_AXI_RDATA), + .S_AXI_RRESP(S_AXI_RRESP), + .S_AXI_RVALID(S_AXI_RVALID), + .S_AXI_RREADY(S_AXI_RREADY), + .probe_in(probes_in), + .probe_out(probes_out) + ); + end + /* else + begin : EIO_GEN + always@(*) begin + S_AXI_ARADDR = 0; + S_AXI_ARPROT = 0; + S_AXI_ARVALID = 0; + S_AXI_AWADDR = 0; + S_AXI_AWPROT = 0; + S_AXI_AWVALID = 0; + S_AXI_BREADY = 0; + S_AXI_RREADY = 0; + S_AXI_WDATA = 0; + S_AXI_WSTRB = 0; + S_AXI_WVALID = 0; + end + end*/ + endgenerate + +endmodule + diff --git a/EDA-3236/rtl/ocla_probe1024_mem_depth_32.sv b/EDA-3236/rtl/ocla_probe1024_mem_depth_32.sv new file mode 100644 index 00000000..e6076aad --- /dev/null +++ b/EDA-3236/rtl/ocla_probe1024_mem_depth_32.sv @@ -0,0 +1,161 @@ +// ----------------------------------------------------------------------------- +// Auto-Generated by: __ _ __ _ __ +// / / (_) /____ | |/_/ +// / /__/ / __/ -_)> < +// /____/_/\__/\__/_/|_| +// Build your hardware, easily! +// https://github.com/enjoy-digital/litex +// +// Filename : ocla_wrapper2_v1_0.v +// Device : gemini +// LiteX sha1 : -------- +// Date : 2024-03-22 15:21:07 +//------------------------------------------------------------------------------ +// This file is Copyright (c) 2022 RapidSilicon +//-------------------------------------------------------------------------------- + +`timescale 1ns / 1ps + +//------------------------------------------------------------------------------ +// Module +//------------------------------------------------------------------------------ + +module ocla_probe1024_mem_depth_32 #( + parameter IP_TYPE = "OCLA", + parameter IP_VERSION = 32'h1, + parameter IP_ID = 32'h5633547 +) +( input wire clk, + input wire rstn, + input wire jtag_tck, + input wire jtag_tms, + input wire jtag_tdi, + output wire jtag_tdo, + input wire jtag_trst, + input wire [1023:0] probe_1, + input wire sampling_clk +); + + +//------------------------------------------------------------------------------ +// Signals +//------------------------------------------------------------------------------ + +wire sys_clk; +wire rstn_rst; +wire jtag_tck_1; +wire jtag_tms_1; +wire jtag_tdi_1; +wire jtag_tdo_1; +wire jtag_trst_1; +reg probes_in = 1'd0; +reg [151:0] axilite = 152'd0; +reg [249:0] axifull = 250'd0; +reg axi_sampling_clk = 1'd0; +wire sampling_clk_1; +wire [1023:0] probe_1_1; + +//------------------------------------------------------------------------------ +// Combinatorial Logic +//------------------------------------------------------------------------------ + +assign sys_clk = clk; +assign rstn_rst = rstn; +assign jtag_tck_1 = jtag_tck; +assign jtag_tms_1 = jtag_tms; +assign jtag_tdi_1 = jtag_tdi; +assign jtag_tdo = jtag_tdo_1; +assign jtag_trst_1 = jtag_trst; +assign probe_1_1 = probe_1; +assign sampling_clk_1 = sampling_clk; + + +//------------------------------------------------------------------------------ +// Synchronous Logic +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Specialized Logic +//------------------------------------------------------------------------------ + +ocla_debug_subsystem #( + .AXI_Core_BaseAddress(32'h02000000), + .Cores(1), + .EIO_BaseAddress(32'h01000000), + .EIO_Enable(0), + .IF01_BaseAddress(32'h03000000), + .IF01_Probes(64'h0000000000000001), + .IF02_BaseAddress(32'h04000000), + .IF02_Probes(64'h0000000000000000), + .IF03_BaseAddress(32'h05000000), + .IF03_Probes(64'h0000000000000000), + .IF04_BaseAddress(32'h06000000), + .IF04_Probes(64'h0000000000000000), + .IF05_BaseAddress(32'h07000000), + .IF05_Probes(64'h0000000000000000), + .IF06_BaseAddress(32'h08000000), + .IF06_Probes(64'h0000000000000000), + .IF07_BaseAddress(32'h09000000), + .IF07_Probes(64'h0000000000000000), + .IF08_BaseAddress(32'h01000000), + .IF08_Probes(64'h0000000000000000), + .IF09_BaseAddress(32'h01100000), + .IF09_Probes(64'h0000000000000000), + .IF10_BaseAddress(32'h01200000), + .IF10_Probes(64'h0000000000000000), + .IF11_BaseAddress(32'h01300000), + .IF11_Probes(64'h0000000000000000), + .IF12_BaseAddress(32'h01400000), + .IF12_Probes(64'h0000000000000000), + .IF13_BaseAddress(32'h01500000), + .IF13_Probes(64'h0000000000000000), + .IF14_BaseAddress(32'h01600000), + .IF14_Probes(64'h0000000000000000), + .IF15_BaseAddress(32'h01700000), + .IF15_Probes(64'h0000000000000000), + .IP_ID(IP_ID), + .IP_TYPE(IP_TYPE), + .IP_VERSION(IP_VERSION), + .Mem_Depth(32), + .Mode("NATIVE"), + .No_AXI_Bus(1), + .No_Probes(1), + .Probe01_Width(11'd1024), + .Probe02_Width(11'd0), + .Probe03_Width(11'd0), + .Probe04_Width(11'd0), + .Probe05_Width(11'd0), + .Probe06_Width(11'd0), + .Probe07_Width(11'd0), + .Probe08_Width(11'd0), + .Probe09_Width(11'd0), + .Probe10_Width(11'd0), + .Probe11_Width(11'd0), + .Probe12_Width(11'd0), + .Probe13_Width(11'd0), + .Probe14_Width(11'd0), + .Probe15_Width(11'd0), + .Probes_Sum(14'd1024), + .Sampling_Clk("SINGLE") +) ocla_debug_subsystem ( + .ACLK(sys_clk), + .RESETn(rstn_rst), + .axi4_probes(axifull), + .axiLite_probes(axilite), + .axi_sampling_clk(axi_sampling_clk), + .jtag_tck(jtag_tck_1), + .jtag_tdi(jtag_tdi_1), + .jtag_tms(jtag_tms_1), + .jtag_trst(jtag_trst_1), + .native_sampling_clk(sampling_clk_1), + .probes({probe_1_1}), + .probes_in(probes_in), + .jtag_tdo(jtag_tdo_1) +); + +endmodule + +// ----------------------------------------------------------------------------- +// Auto-Generated by LiteX on 2024-03-22 15:21:07. +//------------------------------------------------------------------------------ diff --git a/EDA-3236/rtl/priority_encoder.v b/EDA-3236/rtl/priority_encoder.v new file mode 100644 index 00000000..cf82512b --- /dev/null +++ b/EDA-3236/rtl/priority_encoder.v @@ -0,0 +1,92 @@ +/* + +Copyright (c) 2014-2021 Alex Forencich + +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. + +*/ + +// Language: Verilog 2001 + +`resetall +`timescale 1ns / 1ps +`default_nettype none + +/* + * Priority encoder module + */ +module priority_encoder # +( + parameter WIDTH = 4, + // LSB priority selection + parameter LSB_HIGH_PRIORITY = 0 +) +( + input wire [WIDTH-1:0] input_unencoded, + output wire output_valid, + output wire [$clog2(WIDTH)-1:0] output_encoded, + output wire [WIDTH-1:0] output_unencoded +); + +parameter LEVELS = WIDTH > 2 ? $clog2(WIDTH) : 1; +parameter W = 2**LEVELS; + +// pad input to even power of two +wire [W-1:0] input_padded = {{W-WIDTH{1'b0}}, input_unencoded}; + +wire [W/2-1:0] stage_valid[LEVELS-1:0]; +wire [W/2-1:0] stage_enc[LEVELS-1:0]; + +generate + genvar l, n; + + // process input bits; generate valid bit and encoded bit for each pair + for (n = 0; n < W/2; n = n + 1) begin : loop_in + assign stage_valid[0][n] = |input_padded[n*2+1:n*2]; + if (LSB_HIGH_PRIORITY) begin + // bit 0 is highest priority + assign stage_enc[0][n] = !input_padded[n*2+0]; + end else begin + // bit 0 is lowest priority + assign stage_enc[0][n] = input_padded[n*2+1]; + end + end + + // compress down to single valid bit and encoded bus + for (l = 1; l < LEVELS; l = l + 1) begin : loop_levels + for (n = 0; n < W/(2*2**l); n = n + 1) begin : loop_compress + assign stage_valid[l][n] = |stage_valid[l-1][n*2+1:n*2]; + if (LSB_HIGH_PRIORITY) begin + // bit 0 is highest priority + assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+0] ? {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]} : {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]}; + end else begin + // bit 0 is lowest priority + assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+1] ? {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]} : {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]}; + end + end + end +endgenerate + +assign output_valid = stage_valid[LEVELS-1]; +assign output_encoded = stage_enc[LEVELS-1]; +assign output_unencoded = 1 << output_encoded; + +endmodule + +`resetall diff --git a/EDA-3236/rtl/sfifo.v b/EDA-3236/rtl/sfifo.v new file mode 100644 index 00000000..78674094 --- /dev/null +++ b/EDA-3236/rtl/sfifo.v @@ -0,0 +1,471 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: sfifo.v +// {{{ +// Project: WB2AXIPSP: bus bridges and other odds and ends +// +// Purpose: A synchronous data FIFO. +// +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// +// Written and distributed by Gisselquist Technology, LLC +// }}} +// This design is hereby granted to the public domain. +// {{{ +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +//////////////////////////////////////////////////////////////////////////////// +// +// +`default_nettype none +// }}} +module sfifo #( + // {{{ + parameter BW=8, // Byte/data width + parameter LGFLEN=4, + parameter [0:0] OPT_ASYNC_READ = 1'b1, + parameter [0:0] OPT_WRITE_ON_FULL = 1'b0, + parameter [0:0] OPT_READ_ON_EMPTY = 1'b0 + // }}} + ) ( + // {{{ + input wire i_clk, + input wire i_reset, + // + // Write interface + input wire i_wr, + input wire [(BW-1):0] i_data, + output reg o_full, + output reg [LGFLEN:0] o_fill, + // + // Read interface + input wire i_rd, + output reg [(BW-1):0] o_data, + output reg o_empty // True if FIFO is empty +`ifdef FORMAL +`ifdef F_PEEK + , output wire [LGFLEN:0] f_first_addr, + output wire [LGFLEN:0] f_second_addr, + output reg [BW-1:0] f_first_data, f_second_data, + + output reg f_first_in_fifo, + f_second_in_fifo, + output reg [LGFLEN:0] f_distance_to_first, + f_distance_to_second +`endif +`endif + // }}} + ); + + // Register/net declarations + // {{{ + localparam FLEN=(1<1) + begin + assert(!r_empty); + end else if ($past(!i_rd && f_fill > 0)) + assert(!r_empty); + end + + always @(*) + if (!r_empty) + begin + // This also applies for the registered read case + assert(mem[rd_addr[LGFLEN-1:0]] == o_data); + end else if (OPT_READ_ON_EMPTY) + assert(o_data == i_data); + + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Formal contract: (Twin write test) + // {{{ + // If you write two values in succession, you should be able to read + // those same two values in succession some time later. + // + //////////////////////////////////////////////////////////////////////// + // + // + + // Verilator lint_off UNDRIVEN + (* anyconst *) reg [LGFLEN:0] fw_first_addr; + // Verilator lint_on UNDRIVEN +`ifndef F_PEEK + wire [LGFLEN:0] f_first_addr; + wire [LGFLEN:0] f_second_addr; + reg [BW-1:0] f_first_data, f_second_data; + + reg f_first_in_fifo, f_second_in_fifo; + reg [LGFLEN:0] f_distance_to_first, f_distance_to_second; +`endif + reg f_first_addr_in_fifo, f_second_addr_in_fifo; + + assign f_first_addr = fw_first_addr; + assign f_second_addr = f_first_addr + 1; + + always @(*) + begin + f_distance_to_first = (f_first_addr - rd_addr); + f_first_addr_in_fifo = 0; + if ((f_fill != 0) && (f_distance_to_first < f_fill)) + f_first_addr_in_fifo = 1; + end + + always @(*) + begin + f_distance_to_second = (f_second_addr - rd_addr); + f_second_addr_in_fifo = 0; + if ((f_fill != 0) && (f_distance_to_second < f_fill)) + f_second_addr_in_fifo = 1; + end + + always @(posedge i_clk) + if (w_wr && wr_addr == f_first_addr) + f_first_data <= i_data; + + always @(posedge i_clk) + if (w_wr && wr_addr == f_second_addr) + f_second_data <= i_data; + + always @(*) + if (f_first_addr_in_fifo) + assert(mem[f_first_addr[LGFLEN-1:0]] == f_first_data); + always @(*) + f_first_in_fifo = (f_first_addr_in_fifo && (mem[f_first_addr[LGFLEN-1:0]] == f_first_data)); + + always @(*) + if (f_second_addr_in_fifo) + assert(mem[f_second_addr[LGFLEN-1:0]] == f_second_data); + + always @(*) + f_second_in_fifo = (f_second_addr_in_fifo && (mem[f_second_addr[LGFLEN-1:0]] == f_second_data)); + + always @(posedge i_clk) + if (f_past_valid && !$past(i_reset)) + begin + case({$past(f_first_in_fifo), $past(f_second_in_fifo)}) + 2'b00: begin + if ($past(w_wr && (!w_rd || !r_empty)) + &&($past(wr_addr == f_first_addr))) + begin + assert(f_first_in_fifo); + end else begin + assert(!f_first_in_fifo); + end + // + // The second could be in the FIFO, since + // one might write other data than f_first_data + // + // assert(!f_second_in_fifo); + end + 2'b01: begin + assert(!f_first_in_fifo); + if ($past(w_rd && (rd_addr==f_second_addr))) + begin + assert((o_empty&&!OPT_ASYNC_READ)||!f_second_in_fifo); + end else begin + assert(f_second_in_fifo); + end + end + 2'b10: begin + if ($past(w_wr) + &&($past(wr_addr == f_second_addr))) + begin + assert(f_second_in_fifo); + end else begin + assert(!f_second_in_fifo); + end + if ($past(!w_rd ||(rd_addr != f_first_addr))) + assert(f_first_in_fifo); + end + 2'b11: begin + assert(f_second_in_fifo); + if ($past(!w_rd ||(rd_addr != f_first_addr))) + begin + assert(f_first_in_fifo); + if (rd_addr == f_first_addr) + assert(o_data == f_first_data); + end else begin + assert(!f_first_in_fifo); + assert(o_data == f_second_data); + end + end + endcase + end + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Cover properties + // {{{ + //////////////////////////////////////////////////////////////////////// + // + // +`ifdef SFIFO + reg f_was_full; + initial f_was_full = 0; + always @(posedge i_clk) + if (o_full) + f_was_full <= 1; + + always @(posedge i_clk) + cover($fell(f_empty)); + + always @(posedge i_clk) + cover($fell(o_empty)); + + always @(posedge i_clk) + cover(f_was_full && f_empty); + + always @(posedge i_clk) + cover($past(o_full,2)&&(!$past(o_full))&&(o_full)); + + always @(posedge i_clk) + if (f_past_valid) + cover($past(o_empty,2)&&(!$past(o_empty))&& o_empty); +`endif + // }}} + + // Make Verilator happy + // Verilator lint_off UNUSED + wire unused_formal; + assign unused_formal = &{ 1'b0, f_next[LGFLEN], f_empty }; + // Verilator lint_on UNUSED +`endif // FORMAL +// }}} +endmodule +`ifndef YOSYS +`default_nettype wire +`endif diff --git a/EDA-3236/rtl/skidbuffer.v b/EDA-3236/rtl/skidbuffer.v new file mode 100644 index 00000000..6388271f --- /dev/null +++ b/EDA-3236/rtl/skidbuffer.v @@ -0,0 +1,487 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: skidbuffer.v +// {{{ +// Project: WB2AXIPSP: bus bridges and other odds and ends +// +// Purpose: A basic SKID buffer. +// {{{ +// Skid buffers are required for high throughput AXI code, since the AXI +// specification requires that all outputs be registered. This means +// that, if there are any stall conditions calculated, it will take a clock +// cycle before the stall can be propagated up stream. This means that +// the data will need to be buffered for a cycle until the stall signal +// can make it to the output. +// +// Handling that buffer is the purpose of this core. +// +// On one end of this core, you have the i_valid and i_data inputs to +// connect to your bus interface. There's also a registered o_ready +// signal to signal stalls for the bus interface. +// +// The other end of the core has the same basic interface, but it isn't +// registered. This allows you to interact with the bus interfaces +// as though they were combinatorial logic, by interacting with this half +// of the core. +// +// If at any time the incoming !stall signal, i_ready, signals a stall, +// the incoming data is placed into a buffer. Internally, that buffer +// is held in r_data with the r_valid flag used to indicate that valid +// data is within it. +// }}} +// Parameters: +// {{{ +// DW or data width +// In order to make this core generic, the width of the data in the +// skid buffer is parameterized +// +// OPT_LOWPOWER +// Forces both o_data and r_data to zero if the respective *VALID +// signal is also low. While this costs extra logic, it can also +// be used to guarantee that any unused values aren't toggling and +// therefore unnecessarily using power. +// +// This excess toggling can be particularly problematic if the +// bus signals have a high fanout rate, or a long signal path +// across an FPGA. +// +// OPT_OUTREG +// Causes the outputs to be registered +// +// OPT_PASSTHROUGH +// Turns the skid buffer into a passthrough. Used for formal +// verification only. +// }}} +// Creator: Dan Gisselquist, Ph.D. +// Gisselquist Technology, LLC +// +//////////////////////////////////////////////////////////////////////////////// +// }}} +// Copyright (C) 2019-2022, Gisselquist Technology, LLC +// {{{ +// This file is part of the WB2AXIP project. +// +// The WB2AXIP project contains free software and gateware, licensed under the +// Apache License, Version 2.0 (the "License"). You may not use this project, +// or 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. +// +//////////////////////////////////////////////////////////////////////////////// +// +// +`default_nettype none +// }}} +module skidbuffer #( + // {{{ + parameter [0:0] OPT_LOWPOWER = 0, + parameter [0:0] OPT_OUTREG = 1, + // + parameter [0:0] OPT_PASSTHROUGH = 0, + parameter DW = 8, + parameter [0:0] OPT_INITIAL = 1'b1 + // }}} + ) ( + // {{{ + input wire i_clk, i_reset, + input wire i_valid, + output wire o_ready, + input wire [DW-1:0] i_data, + output wire o_valid, + input wire i_ready, + output reg [DW-1:0] o_data + // }}} + ); + + wire [DW-1:0] w_data; + + generate if (OPT_PASSTHROUGH) + begin : PASSTHROUGH + // {{{ + assign { o_valid, o_ready } = { i_valid, i_ready }; + + always @(*) + if (!i_valid && OPT_LOWPOWER) + o_data = 0; + else + o_data = i_data; + + assign w_data = 0; + // }}} + end else begin : LOGIC + // We'll start with skid buffer itself + // {{{ + reg r_valid; + reg [DW-1:0] r_data; + + // r_valid + // {{{ + initial if (OPT_INITIAL) r_valid = 0; + always @(posedge i_clk) + if (i_reset) + r_valid <= 0; + else if ((i_valid && o_ready) && (o_valid && !i_ready)) + // We have incoming data, but the output is stalled + r_valid <= 1; + else if (i_ready) + r_valid <= 0; + // }}} + + // r_data + // {{{ + initial if (OPT_INITIAL) r_data = 0; + always @(posedge i_clk) + if (OPT_LOWPOWER && i_reset) + r_data <= 0; + else if (OPT_LOWPOWER && (!o_valid || i_ready)) + r_data <= 0; + else if ((!OPT_LOWPOWER || !OPT_OUTREG || i_valid) && o_ready) + r_data <= i_data; + + assign w_data = r_data; + // }}} + + // o_ready + // {{{ + assign o_ready = !r_valid; + // }}} + + // + // And then move on to the output port + // + if (!OPT_OUTREG) + begin : NET_OUTPUT + // Outputs are combinatorially determined from inputs + // {{{ + // o_valid + // {{{ + assign o_valid = !i_reset && (i_valid || r_valid); + // }}} + + // o_data + // {{{ + always @(*) + if (r_valid) + o_data = r_data; + else if (!OPT_LOWPOWER || i_valid) + o_data = i_data; + else + o_data = 0; + // }}} + // }}} + end else begin : REG_OUTPUT + // Register our outputs + // {{{ + // o_valid + // {{{ + reg ro_valid; + + initial if (OPT_INITIAL) ro_valid = 0; + always @(posedge i_clk) + if (i_reset) + ro_valid <= 0; + else if (!o_valid || i_ready) + ro_valid <= (i_valid || r_valid); + + assign o_valid = ro_valid; + // }}} + + // o_data + // {{{ + initial if (OPT_INITIAL) o_data = 0; + always @(posedge i_clk) + if (OPT_LOWPOWER && i_reset) + o_data <= 0; + else if (!o_valid || i_ready) + begin + + if (r_valid) + o_data <= r_data; + else if (!OPT_LOWPOWER || i_valid) + o_data <= i_data; + else + o_data <= 0; + end + // }}} + + // }}} + end + // }}} + end endgenerate + + // Keep Verilator happy + // {{{ + // Verilator lint_off UNUSED + wire unused; + assign unused = &{ 1'b0, w_data }; + // Verilator lint_on UNUSED + // }}} +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// +// Formal properties +// {{{ +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +`ifdef FORMAL +`ifdef SKIDBUFFER +`define ASSUME assume +`else +`define ASSUME assert +`endif + + reg f_past_valid; + + initial f_past_valid = 0; + always @(posedge i_clk) + f_past_valid <= 1; + + always @(*) + if (!f_past_valid) + assume(i_reset); + + //////////////////////////////////////////////////////////////////////// + // + // Incoming stream properties / assumptions + // {{{ + //////////////////////////////////////////////////////////////////////// + // + always @(posedge i_clk) + if (!f_past_valid) + begin + `ASSUME(!i_valid || !OPT_INITIAL); + end else if ($past(i_valid && !o_ready && !i_reset) && !i_reset) + `ASSUME(i_valid && $stable(i_data)); + +`ifdef VERIFIC +`define FORMAL_VERIFIC + // Reset properties + property RESET_CLEARS_IVALID; + @(posedge i_clk) i_reset |=> !i_valid; + endproperty + + property IDATA_HELD_WHEN_NOT_READY; + @(posedge i_clk) disable iff (i_reset) + i_valid && !o_ready |=> i_valid && $stable(i_data); + endproperty + +`ifdef SKIDBUFFER + assume property (IDATA_HELD_WHEN_NOT_READY); +`else + assert property (IDATA_HELD_WHEN_NOT_READY); +`endif +`endif + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Outgoing stream properties / assumptions + // {{{ + //////////////////////////////////////////////////////////////////////// + // + + generate if (!OPT_PASSTHROUGH) + begin + + always @(posedge i_clk) + if (!f_past_valid) // || $past(i_reset)) + begin + // Following any reset, valid must be deasserted + assert(!o_valid || !OPT_INITIAL); + end else if ($past(o_valid && !i_ready && !i_reset) && !i_reset) + // Following any stall, valid must remain high and + // data must be preserved + assert(o_valid && $stable(o_data)); + + end endgenerate + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Other properties + // {{{ + //////////////////////////////////////////////////////////////////////// + // + // + generate if (!OPT_PASSTHROUGH) + begin + // Rule #1: + // If registered, then following any reset we should be + // ready for a new request + // {{{ + always @(posedge i_clk) + if (f_past_valid && $past(OPT_OUTREG && i_reset)) + assert(o_ready); + // }}} + + // Rule #2: + // All incoming data must either go directly to the + // output port, or into the skid buffer + // {{{ +`ifndef VERIFIC + always @(posedge i_clk) + if (f_past_valid && !$past(i_reset) && $past(i_valid && o_ready + && (!OPT_OUTREG || o_valid) && !i_ready)) + assert(!o_ready && w_data == $past(i_data)); +`else + assert property (@(posedge i_clk) + disable iff (i_reset) + (i_valid && o_ready + && (!OPT_OUTREG || o_valid) && !i_ready) + |=> (!o_ready && w_data == $past(i_data))); +`endif + // }}} + + // Rule #3: + // After the last transaction, o_valid should become idle + // {{{ + if (!OPT_OUTREG) + begin + // {{{ + always @(posedge i_clk) + if (f_past_valid && !$past(i_reset) && !i_reset + && $past(i_ready)) + begin + assert(o_valid == i_valid); + assert(!i_valid || (o_data == i_data)); + end + // }}} + end else begin + // {{{ + always @(posedge i_clk) + if (f_past_valid && !$past(i_reset)) + begin + if ($past(i_valid && o_ready)) + assert(o_valid); + + if ($past(!i_valid && o_ready && i_ready)) + assert(!o_valid); + end + // }}} + end + // }}} + + // Rule #4 + // Same thing, but this time for o_ready + // {{{ + always @(posedge i_clk) + if (f_past_valid && $past(!o_ready && i_ready)) + assert(o_ready); + // }}} + + // If OPT_LOWPOWER is set, o_data and w_data both need to be + // zero any time !o_valid or !r_valid respectively + // {{{ + if (OPT_LOWPOWER) + begin + always @(*) + if ((OPT_OUTREG || !i_reset) && !o_valid) + assert(o_data == 0); + + always @(*) + if (o_ready) + assert(w_data == 0); + + end + // }}} + end endgenerate + // }}} + //////////////////////////////////////////////////////////////////////// + // + // Cover checks + // {{{ + //////////////////////////////////////////////////////////////////////// + // + // +`ifdef SKIDBUFFER + generate if (!OPT_PASSTHROUGH) + begin + reg f_changed_data; + + initial f_changed_data = 0; + always @(posedge i_clk) + if (i_reset) + f_changed_data <= 1; + else if (i_valid && $past(!i_valid || o_ready)) + begin + if (i_data != $past(i_data + 1)) + f_changed_data <= 0; + end else if (!i_valid && i_data != 0) + f_changed_data <= 0; + + +`ifndef VERIFIC + reg [3:0] cvr_steps, cvr_hold; + + always @(posedge i_clk) + if (i_reset) + begin + cvr_steps <= 0; + cvr_hold <= 0; + end else begin + cvr_steps <= cvr_steps + 1; + cvr_hold <= cvr_hold + 1; + case(cvr_steps) + 0: if (o_valid || i_valid) + cvr_steps <= 0; + 1: if (!i_valid || !i_ready) + cvr_steps <= 0; + 2: if (!i_valid || !i_ready) + cvr_steps <= 0; + 3: if (!i_valid || !i_ready) + cvr_steps <= 0; + 4: if (!i_valid || i_ready) + cvr_steps <= 0; + 5: if (!i_valid || !i_ready) + cvr_steps <= 0; + 6: if (!i_valid || !i_ready) + cvr_steps <= 0; + 7: if (!i_valid || i_ready) + cvr_steps <= 0; + 8: if (!i_valid || i_ready) + cvr_steps <= 0; + 9: if (!i_valid || !i_ready) + cvr_steps <= 0; + 10: if (!i_valid || !i_ready) + cvr_steps <= 0; + 11: if (!i_valid || !i_ready) + cvr_steps <= 0; + 12: begin + cvr_steps <= cvr_steps; + cover(!o_valid && !i_valid && f_changed_data); + if (!o_valid || !i_ready) + cvr_steps <= 0; + else + cvr_hold <= cvr_hold + 1; + end + default: assert(0); + endcase + end + +`else + // Cover test + cover property (@(posedge i_clk) + disable iff (i_reset) + (!o_valid && !i_valid) + ##1 i_valid && i_ready [*3] + ##1 i_valid && !i_ready + ##1 i_valid && i_ready [*2] + ##1 i_valid && !i_ready [*2] + ##1 i_valid && i_ready [*3] + // Wait for the design to clear + ##1 o_valid && i_ready [*0:5] + ##1 (!o_valid && !i_valid && f_changed_data)); +`endif + end endgenerate +`endif // SKIDBUFFER + // }}} +`endif +// }}} +endmodule diff --git a/EDA-3236/rtl/tap_top.sv b/EDA-3236/rtl/tap_top.sv new file mode 100644 index 00000000..1a48184f --- /dev/null +++ b/EDA-3236/rtl/tap_top.sv @@ -0,0 +1,522 @@ +// start of the code + +// Length of the Instruction register +`define IR_LENGTH 5 + +// Supported Instructions +// no EXTEST support? +`define IDCODE 5'b00010 +`define REG1 5'b00100 +`define REG2 5'b01000 +`define BYPASS 5'b11111 // JTAG's standard requires all bits in IR to be 1 + +// Top module +module tap_top + #( + // manufacturer = PULP Platform, part number = 0, version = 1 + parameter IDCODE_VALUE = 32'h10000db3 + ) + ( + // JTAG pins + input tms_i, // JTAG test mode select pad + input tck_i, // JTAG test clock pad + input rst_ni, // JTAG test reset pad (actually ~trst), since trst is active low, + input td_i, // JTAG test data input pad + output reg td_o, // JTAG test data output pad + //output tdo_padoe_o // Output enable for JTAG test data output pad + + // TAP states + output shift_dr_o, + output update_dr_o, + output capture_dr_o, + + // TDO signal that is connected to TDI of sub-modules. + output scan_in_o, + + // Select signals for boundary scan or mbist + output axi_data_in_sel_o, + output axi_data_out_sel_o, + + // TDI signals from sub-modules + input axi_data_in_tdo, // from reg1 module + input axi_data_out_tdo, // from reg2 module + + // CTA signals for AXI registers + output axi_in_cta, + output axi_out_cta, + + // update edge detectors + output updatedr_fedge + ); + + // TAPC FSM state registers + reg test_logic_reset; // FSM state + reg run_test_idle; // FSM state + reg sel_dr_scan; // FSM state + reg capture_dr; // FSM state + reg shift_dr; // FSM state + reg exit1_dr; // FSM state + reg pause_dr; // FSM state + reg exit2_dr; // FSM state + reg update_dr; // FSM state + reg sel_ir_scan; // FSM state + reg capture_ir; // FSM state + reg shift_ir; // FSM state + reg shift_ir_neg; + reg exit1_ir; // FSM state + reg pause_ir; // FSM state + reg exit2_ir; // FSM state + reg update_ir; // FSM state + + // registers + reg idcode_sel; + reg axi_data_in_sel; + reg axi_data_out_sel; + reg bypass_sel; + + reg updatedr_fe; + + reg tdo_comb; + reg tms_q1, tms_q2, tms_q3, tms_q4; + wire tms_reset; + + assign scan_in_o = td_i; + assign shift_dr_o = shift_dr; + assign update_dr_o = update_dr; + assign capture_dr_o = capture_dr; + + assign axi_data_in_sel_o = axi_data_in_sel; + assign axi_data_out_sel_o = axi_data_out_sel; + + assign updatedr_fedge = ((updatedr_fe == 1) & (update_dr == 0)); + + always @ (posedge tck_i) + begin + tms_q1 <= tms_i; + tms_q2 <= tms_q1; + tms_q3 <= tms_q2; + tms_q4 <= tms_q3; + end + + always @ (posedge tck_i) + begin + updatedr_fe <= update_dr; + end + + // the 5-TMS-ticks reset + assign tms_reset = tms_q1 & tms_q2 & tms_q3 & tms_q4 & tms_i; // 5 consecutive TMS=1 causes reset + + /********************************************************************************** + * * + * TAP State Machine: Fully JTAG compliant * + * * + **********************************************************************************/ + + // Not exactly how I thought one would implement an FSM but this is pretty straightforward as well + + // test_logic_reset state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + test_logic_reset <= 1'b1; + else if (tms_reset) + test_logic_reset <= 1'b1; + else + begin + if(tms_i & (test_logic_reset | sel_ir_scan)) + test_logic_reset <= 1'b1; + else + test_logic_reset <= 1'b0; + end + end + + // run_test_idle state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + run_test_idle<= 1'b0; + else if (tms_reset) + run_test_idle<= 1'b0; + else + if(~tms_i & (test_logic_reset | run_test_idle | update_dr | update_ir)) + run_test_idle<= 1'b1; + else + run_test_idle<= 1'b0; + end + + // sel_dr_scan state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + sel_dr_scan<= 1'b0; + else if (tms_reset) + sel_dr_scan<= 1'b0; + else + if(tms_i & (run_test_idle | update_dr | update_ir)) + sel_dr_scan<= 1'b1; + else + sel_dr_scan<= 1'b0; + end + + // capture_dr state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + capture_dr<= 1'b0; + else if (tms_reset) + capture_dr<= 1'b0; + else + if(~tms_i & sel_dr_scan) + capture_dr<= 1'b1; + else + capture_dr<= 1'b0; + end + + // shift_dr state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + shift_dr<= 1'b0; + else if (tms_reset) + shift_dr<= 1'b0; + else + if(~tms_i & (capture_dr | shift_dr | exit2_dr)) + shift_dr<= 1'b1; + else + shift_dr<= 1'b0; + end + + // exit1_dr state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + exit1_dr<= 1'b0; + else if (tms_reset) + exit1_dr<= 1'b0; + else + if(tms_i & (capture_dr | shift_dr)) + exit1_dr<= 1'b1; + else + exit1_dr<= 1'b0; + end + + // pause_dr state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + pause_dr<= 1'b0; + else if (tms_reset) + pause_dr<= 1'b0; + else + if(~tms_i & (exit1_dr | pause_dr)) + pause_dr<= 1'b1; + else + pause_dr<= 1'b0; + end + + // exit2_dr state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + exit2_dr<= 1'b0; + else if (tms_reset) + exit2_dr<= 1'b0; + else + if(tms_i & pause_dr) + exit2_dr<= 1'b1; + else + exit2_dr<= 1'b0; + end + + // update_dr state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + update_dr<= 1'b0; + else if (tms_reset) + update_dr<= 1'b0; + else + if(tms_i & (exit1_dr | exit2_dr)) + update_dr<= 1'b1; + else + update_dr<= 1'b0; + end + + // sel_ir_scan state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + sel_ir_scan<= 1'b0; + else if (tms_reset) + sel_ir_scan<= 1'b0; + else + if(tms_i & sel_dr_scan) + sel_ir_scan<= 1'b1; + else + sel_ir_scan<= 1'b0; + end + + // capture_ir state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + capture_ir<= 1'b0; + else if (tms_reset) + capture_ir<= 1'b0; + else + if(~tms_i & sel_ir_scan) + capture_ir<= 1'b1; + else + capture_ir<= 1'b0; + end + + // shift_ir state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + shift_ir<= 1'b0; + else if (tms_reset) + shift_ir<= 1'b0; + else + if(~tms_i & (capture_ir | shift_ir | exit2_ir)) + shift_ir<= 1'b1; + else + shift_ir<= 1'b0; + end + + // exit1_ir state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + exit1_ir<= 1'b0; + else if (tms_reset) + exit1_ir<= 1'b0; + else + if(tms_i & (capture_ir | shift_ir)) + exit1_ir<= 1'b1; + else + exit1_ir<= 1'b0; + end + + // pause_ir state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + pause_ir<= 1'b0; + else if (tms_reset) + pause_ir<= 1'b0; + else + if(~tms_i & (exit1_ir | pause_ir)) + pause_ir<= 1'b1; + else + pause_ir<= 1'b0; + end + + // exit2_ir state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + exit2_ir<= 1'b0; + else if (tms_reset) + exit2_ir<= 1'b0; + else + if(tms_i & pause_ir) + exit2_ir<= 1'b1; + else + exit2_ir<= 1'b0; + end + + // update_ir state + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + update_ir<= 1'b0; + else if (tms_reset) + update_ir<= 1'b0; + else + if(tms_i & (exit1_ir | exit2_ir)) + update_ir<= 1'b1; + else + update_ir<= 1'b0; + end + + /********************************************************************************** + * * + * End: TAP State Machine * + * * + **********************************************************************************/ + + + + /********************************************************************************** + * * + * jtag_ir: JTAG Instruction Register * + * * + **********************************************************************************/ + reg [`IR_LENGTH-1:0] jtag_ir; // Instruction register + reg [`IR_LENGTH-1:0] latched_jtag_ir, latched_jtag_ir_neg; + wire instruction_tdo; + + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + jtag_ir[`IR_LENGTH-1:0] <= `IR_LENGTH'b0; + else if(capture_ir) + jtag_ir <= 5'b00101; // This value is fixed for easier fault detection + else if(shift_ir) + jtag_ir[`IR_LENGTH-1:0] <= {td_i, jtag_ir[`IR_LENGTH-1:1]}; + end + + assign instruction_tdo = jtag_ir[0]; // the shift-out line that does the magic + /********************************************************************************** + * * + * End: jtag_ir * + * * + **********************************************************************************/ + + + + /********************************************************************************** + * * + * idcode logic * + * * + **********************************************************************************/ + reg [31:0] idcode_reg; + wire idcode_tdo; + + always @ (posedge tck_i or negedge rst_ni) + begin + if (~rst_ni) + idcode_reg <= IDCODE_VALUE; + else if(idcode_sel & shift_dr) + idcode_reg <= {td_i, idcode_reg[31:1]}; + else if(idcode_sel & (capture_dr | exit1_dr)) + idcode_reg <= IDCODE_VALUE; + end + + assign idcode_tdo = idcode_reg[0]; + + /********************************************************************************** + * * + * End: idcode logic * + * * + **********************************************************************************/ + + + /********************************************************************************** + * * + * Bypass logic * + * * + **********************************************************************************/ + wire bypassed_tdo; + reg bypass_reg; + + always @ (posedge tck_i or negedge rst_ni) + begin + if (~rst_ni) + bypass_reg <= 1'b0; + else if(shift_dr) + bypass_reg <= td_i; + end + + assign bypassed_tdo = bypass_reg; + /********************************************************************************** + * * + * End: Bypass logic * + * * + **********************************************************************************/ + + + /********************************************************************************** + * * + * Activating Instructions * + * * + **********************************************************************************/ + // Updating jtag_ir (Instruction Register) + always @ (posedge tck_i or negedge rst_ni) + begin + if(~rst_ni) + latched_jtag_ir <= `IDCODE; // IDCODE seled after reset + else if (tms_reset) + latched_jtag_ir <= `IDCODE; // IDCODE seled after reset + else if(update_ir) + latched_jtag_ir <= jtag_ir; + end + + /********************************************************************************** + * * + * End: Activating Instructions * + * * + **********************************************************************************/ + + + // Updating jtag_ir (Instruction Register) + always @ (latched_jtag_ir) + begin + idcode_sel = 1'b0; + axi_data_in_sel = 1'b0; + axi_data_out_sel = 1'b0; + bypass_sel = 1'b0; + + // only works after the update_ir is detected on a +edge of tck + case(latched_jtag_ir) /* synthesis parallel_case */ + `IDCODE: idcode_sel = 1'b1; // ID Code + `REG1: axi_data_in_sel = 1'b1; // REG1 + `REG2: axi_data_out_sel = 1'b1; // REG2 + default: bypass_sel = 1'b1; // BYPASS + endcase + end + + /********************************************************************************** + * * + * Multiplexing TDO data * + * * + **********************************************************************************/ + always @ (*) + begin + if(shift_ir_neg) + tdo_comb = instruction_tdo; // Instruction register + else + begin + case(latched_jtag_ir_neg) // synthesis parallel_case + `IDCODE: tdo_comb = idcode_tdo; // Reading ID code + `REG1: tdo_comb = axi_data_in_tdo; // REG1 + `REG2: tdo_comb = axi_data_out_tdo; // REG2 + `BYPASS: tdo_comb = bypassed_tdo; // BYPASS + + default: tdo_comb = bypassed_tdo; // BYPASS instruction + endcase + end + end + + + // Tristate control for td_o pin + always @ (negedge tck_i) + begin + td_o <= tdo_comb; + // tdo_padoe_o <= shift_ir | shift_dr; + end + /********************************************************************************** + * * + * End: Multiplexing TDO data * + * * + **********************************************************************************/ + + always @ (negedge tck_i) + begin + shift_ir_neg <= shift_ir; + latched_jtag_ir_neg <= latched_jtag_ir; + end + + /********************************************************************************** + * * + * Generating selects for AXI registers * + * * + **********************************************************************************/ + + // CTA signals: Clear to Access meaning the JTAG is not reading/writing a particulat register + + assign axi_in_cta = !(axi_data_in_sel && (capture_dr | shift_dr | exit1_dr | pause_dr | exit2_dr | update_dr)); + assign axi_out_cta = !(axi_data_out_sel && (capture_dr | shift_dr | exit1_dr | pause_dr | exit2_dr | update_dr)); + +endmodule diff --git a/EDA-3238/raptor.tcl b/EDA-3238/raptor.tcl new file mode 100644 index 00000000..83ece6f5 --- /dev/null +++ b/EDA-3238/raptor.tcl @@ -0,0 +1,25 @@ +create_design fifo_generator_default +target_device 1VG28 +configure_ip fifo_generator_v1_0 -mod_name fifo_generator_default -Pdata_width=36 -Pdepth=1024 -out_file ./fifo_generator_default/run_1/IPs/fifo_generator_default +ipgenerate +add_include_path ./fifo_generator_default/run_1/IPs/rapidsilicon/ip/fifo_generator/v1_0/fifo_generator_default/src/ +add_library_ext .v .sv +add_library_path ./fifo_generator_default/run_1/IPs/rapidsilicon/ip/fifo_generator/v1_0/fifo_generator_default/src/ +add_design_file ./fifo_generator_default/run_1/IPs/rapidsilicon/ip/fifo_generator/v1_0/fifo_generator_default/src/fifo_generator_default\_v1_0.v +set_top_module fifo_generator_default +analyze +synth_options -new_tdp36k +synthesize delay +setup_lec_sim +simulation_options compilation icarus gate +simulate gate icarus +pin_loc_assign_method free +packing +place +route +simulation_options compilation icarus pnr +simulate pnr icarus +sta +power +bitstream +