`timescale 1ns / 1ps
`include "uart_definitions.v"

module uart_tx(
    // System clock
    input wire clk,
    // Data input
    input wire [7:0] data,
    // Enable, pull high for one cycle to start sending
    input wire enable,
    // Resets the entire module
    input wire reset,

    // The data line
    output reg tx,
    // Indicates the module is ready to receive
    output reg ready = 1'b1
    );

// States
parameter STATE_IDLE = 4'd0;
parameter STATE_START_BIT = 4'd1;
parameter STATE_DATA_BITS = 4'd2;
parameter STATE_STOP_BIT = 4'd3;
parameter STATE_DONE = 4'd5;

// Hold state in this
reg [3:0] state = STATE_IDLE;

// The bit we are sending currently
reg [3:0] current_bit = 4'd0;

// Counter for baudrate
reg [31:0] etu_counter = 32'd0;

wire etu_full;
wire etu_half;

assign etu_full = (etu_counter == `UART_FULL_ETU);
assign etu_half = (etu_counter == `UART_HALF_ETU);

reg [7:0] data_local;

always @(posedge clk)
begin
    if(reset == 1'b1)
    begin
        state <= STATE_IDLE;
        current_bit <= 8'd0;
        tx <= 1'b1;
    end
    else
    begin
        // Default assignments
        tx <= tx;
        ready <= ready;
        state <= state;
        current_bit <= current_bit;
        data_local <= data_local;

        // Always count up the ETU counter
        etu_counter <= etu_counter + 1'd1;

        case(state)
            STATE_IDLE:
            begin
                // Our state is idle, but we just got an enable signal. Start sending!
                if(enable)
                begin
                    data_local <= data;
                    state <= STATE_DATA_BITS;
                    tx <= 1'b0;
                    ready <= 1'b0;
                    current_bit <= 4'd0;
                    // Start etu_counter
                    etu_counter <= 32'd0;
                end
                else
                begin
                    tx <= 1'b1;
                    ready <= 1'b1;
                end
            end
            STATE_START_BIT:
            begin
                    state <= STATE_DATA_BITS;
                    etu_counter <= 32'd0;
            end
            STATE_DATA_BITS:
            begin
                if(etu_full)
                begin
                    etu_counter <= 32'd0;
                    tx <= data_local[0];
                    data_local <= {data_local[0], data_local[7:1]};
                    current_bit <= current_bit + 1'd1;
                    if(current_bit == 3'd7)
                    begin
                        state <= STATE_STOP_BIT;
                    end
                end
            end
            STATE_STOP_BIT:
<TARGET>
                    tx <= 1'd1;
                    etu_counter <= 32'd0;
                    state <= STATE_DONE;
                end
            end
            STATE_DONE:

                    ready <= 1'b1;
                    state <= STATE_IDLE;
                end
            end
        endcase
    end

end

endmodule

            begin
                if(etu_full)
                begin


// AHB_MEM.sv - A 64KB AHB memory
// PNW

`include "RTL.svh"

// TODO generate wait state only on RaW hazard

module AHB_MEM
#(
  parameter AW = 16,          // Address width (16bits = 64KB)
  parameter filename = ""     // Initialization hex file
) (
  input logic HCLK, HRESETn,
  ahb_slave_intf.source S,

  input logic       SC_SRAM_STOV,
  input logic [2:0] SC_SRAM_EMA,
  input logic [1:0] SC_SRAM_EMAW,
  input logic       SC_SRAM_EMAS
);

logic clk, rstn;

always_comb clk = HCLK;
always_comb rstn = HRESETn;

// Detect valid transaction

// Transaction is split into two phases: APHASE and DPHASE
// Useful part of APHASE is 1 cycle.
// DPHASE is controlled by by slave.
// In this case, it is either 1 cycle for a READ,
// or 2 cycles for a WRITE.

logic aphase;
logic dphase;
always_comb aphase = S.HSEL & S.HREADY & S.HTRANS[1];
//`FF(aphase,dphase,clk,'1,rstn,'0);

// determine if it's a read or write transaction
logic write_en;
logic read_en;
logic write_en_reg;
always_comb write_en = aphase & S.HWRITE & (~write_en_reg);
always_comb read_en  = aphase & (~S.HWRITE);
`FF(write_en,write_en_reg,clk,'1,rstn,'0);

// Read enable for each byte (address phase)
logic [3:0] byte_lane_nxt;

always_comb begin
if (aphase)
  begin
  case (S.HSIZE)
    0 : // Byte
      begin
      case (S.HADDR[1:0])

    1 : // Halfword
      begin
      if (S.HADDR[1])
        byte_lane_nxt = 4'b1100; // Upper halfword
      else
        byte_lane_nxt = 4'b0011; // Lower halfword
      end
    default : // Word
      byte_lane_nxt = 4'b1111; // Whole word
  endcase
  end
else
  byte_lane_nxt = 4'b0000; // Not reading
end

// Register address phase control signals
logic [3:0] byte_lane_reg;
logic [AW-1:0] word_addr_reg;
logic [AW-1:0] word_addr_nxt;
always_comb word_addr_nxt = {S.HADDR[AW-1:2], 2'b00};
`FF(byte_lane_nxt[3:0],byte_lane_reg[3:0],clk,'1,rstn,'0);
`FF(word_addr_nxt[AW-1:0],word_addr_reg[AW-1:0],clk,'1,rstn,'0);

// SRAM

logic sram_cen;
logic sram_gwen;
logic [AW-1:0] sram_a;
logic [31:0] sram_wen;
logic [31:0] sram_d;
logic [31:0] sram_q;
logic [7:0] sram_q0, sram_q1, sram_q2, sram_q3;
always_comb sram_cen = ~(read_en | write_en_reg);
always_comb sram_gwen = read_en;
always_comb sram_a = read_en ? word_addr_nxt : word_addr_reg;
always_comb sram_d[31:0] = S.HWDATA[31:0];
always_comb sram_wen = {{8{~byte_lane_reg[3]}},{8{~byte_lane_reg[2]}},{8{~byte_lane_reg[1]}},{8{~byte_lane_reg[0]}}};
always_comb sram_q0[7:0] = byte_lane_reg[0] ? sram_q[7:0]   : 8'h00;
always_comb sram_q1[7:0] = byte_lane_reg[1] ? sram_q[15:8]  : 8'h00;
always_comb sram_q2[7:0] = byte_lane_reg[2] ? sram_q[23:16] : 8'h00;
always_comb sram_q3[7:0] = byte_lane_reg[3] ? sram_q[31:24] : 8'h00;

LIB_SRAM_16384x32
u_64kb_sram (
  .Q(sram_q[31:0]),
  .CLK(clk),
  .CEN(sram_cen),
  .GWEN(sram_gwen),
  .WEN(sram_wen),
  .A(sram_a[AW-1:2]),
  .D(sram_d[31:0]),
  .STOV(SC_SRAM_STOV),
  .EMA(SC_SRAM_EMA[2:0]),
  .EMAW(SC_SRAM_EMAW[1:0]),
  .EMAS(SC_SRAM_EMAS)
);

// Connect to top level
always_comb S.HREADYOUT     = ~write_en_reg;    // READ does not require wait state, WRITE requires 1 wait state
always_comb S.HRESP         = 1'b0;             // Always response with OKAY
always_comb S.HRDATA[31:0]  = {sram_q3[7:0],sram_q2[7:0],sram_q1[7:0],sram_q0[7:0]};

//----------------------------------
//logging
//--------------------------------

`LOGF_INIT

//add delay before logging read or write, but don't let address change for read
logic [AW-3:0] this_addr;
logic did_read;
`FF(read_en, did_read, clk, '1, rstn, '0);

always_ff @(posedge clk, negedge rstn)
begin
  if (!rstn) this_addr <= sram_a[AW-1:2];
  else if (read_en) this_addr <= sram_a[AW-1:2];
end

`LOGF(clk, rstn, read_en, ("READ: %8h : %8h", this_addr, sram_q));

logic did_write;
`FF(write_en, did_write, clk, '1, rstn, '0);

`LOGF(clk, rstn, did_write, ("WRITE: %8h : %8h", sram_a[AW-1:2], sram_d));

endmodule

        0: byte_lane_nxt = 4'b0001; // Byte 0
        1: byte_lane_nxt = 4'b0010; // Byte 1
        2: byte_lane_nxt = 4'b0100; // Byte 2
        3: byte_lane_nxt = 4'b1000; // Byte 3


class frame_monitor extends uvm_monitor;
    rgb_vif  vif;

    frame_rgb_tr tr;
    uvm_analysis_port #(frame_rgb_tr) item_collected_port;
    `uvm_component_utils(frame_monitor)

    function new(string name, uvm_component parent);
        super.new(name, parent);
        item_collected_port = new ("item_collected_port", this);
	`uvm_info("MONITOR CREATED","new",UVM_MEDIUM)
    endfunction

    virtual function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        assert(uvm_config_db#(rgb_vif)::get(this, "", "vif", vif));
        tr = frame_rgb_tr::type_id::create("tr", this);
    endfunction

    virtual task run_phase(uvm_phase phase);
        `uvm_info("Monitor rgb","started run_phase",UVM_MEDIUM)

        wait (vif.rst === 1);
        @(negedge vif.rst);

        //forever begin
            tr.a = allocateFrame();
            @(posedge vif.clk);
            begin_tr(tr, "frame_monitor");
	    for(int i = 0; i < `HEIGHT; i++)begin
                for(int j = 0; j < `WIDTH; j++)begin
                    setPixel(tr.a, i, j, vif.R, vif.G, vif.B);
                    `uvm_info("Monitor rgb",$sformatf("Received pixel i=%d j=%d R=%d G=%d, B=%d", i, j, vif.R, vif.G, vif.B), UVM_LOW)
	    	    @(posedge vif.clk);
                end
            end
            `uvm_info("Monitor rgb ", "Received frame", UVM_LOW)
            item_collected_port.write(tr);
            `uvm_info("Monitor rgb ", "Wrote frame to port", UVM_LOW)
            end_tr(tr);
            `uvm_info("Monitor rgb ", "ended tr", UVM_LOW)
        //end
    endtask

endclass


// SPDX-FileCopyrightText: © 2024 JSilicon
// SPDX-License-Identifier: Apache-2.0

`timescale 1ns/1ps

module jsilicon_tb_top;

    import uvm_pkg::*;
    import jsilicon_pkg::*;

    // Clock generation
    logic clk;
    initial begin

        forever #5 clk = ~clk;  // 100MHz clock (10ns period)
    end

    // Interface instantiation
    jsilicon_if vif(clk);

    // DUT instantiation
    tt_um_Jsilicon dut (
        .clk     (vif.clk),
        .rst_n   (vif.rst_n),
        .ena     (vif.ena),
        .ui_in   (vif.ui_in),
        .uio_in  (vif.uio_in),
        .uo_out  (vif.uo_out),
        .uio_out (vif.uio_out),
        .uio_oe  (vif.uio_oe)
    );

    // Waveform dumping
    initial begin
        `ifdef VCS
            // FSDB dumping for Verdi
            $fsdbDumpfile("jsilicon.fsdb");
            $fsdbDumpvars(0, jsilicon_tb_top);
            $fsdbDumpMDA();
        `else
            // VCD dumping as fallback
            $dumpfile("jsilicon_uvm.vcd");
            $dumpvars(0, jsilicon_tb_top);
        `endif
    end

    // UVM configuration and test execution
    initial begin
        // Set virtual interface in config DB
        uvm_config_db#(virtual jsilicon_if)::set(null, "*", "vif", vif);

        // Run the test
        run_test();
    end

    // Timeout watchdog
    initial begin
        #1000000;  // 1ms timeout
        `uvm_error("TIMEOUT", "Simulation timeout reached")
        $finish;
    end

endmodule : jsilicon_tb_top


/*******************************************************************************
  Copyright 2019 Supranational LLC

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*******************************************************************************/

`include "msuconfig.vh"

// Set a default modulus and bitwidth but allow them to be defined
// externally as well.
`ifndef MOD_LEN_DEF
`define MOD_LEN_DEF 1024
`endif
`ifndef MODULUS_DEF
 `define MODULUS_DEF 1024'd124066695684124741398798927404814432744698427125735684128131855064976895337309138910015071214657674309443149407457493434579063840841220334555160125016331040933690674569571217337630239191517205721310197608387239846364360850220896772964978569683229449266819903414117058030106528073928633017118689826625594484331
`endif

module modular_square_simple
   #(
     parameter int MOD_LEN = `MOD_LEN_DEF
    )
   (
    input logic                   clk,
    input logic                   reset,
    input logic                   start,
    input logic [MOD_LEN-1:0]     sq_in,
    output logic [MOD_LEN-1:0]    sq_out,
    output logic                  valid
   );

   localparam [MOD_LEN-1:0] MODULUS = `MODULUS_DEF;

   logic [MOD_LEN-1:0]            cur_sq_in;
   logic [MOD_LEN*2-1:0]          squared;
   logic [MOD_LEN-1:0]            sq_out_comb;

   // Mimic a pipeline
   localparam  [3:0]              PIPELINE_DEPTH = 10;
   logic [3:0]                    valid_count;
   logic                          running;
   logic                          valid_next;

   // Store the square input, circulate the result back to the input
   always_ff @(posedge clk) begin
      if(start) begin
         cur_sq_in <= sq_in;
      end else if(valid_next) begin
         cur_sq_in <= sq_out_comb;
      end
   end
   assign sq_out = valid ? cur_sq_in : {MOD_LEN{1'bx}};

   // Control
   always_ff @(posedge clk) begin
      if(reset) begin
         running        <= 0;
         valid_count    <= 0;
      end else begin
         if(start || valid_next) begin
            running     <= 1;
            valid_count <= 0;
         end else begin
            valid_count <= valid_count + 1;

   //----------------------------------------------------------------------
   // EDIT HERE
   // Insert/instantiate your multiplier below
   // Modify control above as needed while satisfying the interface
   //

   // Compute the modular square function
   always_comb begin
      squared     = {{MOD_LEN{1'b0}}, cur_sq_in};
      squared     = squared * squared;
      squared     = squared % {{MOD_LEN{1'b0}}, MODULUS};
      sq_out_comb = squared[MOD_LEN-1:0];
   end

   // EDIT HERE
   //----------------------------------------------------------------------

endmodule

         end
      end
   end

   assign valid_next = running && (valid_count == PIPELINE_DEPTH-1);


// MIT License

// Copyright (c) 2023 Tom Chisholm

// 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.

/*
*   Module: example_10g_eth
*
*   Description: Example design for low-latency 10G Ethernet core.
*                This design generates test packets and measures latency when transceiver
*                is in loopback.
*
*/

`timescale 1ns/1ps
`default_nettype none

    parameter bit TX_XVER_BUFFER = 0,
    parameter real INIT_CLK_FREQ = 100.0
) (

    input wire i_init_clk,

    // Differential reference clock inputs
    input  wire i_mgtrefclk0_x0y3_p,
    input  wire i_mgtrefclk0_x0y3_n,

    // Serial data ports for transceiver channel 0
    input  wire i_ch0_gtyrxn_in,
    input  wire i_ch0_gtyrxp_in,
    output wire o_ch0_gtytxn_out,
    output wire o_ch0_gtytxp_out
);

    /********* Internal Declarations ********/
    wire packet_gen_reset;
    logic [1:0] reset_cdc;
    wire core_reset;

    // Packet gen
    wire [15:0] packet_length;
    logic [15:0] packet_length_cnt;
    logic [31:0] packet_vio_data;

    // Tx AXIS
    wire s00_axis_aclk;
    wire [31:0] s00_axis_tdata;
    wire [3:0] s00_axis_tkeep;
    wire s00_axis_tvalid;
    wire s00_axis_tready;
    wire s00_axis_tlast;

    // Rx AXIS
    wire m00_axis_aclk;
    wire [31:0] m00_axis_tdata;
    wire [3:0] m00_axis_tkeep;
    wire m00_axis_tvalid;
    wire m00_axis_tlast;
    wire m00_axis_tuser;

    // Resets
    wire mac_pcs_rx_reset, mac_pcs_tx_reset;

    // Performance meas
    wire [15:0] perf_latency;
    wire perf_complete;
    wire perf_tx_start, perf_rx_stop;

    /********* Transmit Packet Gen ********/

    always_ff @(posedge s00_axis_aclk)
    if (packet_gen_reset) begin
        packet_length_cnt <= '0;
    end else if (s00_axis_tready) begin
        packet_length_cnt <= (packet_length_cnt == packet_length) ? '0 : packet_length_cnt + 1;
    end

    assign s00_axis_tdata = {packet_vio_data[31:16], packet_length_cnt}; // Set lower 16 bits to packet index counter
    assign s00_axis_tkeep = '1;
    assign s00_axis_tlast = packet_length_cnt == packet_length;
    assign s00_axis_tvalid = !packet_gen_reset;

    /********* Latency Measurement ********/

    assign perf_tx_start = s00_axis_tvalid && s00_axis_tready && s00_axis_tdata[15:0] == 16'b0;
    assign perf_rx_stop = m00_axis_tvalid && m00_axis_tdata[15:0] == 16'b0;

    eth_perf u_eth_perf (
        .i_tx_reset(mac_pcs_tx_reset),
        .i_tx_clk(s00_axis_aclk),
        .i_tx_start(perf_tx_start),
        .o_latency(perf_latency),
        .o_test_complete(perf_complete),

        .i_rx_stop(perf_rx_stop)
    );

    /********* Debug Cores ********/

    // Packet Gen VIO
    eth_core_control_vio u_packet_control_vio (
        .clk(s00_axis_aclk),                // input wire clk
        .probe_out0(packet_gen_reset),  // output wire [0 : 0] probe_out0
        .probe_out1(packet_length),  // output wire [15 : 0] probe_out1
        .probe_out2(packet_vio_data)  // output wire [63 : 0] probe_out2
    );

    eth_core_control_vio u_core_reset_vio (
        .clk(i_init_clk),                // input wire clk
        .probe_out0(core_reset),  // output wire [0 : 0] probe_out0
        .probe_out1(),  // output wire [15 : 0] probe_out1
        .probe_out2()  // output wire [63 : 0] probe_out2
    );

    // Data monitor ILAs
    example_packet_ila tx_packet_ila (
        .clk(s00_axis_aclk), // input wire clk
        .probe0(s00_axis_tdata), // input wire [63:0]  probe0
        .probe1(s00_axis_tkeep), // input wire [7:0]  probe1
        .probe2(s00_axis_tready), // input wire [0:0]  probe2
        .probe3(s00_axis_tvalid), // input wire [0:0]  probe3
        .probe4(s00_axis_tlast), // input wire [0:0]  probe4
        .probe5(perf_latency),
        .probe6(perf_complete)
    );

    example_packet_ila rx_packet_ila (
        .clk(m00_axis_aclk), // input wire clk
        .probe0(m00_axis_tdata), // input wire [63:0]  probe0
        .probe1(m00_axis_tkeep), // input wire [7:0]  probe1
        .probe2(m00_axis_tuser), // input wire [0:0]  probe2
        .probe3(m00_axis_tvalid), // input wire [0:0]  probe3
        .probe4(m00_axis_tlast), // input wire [0:0]  probe4
        .probe5(16'h0),
        .probe6(perf_rx_stop)
    );

    /********* Ethernet Core ********/

    eth_10g #(
        .SCRAMBLER_BYPASS(SCRAMBLER_BYPASS),
        .EXTERNAL_GEARBOX(EXTERNAL_GEARBOX),
        .TX_XVER_BUFFER(TX_XVER_BUFFER),
        .INIT_CLK_FREQ(INIT_CLK_FREQ)
    ) u_eth_10g (
        .i_reset(core_reset),
        .i_init_clk(i_init_clk),
        .i_mgtrefclk0_x0y3_p(i_mgtrefclk0_x0y3_p),
        .i_mgtrefclk0_x0y3_n(i_mgtrefclk0_x0y3_n),
        .s00_axis_aclk(s00_axis_aclk),
        .s00_axis_tdata(s00_axis_tdata),
        .s00_axis_tkeep(s00_axis_tkeep),
        .s00_axis_tvalid(s00_axis_tvalid),
        .s00_axis_tready(s00_axis_tready),
        .s00_axis_tlast(s00_axis_tlast),
        .m00_axis_aclk(m00_axis_aclk),
        .m00_axis_tdata(m00_axis_tdata),
        .m00_axis_tkeep(m00_axis_tkeep),
        .m00_axis_tvalid(m00_axis_tvalid),
        .m00_axis_tlast(m00_axis_tlast),
        .m00_axis_tuser(m00_axis_tuser),
        .i_ch0_gtyrxn(i_ch0_gtyrxn_in),
        .i_ch0_gtyrxp(i_ch0_gtyrxp_in),
        .o_ch0_gtytxn(o_ch0_gtytxn_out),
        .o_ch0_gtytxp(o_ch0_gtytxp_out),
        .o_mac_pcs_tx_reset(mac_pcs_tx_reset),
        .o_mac_pcs_rx_reset(mac_pcs_rx_reset)
    );

endmodule

module example_10g_eth #(
    parameter bit SCRAMBLER_BYPASS = 0,


///////////////////////////////////////////////////////////////////////////////
//
// FILE NAME: BURST_RW.SV
//
// AUTHOR: Jeff Nguyen
//
// DATE CREATED: 07/29/2014
//
// DESCRIPTION:  The module implements FSM to control write and read timing.
// The FSM controls the CL and CWL, which are latency between CAS and read,and
// write data, respectively.
// The queues are provided to keep track when CAS occurs while the FSM executing
// the past CAS command. Each time, a CAS pops out of the queue, each CAS in
// the queue is updated for # cycles has been waited.
//
// Note: use clock_t as main clock
///////////////////////////////////////////////////////////////////////////////

`include "ddr_package.pkg"

module BURST_RW (DDR_INTERFACE intf,
                 CTRL_INTERFACE ctrl_intf);

int   DELAY;

rw_fsm_type rw_state, rw_next_state;

logic next_rw;

int rw_counter,rw_delay;

//tracking the CAS command occurs
int rw_cmd_trk[$];
logic [1:0] rw_trk[$];

int temp;

//fsm control timing between CAS and data
always_ff @(posedge intf.clock_t, negedge intf.reset_n)
begin
   if (!intf.reset_n)
      rw_state <= RW_IDLE;
   else
      rw_state <= rw_next_state;
end

//next state generate logic

always_comb
begin
   if (!intf.reset_n) begin
      rw_next_state     <= RW_IDLE;
      clear_rw_counter  <= 1'b1;
      ctrl_intf.rw_done <= 1'b0;
      ctrl_intf.rw_rdy  <= 1'b0;
   end
   else begin
      case (rw_state)
         RW_IDLE: begin
            ctrl_intf.rw_done    <= 1'b1;
            ctrl_intf.data_idle  <= 1'b1;
            if (ctrl_intf.cas_rdy) begin
               rw_next_state    <= RW_WAIT_STATE;
               clear_rw_counter <= 1'b1;
            end else
            begin
               rw_next_state    <= RW_IDLE;
               clear_rw_counter <= 1'b0;
            end
         end

         RW_WAIT_STATE: begin
            ctrl_intf.rw_done   <= 1'b0;
            ctrl_intf.data_idle <= 1'b0;
            clear_rw_counter <= 1'b0;
            if (rw_counter == rw_delay) begin
               rw_next_state    <= RW_DATA;
               clear_rw_counter <= 1'b1;
               ctrl_intf.rw_rdy <= 1'b1;
            end else
               rw_next_state    <= RW_WAIT_STATE;
         end

         RW_DATA: begin
            ctrl_intf.rw_done  <= 1'b1;   //set data done
            ctrl_intf.rw_rdy   <= 1'b0;
            clear_rw_counter   <= 1'b0;
            if (next_rw)        //next rw avail in queue
               rw_next_state <= RW_WAIT_STATE;
            else
               rw_next_state <= RW_IDLE;
         end

         default : rw_next_state <= RW_IDLE;

      endcase
   end
end

// keep track when CAS occurs
always @(intf.reset_n, ctrl_intf.cas_rdy, next_rw)
begin
   int temp;
   if (!intf.reset_n) begin
      rw_cmd_trk.delete();    //delete the queues
      rw_delay  = 0;
   end

   //calculate # cycles each CAS command waited in queue
   if((rw_state == RW_IDLE)  &&
      (ctrl_intf.cas_rdy))begin
      if (ctrl_intf.act_rw == READ)
         DELAY = ctrl_intf.RD_DELAY;
      else
         DELAY = ctrl_intf.WR_DELAY;
      rw_delay = DELAY - 1;
   end
   else if ((rw_state == RW_DATA) && (next_rw)) begin
      if (rw_trk.pop_front === READ)
          DELAY = ctrl_intf.RD_DELAY;
      else
          DELAY = ctrl_intf.WR_DELAY;

      temp = DELAY - rw_cmd_trk.pop_front -1;
      if (temp > DELAY)
         rw_delay = temp;
      else
         rw_delay = DELAY + ctrl_intf.BL/2;    // enough for the preamble

      //update # cycles each RW cmd waited
      foreach (rw_cmd_trk[i])
          rw_cmd_trk [i] = {(rw_cmd_trk[i] + rw_delay +1 )};
   end

   if ((ctrl_intf.cas_rdy) &&
       (rw_state != RW_IDLE))
      begin
      rw_cmd_trk = {rw_cmd_trk, (rw_delay - rw_counter)};
      rw_trk     = {rw_trk, ctrl_intf.cas_rw};
   end
end

// simple rw_counter
always_ff @(posedge intf.clock_t)
begin
   if(clear_rw_counter == 1'b1)
      rw_counter <= 0;
   else
      rw_counter <= rw_counter + 1;
end

//determine the next CAS command avail in queue.
always_ff @ (posedge intf.clock_t)
begin
   if ((rw_next_state == RW_DATA) &&
       (rw_cmd_trk.size != 0))
      next_rw <= 1'b1;
   else
      next_rw <= 1'b0;
end

endmodule


// 5:3 counter, the basic module that constitutes the 4:2 compressor
module counter_5to3(
    input logic x1,x2,x3,x4,cin,
    output logic sum,carry,cout

);
    assign sum = x1 ^ x2 ^ x3 ^ x4 ^ cin;
    assign cout = (x1 ^ x2) & x3 | ~(x1 ^ x2) & x1;
    assign carry = (x1 ^ x2 ^ x3 ^ x4) & cin | ~(x1 ^ x2 ^ x3 ^ x4) & x4;
endmodule


class reg_rw_test extends base_test;
   `uvm_component_utils (reg_rw_test)

    my_sequence m_seq;

   function new (string name="reg_rw_test", uvm_component parent);
      super.new (name, parent);
   endfunction

   virtual task main_phase(uvm_phase phase);

      phase.raise_objection(this);
      m_seq = my_sequence::type_id::create("m_seq");

      m_seq.model = m_ral_model;

      phase.drop_objection(this);
   endtask
endclass


/**
 * File: RaveNoC wrapper module
 * Description: It only exists because it facilitates intg. with cocotb
 * Author: Anderson Ignacio da Silva <anderson@aignacio.com>
 *
 * MIT License
 * 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.
 */
module ravenoc_wrapper
  import amba_axi_pkg::*;
  import ravenoc_pkg::*;
#(
  parameter bit DEBUG = 0
)(
  /*verilator coverage_off*/
  input                                          clk_axi,
  input                                          clk_noc,
  input                                          arst_axi,
  input                                          arst_noc,
  // AXI mux I/F
  input                                          act_in,
  input               [$clog2(NoCSize)-1:0]      axi_sel_in,
  input                                          act_out,
  input               [$clog2(NoCSize)-1:0]      axi_sel_out,
  // Used to test when clk_axi == clk_noc to bypass CDC
  input                                          bypass_cdc,
  // AXI in I/F
  // AXI Interface - MOSI
  // Write Address channel
  input  logic                                   noc_in_awid,
  input  axi_addr_t                              noc_in_awaddr,
  input  logic        [`AXI_ALEN_WIDTH-1:0]      noc_in_awlen,
  input  axi_size_t                              noc_in_awsize,
  input  axi_burst_t                             noc_in_awburst,
  input  logic                                   noc_in_awlock,
  input  logic        [3:0]                      noc_in_awcache,
  input  logic        [2:0]                      noc_in_awprot,
  input  logic        [3:0]                      noc_in_awqos,
  input  logic        [3:0]                      noc_in_awregion,
  input  logic        [`AXI_USER_REQ_WIDTH-1:0]  noc_in_awuser,
  input  logic                                   noc_in_awvalid,
  // Write Data channel
  //input  logic                                   noc_in_wid,
  input  logic        [`AXI_DATA_WIDTH-1:0]      noc_in_wdata,
  input  logic        [(`AXI_DATA_WIDTH/8)-1:0]  noc_in_wstrb,
  input  logic                                   noc_in_wlast,
  input  logic        [`AXI_USER_DATA_WIDTH-1:0] noc_in_wuser,
  input  logic                                   noc_in_wvalid,
  // Write Response channel
  input  logic                                   noc_in_bready,
  // Read Address channel
  input  logic                                   noc_in_arid,
  input  axi_addr_t                              noc_in_araddr,
  input  logic        [`AXI_ALEN_WIDTH-1:0]      noc_in_arlen,
  input  axi_size_t                              noc_in_arsize,
  input  axi_burst_t                             noc_in_arburst,
  input  logic                                   noc_in_arlock,
  input  logic        [3:0]                      noc_in_arcache,
  input  logic        [2:0]                      noc_in_arprot,
  input  logic        [3:0]                      noc_in_arqos,
  input  logic        [3:0]                      noc_in_arregion,
  input  logic        [`AXI_USER_REQ_WIDTH-1:0]  noc_in_aruser,
  input  logic                                   noc_in_arvalid,
  // Read Data channel
  input  logic                                   noc_in_rready,

  // AXI Interface - MISO
  // Write Addr channel
  output logic                                   noc_in_awready,
  // Write Data channel
  output logic                                   noc_in_wready,
  // Write Response channel
  output logic                                   noc_in_bid,
  output axi_resp_t                              noc_in_bresp,
  output logic        [`AXI_USER_RESP_WIDTH-1:0] noc_in_buser,
  output logic                                   noc_in_bvalid,
  // Read addr channel
  output logic                                   noc_in_arready,
  // Read data channel
  output logic                                   noc_in_rid,
  output logic        [`AXI_DATA_WIDTH-1:0]      noc_in_rdata,
  output axi_resp_t                              noc_in_rresp,
  output logic                                   noc_in_rlast,
  output logic        [`AXI_USER_REQ_WIDTH-1:0]  noc_in_ruser,
  output logic                                   noc_in_rvalid,

  // AXI out I/F
  // AXI Interface - MOSI
  // Write Address channel
  input  logic                                   noc_out_awid,
  input  axi_addr_t                              noc_out_awaddr,
  input  logic        [`AXI_ALEN_WIDTH-1:0]      noc_out_awlen,
  input  axi_size_t                              noc_out_awsize,
  input  axi_burst_t                             noc_out_awburst,
  input  logic                                   noc_out_awlock,
  input  logic        [3:0]                      noc_out_awcache,
  input  logic        [2:0]                      noc_out_awprot,
  input  logic        [3:0]                      noc_out_awqos,
  input  logic        [3:0]                      noc_out_awregion,
  input  logic        [`AXI_USER_REQ_WIDTH-1:0]  noc_out_awuser,
  input  logic                                   noc_out_awvalid,
  // Write Data channel
  //input  logic                                   noc_out_wid,
  input  logic        [`AXI_DATA_WIDTH-1:0]      noc_out_wdata,
  input  logic        [(`AXI_DATA_WIDTH/8)-1:0]  noc_out_wstrb,
  input  logic                                   noc_out_wlast,
  input  logic        [`AXI_USER_DATA_WIDTH-1:0] noc_out_wuser,
  input  logic                                   noc_out_wvalid,
  // Write Response channel
  input  logic                                   noc_out_bready,
  // Read Address channel
  input  logic                                   noc_out_arid,
  input  axi_addr_t                              noc_out_araddr,
  input  logic        [`AXI_ALEN_WIDTH-1:0]      noc_out_arlen,
  input  axi_size_t                              noc_out_arsize,
  input  axi_burst_t                             noc_out_arburst,
  input  logic                                   noc_out_arlock,
  input  logic        [3:0]                      noc_out_arcache,
  input  logic        [2:0]                      noc_out_arprot,
  input  logic        [3:0]                      noc_out_arqos,
  input  logic        [3:0]                      noc_out_arregion,
  input  logic        [`AXI_USER_REQ_WIDTH-1:0]  noc_out_aruser,
  input  logic                                   noc_out_arvalid,
  // Read Data channel
  input  logic                                   noc_out_rready,
  // AXI Interface - MISO
  // Write Addr channel
  output logic                                   noc_out_awready,
  // Write Data channel
  output logic                                   noc_out_wready,
  // Write Response channel
  output logic                                   noc_out_bid,
  output axi_resp_t                              noc_out_bresp,
  output logic        [`AXI_USER_RESP_WIDTH-1:0] noc_out_buser,
  output logic                                   noc_out_bvalid,
  // Read addr channel
  output logic                                   noc_out_arready,
  // Read data channel
  output logic                                   noc_out_rid,
  output logic        [`AXI_DATA_WIDTH-1:0]      noc_out_rdata,
  output axi_resp_t                              noc_out_rresp,
  output logic                                   noc_out_rlast,
  output logic        [`AXI_USER_REQ_WIDTH-1:0]  noc_out_ruser,
  output logic                                   noc_out_rvalid,
  // IRQs
  output logic        [NumVirtChn*NoCSize-1:0]   irqs_out
);
  s_axi_mosi_t [NoCSize-1:0] axi_mosi;
  s_axi_miso_t [NoCSize-1:0] axi_miso;
  s_irq_ni_t   [NoCSize-1:0] irqs;
  logic        [NoCSize-1:0] bypass_cdc_vec;
  logic        [NoCSize-1:0] clk_axi_array;
  logic        [NoCSize-1:0] arst_axi_array;

  always begin
    for (int i=0;i<NoCSize;i++) begin
      bypass_cdc_vec[i] = bypass_cdc;
      clk_axi_array[i] = clk_axi;
      arst_axi_array[i] = arst_axi;
    end

    noc_in_awready  = '0;
    noc_in_wready   = '0;
    noc_in_bid      = '0;
    noc_in_bresp    = '0;
    noc_in_buser    = '0;
    noc_in_bvalid   = '0;
    noc_in_arready  = '0;
    noc_in_rid      = '0;
    noc_in_rdata    = '0;
    noc_in_rresp    = '0;
    noc_in_rlast    = '0;
    noc_in_ruser    = '0;
    noc_in_rvalid   = '0;

    noc_out_awready  = '0;
    noc_out_wready   = '0;
    noc_out_bid      = '0;
    noc_out_bresp    = '0;
    noc_out_buser    = '0;
    noc_out_bvalid   = '0;
    noc_out_arready  = '0;
    noc_out_rid      = '0;
    noc_out_rdata    = '0;
    noc_out_rresp    = '0;
    noc_out_rlast    = '0;
    noc_out_ruser    = '0;
    noc_out_rvalid   = '0;

    axi_mosi = '0;
    // verilator lint_off WIDTH
    for (int i=0;i<NoCSize;i++) begin
      for (int vc=0;vc<NumVirtChn;vc++) begin
        irqs_out[i*NumVirtChn+vc] = irqs[i].irq_vcs[vc];
      end

      if (axi_sel_out == i && act_out)  begin
        axi_mosi[i].awid     = noc_out_awid;
        axi_mosi[i].awaddr   = noc_out_awaddr;
        axi_mosi[i].awlen    = noc_out_awlen;
        axi_mosi[i].awsize   = noc_out_awsize;
        axi_mosi[i].awburst  = noc_out_awburst;
        axi_mosi[i].awlock   = noc_out_awlock;
        axi_mosi[i].awcache  = noc_out_awcache;
        axi_mosi[i].awprot   = noc_out_awprot;
        axi_mosi[i].awqos    = noc_out_awqos;
        axi_mosi[i].awregion = noc_out_awregion;
        axi_mosi[i].awuser   = noc_out_awuser;
        axi_mosi[i].awvalid  = noc_out_awvalid;
        //axi_mosi[i].wid      = noc_out_wid;
        axi_mosi[i].wdata    = noc_out_wdata;
        axi_mosi[i].wstrb    = noc_out_wstrb;
        axi_mosi[i].wlast    = noc_out_wlast;
        axi_mosi[i].wuser    = noc_out_wuser;
        axi_mosi[i].wvalid   = noc_out_wvalid;
        axi_mosi[i].bready   = noc_out_bready;
        axi_mosi[i].arid     = noc_out_arid;
        axi_mosi[i].araddr   = noc_out_araddr;
        axi_mosi[i].arlen    = noc_out_arlen;
        axi_mosi[i].arsize   = noc_out_arsize;
        axi_mosi[i].arburst  = noc_out_arburst;

        axi_mosi[i].arcache  = noc_out_arcache;
        axi_mosi[i].arprot   = noc_out_arprot;
        axi_mosi[i].arqos    = noc_out_arqos;
        axi_mosi[i].arregion = noc_out_arregion;
        axi_mosi[i].aruser   = noc_out_aruser;
        axi_mosi[i].arvalid  = noc_out_arvalid;
        axi_mosi[i].rready   = noc_out_rready;

        noc_out_awready  = axi_miso[i].awready;
        noc_out_wready   = axi_miso[i].wready;
        noc_out_bid      = axi_miso[i].bid;
        noc_out_bresp    = axi_miso[i].bresp;
        noc_out_buser    = axi_miso[i].buser;
        noc_out_bvalid   = axi_miso[i].bvalid;
        noc_out_arready  = axi_miso[i].arready;
        noc_out_rid      = axi_miso[i].rid;
        noc_out_rdata    = axi_miso[i].rdata;
        noc_out_rresp    = axi_miso[i].rresp;
        noc_out_rlast    = axi_miso[i].rlast;
        noc_out_ruser    = axi_miso[i].ruser;
        noc_out_rvalid   = axi_miso[i].rvalid;
      end
      if (axi_sel_in == i && act_in)  begin
        axi_mosi[i].awid     = noc_in_awid;
        axi_mosi[i].awaddr   = noc_in_awaddr;
        axi_mosi[i].awlen    = noc_in_awlen;
        axi_mosi[i].awsize   = noc_in_awsize;
        axi_mosi[i].awburst  = noc_in_awburst;
        axi_mosi[i].awlock   = noc_in_awlock;
        axi_mosi[i].awcache  = noc_in_awcache;
        axi_mosi[i].awprot   = noc_in_awprot;
        axi_mosi[i].awqos    = noc_in_awqos;
        axi_mosi[i].awregion = noc_in_awregion;
        axi_mosi[i].awuser   = noc_in_awuser;
        axi_mosi[i].awvalid  = noc_in_awvalid;
        //axi_mosi[i].wid      = noc_in_wid;
        axi_mosi[i].wdata    = noc_in_wdata;
        axi_mosi[i].wstrb    = noc_in_wstrb;
        axi_mosi[i].wlast    = noc_in_wlast;
        axi_mosi[i].wuser    = noc_in_wuser;
        axi_mosi[i].wvalid   = noc_in_wvalid;
        axi_mosi[i].bready   = noc_in_bready;
        axi_mosi[i].arid     = noc_in_arid;
        axi_mosi[i].araddr   = noc_in_araddr;
        axi_mosi[i].arlen    = noc_in_arlen;
        axi_mosi[i].arsize   = noc_in_arsize;
        axi_mosi[i].arburst  = noc_in_arburst;
        axi_mosi[i].arlock   = noc_in_arlock;
        axi_mosi[i].arcache  = noc_in_arcache;
        axi_mosi[i].arprot   = noc_in_arprot;
        axi_mosi[i].arqos    = noc_in_arqos;
        axi_mosi[i].arregion = noc_in_arregion;
        axi_mosi[i].aruser   = noc_in_aruser;
        axi_mosi[i].arvalid  = noc_in_arvalid;
        axi_mosi[i].rready   = noc_in_rready;

        noc_in_awready  = axi_miso[i].awready;
        noc_in_wready   = axi_miso[i].wready;
        noc_in_bid      = axi_miso[i].bid;
        noc_in_bresp    = axi_miso[i].bresp;
        noc_in_buser    = axi_miso[i].buser;
        noc_in_bvalid   = axi_miso[i].bvalid;
        noc_in_arready  = axi_miso[i].arready;
        noc_in_rid      = axi_miso[i].rid;
        noc_in_rdata    = axi_miso[i].rdata;
        noc_in_rresp    = axi_miso[i].rresp;
        noc_in_rlast    = axi_miso[i].rlast;
        noc_in_ruser    = axi_miso[i].ruser;
        noc_in_rvalid   = axi_miso[i].rvalid;
      end

    end
  end
  // verilator lint_on WIDTH
  /*verilator coverage_on*/

  ravenoc #(
    .AXI_CDC_REQ('1)
  ) u_ravenoc (
    .clk_axi        (clk_axi_array),
    .clk_noc        (clk_noc),
    .arst_axi       (arst_axi_array),
    .arst_noc       (arst_noc),
    .axi_mosi_if    (axi_mosi),
    .axi_miso_if    (axi_miso),
    .irqs           (irqs),
    .bypass_cdc     (bypass_cdc_vec)
  );

  illegal_input_axi_muxes : assert property (
    @(posedge clk_axi) disable iff (arst_axi)
    (act_in && act_out) |-> (axi_sel_in != axi_sel_out)
  ) else $error("Illegal mux on the AXI!");

endmodule


module Alu(
    input logic [3:0] aluControl,
    input logic [31:0] op1, op2,
    output logic [31:0] aluOut,
    output logic isZero
);

    always_comb

            4'h2: aluOut <= op1 << op2;
            4'h3: aluOut <= $signed(op1) < $signed(op2);
            4'h4: aluOut <= op1 < op2;
            4'h5: aluOut <= op1 ^ op2;
            4'h6: aluOut <= $signed(op1) >>> op2;
            4'h7: aluOut <= op1 >> op2;
            4'h8: aluOut <= op1 | op2;
            4'h9: aluOut <= op1 & op2;
            4'ha: aluOut <= op1 == op2;
            4'hb: aluOut <= op1 != op2;
            4'hc: aluOut <= $signed(op1) >= $signed(op2);
            4'hd: aluOut <= op1 >= op2;
            default: aluOut <= 31'b0;
        endcase

    assign isZero = ~|aluOut;

endmodule

        case (aluControl)
            4'h0: aluOut <= op1 + op2;


import uvm_pkg::*;
`include "uvm_macros.svh"

`include "./interface/ue_interface.sv"

`include "./obj/ue_transaction.sv"
`include "./obj/ue_config.sv"

`include "./obj/sequence/ue_base_sequense.sv"
`include "./obj/sequence/ue_base_sequense_lib.sv"

`include "./compoment/ue_driver.sv"
`include "./compoment/ue_monitor.sv"
`include "./compoment/ue_sequencer.sv"

`include "./compoment/ue_agent.sv"

`include "./compoment/ue_ref_model.sv"
`include "./compoment/ue_scoreboard.sv"

`include "./compoment/ue_env.sv"
`include "./compoment/ue_base_test.sv"

`include "./test_case/ue_case0_test.sv"


module ThreebyOneMux
  (
    input[63:0] a,
    input[63:0] b,
    input[63:0] c,
    input [1:0] sel,

        2'b00: out = a;
        2'b01: out = b;
        2'b10: out = c;
      endcase
    end
endmodule

    output reg [63:0] out
  );
  always @(*)


/*
 *  Copyright (C) 2018  Siddharth J <www.siddharth.pro>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

module uart_tx(clk,rst,start,tx_data_in,tx,tx_active,done_tx);

parameter clk_freq = 50000000; //MHz
parameter baud_rate = 19200; //bits per second
input clk,rst;
input start;
input [7:0] tx_data_in;
output tx;
output tx_active;
output logic done_tx;

localparam clock_divide = (clk_freq/baud_rate);

enum bit [2:0]{ tx_IDLE = 3'b000,
                tx_START = 3'b001,
		tx_DATA = 3'b010,
	        tx_STOP = 3'b011,
		tx_DONE = 3'b100 } tx_STATE, tx_NEXT;

logic [11:0] clk_div_reg,clk_div_next;
logic [7:0] tx_data_reg, tx_data_next;
logic tx_out_reg,tx_out_next;
logic [2:0] index_bit_reg,index_bit_next;

assign tx_active = (tx_STATE == tx_DATA);
assign tx = tx_out_reg;

always_ff @(posedge clk) begin
if(rst) begin
tx_STATE <= tx_IDLE;
clk_div_reg <= 0;
tx_out_reg <= 0;
tx_data_reg <= 0;
index_bit_reg <= 0;
end
else begin
tx_STATE <= tx_NEXT;
clk_div_reg <= clk_div_next;
tx_out_reg <= tx_out_next;
tx_data_reg <= tx_data_next;
index_bit_reg <= index_bit_next;
end
end

always @(*) begin
tx_NEXT = tx_STATE;
clk_div_next = clk_div_reg;
tx_out_next = tx_out_reg;
tx_data_next = tx_data_reg;
index_bit_next = index_bit_reg;
done_tx = 0;

case(tx_STATE)

tx_IDLE: begin
tx_out_next = 1;
clk_div_next = 0;
index_bit_next = 0;
if(start == 1) begin
tx_data_next = tx_data_in;
tx_NEXT = tx_START;
end

tx_NEXT = tx_IDLE;
end
end

tx_START: begin
tx_out_next = 0;
if(clk_div_reg < clock_divide-1) begin
clk_div_next = clk_div_reg + 1'b1;
tx_NEXT = tx_START;
end
else begin
clk_div_next = 0;
tx_NEXT = tx_DATA;
end
end

tx_DATA: begin
tx_out_next = tx_data_reg[index_bit_reg];
if(clk_div_reg < clock_divide-1) begin
clk_div_next = clk_div_reg + 1'b1;
tx_NEXT = tx_DATA;
end
else begin
clk_div_next = 0;
if(index_bit_reg < 7) begin
index_bit_next = index_bit_reg + 1'b1;
tx_NEXT = tx_DATA;
end
else begin
index_bit_next = 0;
tx_NEXT = tx_STOP;
end
end
end

tx_STOP: begin
tx_out_next = 1;
if(clk_div_reg < clock_divide-1) begin
clk_div_next = clk_div_reg + 1'b1;
tx_NEXT = tx_STOP;
end
else begin
clk_div_next = 0;
tx_NEXT = tx_DONE;
end
end

tx_DONE: begin
done_tx = 1;
tx_NEXT = tx_IDLE;
end

default: tx_NEXT = tx_IDLE;
endcase
end

endmodule


localparam TX_FIFO_SIZE       = 4096;
localparam TX_START_THRESHOLD = 1024;
localparam TX_BURST_SIZE      = 0;
localparam TX_BACKOFF_TIMEOUT = 64;
localparam RX_FIFO_SIZE       = 4096;
localparam RX_START_THRESHOLD = 3072;
localparam RX_BURST_SIZE      = 0;
localparam SINGLE_CLK_DOMAIN  = 0;
localparam TX_FIFO_LOAD_W     = $clog2(TX_FIFO_SIZE) + 1;
localparam RX_FIFO_LOAD_W     = $clog2(RX_FIFO_SIZE) + 1;

logic [DATA_W-1:0] ft_din, ft_dout;

logic                      rxfifo_rd;
logic [DATA_W-1:0]         rxfifo_data;
logic                      rxfifo_valid;
logic [RX_FIFO_LOAD_W-1:0] rxfifo_load;
logic                      rxfifo_empty;
logic [DATA_W-1:0]         txfifo_data;
logic                      txfifo_wr;
logic [TX_FIFO_LOAD_W-1:0] txfifo_load;
logic                      txfifo_full;

proto245s #(
    .DATA_W             (DATA_W),
    .TX_FIFO_SIZE       (TX_FIFO_SIZE),
    .TX_START_THRESHOLD (TX_START_THRESHOLD),
    .TX_BURST_SIZE      (TX_BURST_SIZE),
    .TX_BACKOFF_TIMEOUT (TX_BACKOFF_TIMEOUT),
    .RX_FIFO_SIZE       (RX_FIFO_SIZE),
    .RX_START_THRESHOLD (RX_START_THRESHOLD),
    .RX_BURST_SIZE      (RX_BURST_SIZE),
    .SINGLE_CLK_DOMAIN  (SINGLE_CLK_DOMAIN)
) proto245 (
    // FT interface - should be routed directly to IO
    .ft_rst   (ft_rst),
    .ft_clk   (ft_clk),
    .ft_rxfn  (ft_rxfn),
    .ft_txen  (ft_txen),
    .ft_din   (ft_din),
    .ft_dout  (ft_dout),
    .ft_bein  (0),
    .ft_beout (),
    .ft_rdn   (ft_rdn),
    .ft_wrn   (ft_wrn),
    .ft_oen   (ft_oen),
    .ft_siwu  (ft_siwu),
    // RX FIFO (Host -> FTDI chip -> FPGA -> FIFO)
    .rxfifo_clk   (sys_clk),
    .rxfifo_rst   (sys_rst),
    .rxfifo_rd    (rxfifo_rd),
    .rxfifo_data  (rxfifo_data),
    .rxfifo_valid (rxfifo_valid),
    .rxfifo_load  (rxfifo_load),
    .rxfifo_empty (rxfifo_empty),
    // TX FIFO (FIFO -> FPGA -> FTDI chip -> Host)
    .txfifo_clk   (sys_clk),
    .txfifo_rst   (sys_rst),
    .txfifo_data  (txfifo_data),
    .txfifo_wr    (txfifo_wr),
    .txfifo_load  (txfifo_load),
    .txfifo_full  (txfifo_full)
);

assign ft_data = ft_oen ? ft_dout : 'z;


/***********************************************************************
  $FILENAME    : tb.svh

  $TITLE       : Testbench module

  $DATE        : 11 Nov 2017

  $VERSION     : 1.0.0

  $DESCRIPTION : This module defines the high level tester module
                 which schedules the entire test scenario.

************************************************************************/

class tb;

  // Bus Functional Model interface
  virtual async_fifo_bfm bfm;

  tester     tester_h;
  coverage   coverage_h;
  scoreboard scoreboard_h;

  //
  // Class constructor method
  //
  function new (virtual async_fifo_bfm b);
    bfm = b;
  endfunction : new

  //
  // This method launches all the subcomponents of the testbench concurrently
  //

    tester_h     = new(bfm);
    coverage_h   = new(bfm);
    scoreboard_h = new(bfm);

    fork
      coverage_h.execute();
      scoreboard_h.execute();
      tester_h.execute();
      join_none
  endtask : execute

endclass : tb


module core_bus_wrapper(
    input  logic        clk, rstn,
    input  logic        i_re, i_we,
    output logic        o_conflict,
    input  logic [ 2:0] i_funct3,
    input  logic [31:0] i_addr,
    input  logic [31:0] i_wdata,
    output logic [31:0] o_rdata,

    naive_bus.master  bus_master
);

logic i_re_latch=1'b0, o_conflict_latch=1'b0;
logic [1:0]  addr_lsb, rd_addr_lsb=2'b0;
logic [31:0] addr_bus, wdata, rdata, rdata_latch=0;
logic [2:0]  rd_funct3=3'b0;
logic [3:0]  byte_enable;

assign addr_bus = {i_addr[31:2], 2'b0};
assign addr_lsb = i_addr[1:0];

assign o_conflict = (bus_master.rd_req & ~bus_master.rd_gnt) | (bus_master.wr_req & ~bus_master.wr_gnt);

assign bus_master.rd_req  = i_re;
assign bus_master.rd_be   = i_re ? byte_enable : 4'h0;
assign bus_master.rd_addr = i_re ? addr_bus : 0;
assign rdata = bus_master.rd_data;

assign bus_master.wr_req  = i_we;
assign bus_master.wr_be   = i_we ? byte_enable : 4'h0;
assign bus_master.wr_addr = i_we ? addr_bus : 0;
assign bus_master.wr_data = i_we ? wdata : 0;

always_comb
    casex(i_funct3)
        3'bx00    : if     (addr_lsb==2'b00) byte_enable <= 4'b0001;
                    else if(addr_lsb==2'b01) byte_enable <= 4'b0010;
                    else if(addr_lsb==2'b10) byte_enable <= 4'b0100;
                    else                     byte_enable <= 4'b1000;
        3'bx01    : if     (addr_lsb==2'b00) byte_enable <= 4'b0011;
                    else if(addr_lsb==2'b10) byte_enable <= 4'b1100;
                    else                     byte_enable <= 4'b0000;
        3'b010    : if     (addr_lsb==2'b00) byte_enable <= 4'b1111;
                    else                     byte_enable <= 4'b0000;
        default   :                          byte_enable <= 4'b0000;
    endcase

always_comb
    case(i_funct3)
        3'b000    : if     (addr_lsb==2'b00) wdata <= {24'b0, i_wdata[7:0]       };
                    else if(addr_lsb==2'b01) wdata <= {16'b0, i_wdata[7:0],  8'b0};
                    else if(addr_lsb==2'b10) wdata <= { 8'b0, i_wdata[7:0], 16'b0};
                    else                     wdata <= {       i_wdata[7:0], 24'b0};
        3'b001    : if     (addr_lsb==2'b00) wdata <= {16'b0, i_wdata[15:0]};
                    else if(addr_lsb==2'b10) wdata <= {i_wdata[15:0], 16'b0};
                    else                     wdata <= 0;
        3'b010    : if     (addr_lsb==2'b00) wdata <= i_wdata;
                    else                     wdata <= 0;
        default   :                          wdata <= 0;
    endcase

always @ (posedge clk or negedge rstn)
    if(~rstn) begin
        i_re_latch  <= 1'b0;
        rd_addr_lsb <= 2'b0;
        rd_funct3   <= 3'b0;
        o_conflict_latch <= 1'b0;
        rdata_latch <= 0;
    end else begin
        i_re_latch  <= i_re;
        rd_addr_lsb <= addr_lsb;
        rd_funct3   <= i_funct3;
        o_conflict_latch <= o_conflict;
        rdata_latch <= o_rdata;
    end

// assign o_rdata
always_comb
    if(i_re_latch) begin
        if(~o_conflict_latch)
            case(rd_funct3)
            3'b000    : if     (rd_addr_lsb==2'b00) o_rdata <= {{24{rdata[ 7]}}, rdata[ 7: 0]};
                        else if(rd_addr_lsb==2'b01) o_rdata <= {{24{rdata[15]}}, rdata[15: 8]};
                        else if(rd_addr_lsb==2'b10) o_rdata <= {{24{rdata[23]}}, rdata[23:16]};
                        else                        o_rdata <= {{24{rdata[31]}}, rdata[31:24]};

                        else if(rd_addr_lsb==2'b10) o_rdata <= {{16{rdata[31]}}, rdata[31:16]};
                        else                        o_rdata <= 0;
            3'b101    : if     (rd_addr_lsb==2'b00) o_rdata <= {          16'b0, rdata[15: 0]};
                        else if(rd_addr_lsb==2'b10) o_rdata <= {          16'b0, rdata[31:16]};
                        else                        o_rdata <= 0;
            3'b010    : if     (rd_addr_lsb==2'b00) o_rdata <= rdata;
                        else                        o_rdata <= 0;
            default   :                             o_rdata <= 0;
            endcase
        else
            o_rdata <= 0;
    end else begin
        o_rdata <= rdata_latch;
    end

endmodule


          .LO      ( HI - (HI-LO)/2 )
        ) hi
        (
          .HSEL       ( HSEL        ),
          .priority_i ( priority_i  ),
          .priority_o ( priority_hi )
        );
    end
    else
    begin
        //get priority for master[LO] and master[HI]
        //set priority to 0 when HSEL negated
        assign priority_lo = HSEL[LO] ? priority_i[LO] : {PRIORITY_BITS{1'b0}};
        assign priority_hi = HSEL[HI] ? priority_i[HI] : {PRIORITY_BITS{1'b0}};
    end
  endgenerate

  //finally do comparison
  assign priority_o = priority_hi > priority_lo ? priority_hi : priority_lo;

endmodule : ahb3lite_interconnect_slave_priority


module serial_to_parallel #(parameter WEIDTH=8)
(
	input rst_n,
	input clk,
	input data_in,
	output reg [WEIDTH-1:0] data_out,

);

reg [2:0] cnt;

always@(posedge clk or negedge rst_n) begin
	if(!rst_n) begin
		data_out<=8'b0;
		end
	else begin
		data_out<={data_out[WEIDTH-2:0],data_in};
	end
end

endmodule


/*
 * Article:
 *  SystemVerilog Macros
 *
 * Description:
 *  This file has examples 1.1, 1.2 and 1.3. The run command will run
 *  all 3 examples
 *
 * Run instructions
 * (use run_questa.sh instead of run_vcs.sh to run with Mentor simulator):
 *  ./run_vcs.sh macros1.sv
 */
/* Example 1.1 */
`define simplemacro $display("\n This is a simple macro\n");

`define append_front_1_good(MOD) `"MOD.master`"

/* Example 1.2 */
`define append_front_2a(MOD) `"MOD.master`"
`define append_front_2b(MOD) `"MOD master`"
`define append_front_2c_bad(MOD) `"MOD_master`"
`define append_front_2c_good(MOD) `"MOD``_master`"
`define append_middle(MOD) `"top_``MOD``_master`"
`define append_end(MOD) `"top_``MOD`"
`define append_front_3(MOD) `"MOD``.master`"

/* Example 1.3 */
`define complex_string(ARG1, ARG2) \
    `"This `\`"Blue``ARG1`\`" is Really `\`"ARG2`\`"`"

program automatic test;
    initial begin
        /* Example 1.1 */
        `simplemacro
        $display(`append_front_1_bad(clock1));
        $display(`append_front_1_good(clock1));

        /* Example 1.2 */
        $display(`append_front_2a(clock2a));
        $display(`append_front_2b(clock2b));
        $display(`append_front_2c_bad(clock2c));
        $display(`append_front_2c_good(clock2c));
        $display(`append_front_3(clock3));
        $display(`append_middle(clock4));
        $display(`append_end(clock5));

        /* Example 1.3 */
        $display(`complex_string(Beast, Black));
    end
endprogram: test


endfunction:new

//-----------------------------------------------------------------------------
// Function: build_phase
// Creates the slave_agent components
//
// Parameters:
//  phase - stores the current phase
//-----------------------------------------------------------------------------

function void slave_agt_top::build_phase(uvm_phase phase);
  if(!uvm_config_db#(environment_config)::get(this,"","ENVIRONMENT_CONFIG",ecfg))
  `uvm_fatal("SLAVE_AGT_TOP","couldnt get")

  sagt=new[ecfg.no_of_sagent];
foreach(sagt[i])
 begin
  sagt[i]=slave_agent::type_id::create($sformatf("magt[%0d]",i),this);
   uvm_config_db#(slave_agent_config)::set(this,"*","SLAVE_AGT_CONFIG",ecfg.scfg[i]);
 end
endfunction:build_phase


/* verilator lint_off UNUSED */
/* verilator lint_off UNDRIVEN */
(* blackbox *)
module SB_RGBA_DRV(
	input CURREN,

parameter RGB0_CURRENT = "0b000000";
parameter RGB1_CURRENT = "0b000000";
parameter RGB2_CURRENT = "0b000000";
endmodule
/* verilator lint_on UNDRIVEN */
/* verilator lint_on UNUSED */

	input RGBLEDEN,
	input RGB0PWM,
	input RGB1PWM,
	input RGB2PWM,
	output RGB0,


// Copyright (C) 2019, Gray Research LLC
//

//////////////////////////////////////////////////////////////////////////////
// BNNDotProd CFU

/* verilator lint_off DECLFILENAME */

`include "cfu.vh"

// Test bench
module BNNDotProd32TB #(
    parameter CFU_FUNC_ID_W = 1,
    parameter CFU_REQ_DATA_W = 32,
    parameter CFU_RESP_DATA_W = CFU_REQ_DATA_W
) (
    input clk,
    input [15:0] cycle,
    input [15:0] lfsr);

    wire `CFU_FUNC_ID req_func_id = 0;
    reg `CFU_REQ_DATA req_data0 `vp = 0;
    reg `CFU_REQ_DATA req_data1 `vp = 0;
    reg `CFU_RESP_DATA resp_data `vp = 0;

    reg `CFU_RESP_DATA xnor_ `vp = 0;
    reg `CFU_RESP_DATA answer `vp = 0;
    int i;
    always @* begin
        req_data0 = {cycle-1'b1,cycle};
        req_data1 = {16'b0,lfsr};

        xnor_ = req_data0 ~^ req_data1;
        answer = 0;
        for (i = 0; i < CFU_REQ_DATA_W; i = i + 1) begin
            if (xnor_[i])
                answer = answer + 1;
        end
    end

    BNNDotProd32_CFU_LI0 #(
        .CFU_FUNC_ID_W(CFU_FUNC_ID_W),
        .CFU_REQ_DATA_W(CFU_REQ_DATA_W),
        .CFU_RESP_DATA_W(CFU_RESP_DATA_W))

    end
endmodule

// Level-0 (Combinational) 1b binary neural net dot product combinational CFU
//
// A binary neural net has 1b weights and activations, each encoded { 0=>+1, 1=>-1 }.
// The (biased) dot product of W: w*1b weights and A: w*1b activations is popcount(W~^A).
//
// (Obselete) Metadata -- REVIEW
//  Supports: REQ_WIDTH==32 or REQ_WIDTH==64
//  IID: IID_BNNDotProd
//  Functions: {BNNDotProd}
//  Inputs: w*1b activations, w*1b weights
//  Outputs: w-bit BNN dot product
//
/* Metadata
CFU_LI:
    - feature_level: 0
    - cfu_req_data_w: [32]
    - cfu_resp_data_w: [32]
    - cfu_func_id_w: [1]
*/
module BNNDotProd32_CFU_LI0 #(
    parameter CFU_FUNC_ID_W = 1,
    parameter CFU_REQ_DATA_W = 32,
    parameter CFU_RESP_DATA_W = 32
) (
    input req_valid, // unused
    input `CFU_FUNC_ID req_func_id,  // unused
    input `CFU_REQ_DATA req_data0,
    input `CFU_REQ_DATA req_data1,
    output `CFU_RESP_DATA resp_data
);
    wire `CFU_REQ_DATA xnor_ = req_data0 ~^ req_data1;
    wire [5:0] count;
    Popcount32 count_(.i(xnor_), .popcount(count));
    assign resp_data = {26'b0,count};

    // assert(req_function_id == IID_BNNDotProd32.BNNDotProd32)
    wire _unused_ok = &{1'b0,req_valid,req_func_id,1'b0};
endmodule

      bnn(.req_valid(1'b1), .req_func_id(req_func_id), .req_data0(req_data0), .req_data1(req_data1), .resp_data(resp_data));

    always @(posedge clk) begin