// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or it's affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//********************************************************************************
// eh2_dec_csr.sv
//
//
// Function: CSR decodes
//********************************************************************************

module eh2_dec_csr
import eh2_pkg::*;
#(
`include "eh2_param.vh"
)
  (

input logic [11:0] dec_csr_rdaddr_d,
input logic dec_csr_any_unq_d,
input logic dec_csr_wen_unq_d,
input logic dec_tlu_dbg_halted,

output logic dec_csr_legal_d,
output logic tlu_presync_d,
output logic tlu_postsync_d,

output eh2_csr_tlu_pkt_t tlu_csr_pkt_d
);

// file "csrdecode" is human readable file that has all of the CSR decodes defined and is part of git repo
// modify this file as needed

// to generate all the equations below from "csrdecode" except legal equation:
// 1) coredecode -in csrdecode > corecsrdecode.e
// 2) espresso -Dso -oeqntott corecsrdecode.e | addassign  > csrequations

// to generate the legal CSR equation below:
// 1) coredecode -in csrdecode -legal > csrlegal.e
// 2) espresso -Dso -oeqntott csrlegal.e | addassign  > csrlegal_equation

// coredecode -in csrdecode > corecsrdecode.e; espresso -Dso -oeqntott corecsrdecode.e | addassign  > csrequations; coredecode -in csrdecode -legal > csrlegal.e; espresso -Dso -oeqntott csrlegal.e | addassign  > csrlegal_equation

// insert "csrequations" here
logic csr_misa;
logic csr_mvendorid;
logic csr_marchid;
logic csr_mimpid;
logic csr_mhartid;
logic csr_mstatus;
logic csr_mtvec;
logic csr_mip;
logic csr_mie;
logic csr_mcyclel;
logic csr_mcycleh;
logic csr_minstretl;
logic csr_minstreth;
logic csr_mscratch;
logic csr_mepc;
logic csr_mcause;
logic csr_mscause;
logic csr_mtval;
logic csr_mrac;
logic csr_dmst;
logic csr_mdseac;
logic csr_meihap;
logic csr_meivt;
logic csr_meipt;
logic csr_meicurpl;
logic csr_meicidpl;
logic csr_dcsr;
logic csr_mcgc;
logic csr_mfdc;
logic csr_dpc;
logic csr_mtsel;
logic csr_mtdata1;
logic csr_mtdata2;
logic csr_mhpmc3;
logic csr_mhpmc4;
logic csr_mhpmc5;
logic csr_mhpmc6;
logic csr_mhpmc3h;
logic csr_mhpmc4h;
logic csr_mhpmc5h;
logic csr_mhpmc6h;
logic csr_mhpme3;
logic csr_mhpme4;
logic csr_mhpme5;
logic csr_mhpme6;
logic csr_mitctl0;
logic csr_mitctl1;
logic csr_mitb0;
logic csr_mitb1;
logic csr_mitcnt0;
logic csr_mitcnt1;
logic csr_perfva;
logic csr_perfvb;
logic csr_perfvc;
logic csr_perfvd;
logic csr_perfve;
logic csr_perfvf;
logic csr_perfvg;
logic csr_perfvh;
logic csr_perfvi;
logic csr_mpmc;
logic csr_mcpc;
logic csr_meicpct;
logic csr_mdeau;
logic csr_micect;
logic csr_miccmect;
logic csr_mdccmect;
logic csr_mcountinhibit;
logic csr_mfdht;
logic csr_mfdhs;
logic csr_dicawics;
logic csr_dicad0h;
logic csr_dicad0;
logic csr_dicad1;
logic csr_dicago;
logic csr_mhartnum;
logic csr_mhartstart;
logic csr_mnmipdel;
logic valid_only;
logic presync;
logic postsync;
logic glob;
//logic ooat;

logic conditionally_illegal, valid_csr;
logic legal;

assign csr_misa = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]);

assign csr_mvendorid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_marchid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[7]
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mimpid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_mhartid = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[7]
    &dec_csr_rdaddr_d[2]);

assign csr_mstatus = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]);

assign csr_mtvec = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]);

assign csr_mip = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[2]);

assign csr_mie = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]);

assign csr_mcyclel = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[1]);

assign csr_mcycleh = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);

assign csr_minstretl = (!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_minstreth = (!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mscratch = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mepc = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]);

assign csr_mcause = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mscause = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_mtval = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]);

assign csr_mrac = (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);

assign csr_dmst = (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);

assign csr_mdseac = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]);

assign csr_meihap = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[3]);

assign csr_meivt = (!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]);

assign csr_meipt = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]);

assign csr_meicurpl = (!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]);

assign csr_meicidpl = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_dcsr = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[0]);

assign csr_mcgc = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]);

assign csr_mfdc = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_dpc = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[0]);

assign csr_mtsel = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mtdata1 = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[0]);

assign csr_mtdata2 = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[1]);

assign csr_mhpmc3 = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[0]);

assign csr_mhpmc4 = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mhpmc5 = (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]);

assign csr_mhpmc6 = (!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mhpmc3h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]);

assign csr_mhpmc4h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]

    &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mhpmc5h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]);

assign csr_mhpmc6h = (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
<TARGET>
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mhpme3 = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[0]);

assign csr_mhpme4 = (dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]);

assign csr_mhpme5 = (dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]);

assign csr_mhpme6 = (dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]);

assign csr_mitctl0 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mitctl1 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[3]
    &dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_mitb0 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]);

assign csr_mitb1 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]
    &dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mitcnt0 = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]);

assign csr_mitcnt1 = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_mpmc = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]);

assign csr_mcpc = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]);

assign csr_meicpct = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mdeau = (!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[7]
    &dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[3]);

assign csr_micect = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_miccmect = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[0]);

assign csr_mdccmect = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]);

assign csr_mcountinhibit = (!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[0]);

assign csr_mfdht = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
    &dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_mfdhs = (dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[0]);

assign csr_dicawics = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]);

assign csr_dicad0h = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]
    &dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);

assign csr_dicad0 = (dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]
    &dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_dicad1 = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign csr_dicago = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]);

assign csr_mhartnum = (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[2]);

assign csr_mhartstart = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]);

assign csr_mnmipdel = (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]);

assign presync = (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[7]
    &dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[1]);

assign postsync = (dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[2]
    &dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]) | (
    !dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[1]
    &dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[1]) | (!dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]) | (
    dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[7]
    &dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]);

assign glob = (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[2]) | (dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]) | (
    dec_csr_rdaddr_d[10]&!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[2]) | (dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[7]
    &dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[1]);

   // insert "csrlegal_equation" here
assign legal = (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
    &dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
    &dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]) | (!dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[0]) | (
    dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]
    &dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]
    &dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]) | (
    !dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
    &dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[2]
    &!dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[9]
    &dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[2]) | (!dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]) | (dec_csr_rdaddr_d[11]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]
    &!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[9]
    &dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&dec_csr_rdaddr_d[1]) | (!dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[1]&dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]
    &dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]) | (!dec_csr_rdaddr_d[11]
    &dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]) | (
    !dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
    &dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &dec_csr_rdaddr_d[2]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[2]) | (!dec_csr_rdaddr_d[11]
    &dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&dec_csr_rdaddr_d[1]) | (
    dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
    &dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[1]) | (!dec_csr_rdaddr_d[11]
    &dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]) | (
    !dec_csr_rdaddr_d[11]&dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]
    &dec_csr_rdaddr_d[8]&dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]
    &dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[2]&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
    &dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &!dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[2]) | (
    dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &dec_csr_rdaddr_d[7]&dec_csr_rdaddr_d[6]&!dec_csr_rdaddr_d[5]
    &!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]&!dec_csr_rdaddr_d[1]
    &!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[7]
    &!dec_csr_rdaddr_d[5]&!dec_csr_rdaddr_d[4]&!dec_csr_rdaddr_d[3]
    &!dec_csr_rdaddr_d[1]&!dec_csr_rdaddr_d[0]) | (!dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[3]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[3]) | (!dec_csr_rdaddr_d[11]
    &!dec_csr_rdaddr_d[10]&dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]
    &!dec_csr_rdaddr_d[7]&!dec_csr_rdaddr_d[6]&dec_csr_rdaddr_d[5]
    &dec_csr_rdaddr_d[4]) | (dec_csr_rdaddr_d[11]&!dec_csr_rdaddr_d[10]
    &dec_csr_rdaddr_d[9]&dec_csr_rdaddr_d[8]&!dec_csr_rdaddr_d[6]
    &!dec_csr_rdaddr_d[5]&dec_csr_rdaddr_d[4]);

//
   assign tlu_presync_d = presync & dec_csr_any_unq_d & ~dec_csr_wen_unq_d;
   assign tlu_postsync_d = postsync & dec_csr_any_unq_d;

   // allow individual configuration of these features
   assign conditionally_illegal = ((csr_mitcnt0 | csr_mitcnt1 | csr_mitb0 | csr_mitb1 | csr_mitctl0 | csr_mitctl1) & !pt.TIMER_LEGAL_EN) |
                                  (csr_meicpct & pt.FAST_INTERRUPT_REDIRECT);

   assign valid_csr = ( legal &
                        // not a debug only csr during running mode
                        (~(csr_dcsr | csr_dpc | csr_dmst | csr_dicawics | csr_dicad0 | csr_dicad0h | csr_dicad1 | csr_dicago) | dec_tlu_dbg_halted) &
                        // not conditionally illegal based on configuration
                        ~conditionally_illegal
                        );

   assign dec_csr_legal_d = ( dec_csr_any_unq_d &
                              valid_csr &          // of a valid CSR
                              ~(dec_csr_wen_unq_d & (csr_mvendorid | csr_marchid | csr_mimpid | csr_mhartid |
                                                     csr_mdseac | csr_meihap | csr_mhartnum)) // that's not a write to a RO CSR
                              );

   assign tlu_csr_pkt_d.csr_misa = csr_misa;
   assign tlu_csr_pkt_d.csr_mvendorid = csr_mvendorid;
   assign tlu_csr_pkt_d.csr_marchid = csr_marchid;
   assign tlu_csr_pkt_d.csr_mimpid = csr_mimpid;
   assign tlu_csr_pkt_d.csr_mhartid = csr_mhartid;
   assign tlu_csr_pkt_d.csr_mstatus = csr_mstatus;
   assign tlu_csr_pkt_d.csr_mtvec = csr_mtvec;
   assign tlu_csr_pkt_d.csr_mip = csr_mip;
   assign tlu_csr_pkt_d.csr_mie = csr_mie;
   assign tlu_csr_pkt_d.csr_mcyclel = csr_mcyclel;
   assign tlu_csr_pkt_d.csr_mcycleh = csr_mcycleh;
   assign tlu_csr_pkt_d.csr_minstretl = csr_minstretl;
   assign tlu_csr_pkt_d.csr_minstreth = csr_minstreth;
   assign tlu_csr_pkt_d.csr_mscratch = csr_mscratch;
   assign tlu_csr_pkt_d.csr_mepc = csr_mepc;
   assign tlu_csr_pkt_d.csr_mcause = csr_mcause;
   assign tlu_csr_pkt_d.csr_mscause = csr_mscause;
   assign tlu_csr_pkt_d.csr_mtval = csr_mtval;
   assign tlu_csr_pkt_d.csr_mrac = csr_mrac;
   assign tlu_csr_pkt_d.csr_dmst = csr_dmst;
   assign tlu_csr_pkt_d.csr_mdseac = csr_mdseac;
   assign tlu_csr_pkt_d.csr_meihap = csr_meihap;
   assign tlu_csr_pkt_d.csr_meivt = csr_meivt;
   assign tlu_csr_pkt_d.csr_meipt = csr_meipt;
   assign tlu_csr_pkt_d.csr_meicurpl = csr_meicurpl;
   assign tlu_csr_pkt_d.csr_meicidpl = csr_meicidpl;
   assign tlu_csr_pkt_d.csr_dcsr = csr_dcsr;
   assign tlu_csr_pkt_d.csr_mcgc = csr_mcgc;
   assign tlu_csr_pkt_d.csr_mfdc = csr_mfdc;
   assign tlu_csr_pkt_d.csr_dpc = csr_dpc;
   assign tlu_csr_pkt_d.csr_mtsel = csr_mtsel;
   assign tlu_csr_pkt_d.csr_mtdata1 = csr_mtdata1;
   assign tlu_csr_pkt_d.csr_mtdata2 = csr_mtdata2;
   assign tlu_csr_pkt_d.csr_mhpmc3 = csr_mhpmc3;
   assign tlu_csr_pkt_d.csr_mhpmc4 = csr_mhpmc4;
   assign tlu_csr_pkt_d.csr_mhpmc5 = csr_mhpmc5;
   assign tlu_csr_pkt_d.csr_mhpmc6 = csr_mhpmc6;
   assign tlu_csr_pkt_d.csr_mhpmc3h = csr_mhpmc3h;
   assign tlu_csr_pkt_d.csr_mhpmc4h = csr_mhpmc4h;
   assign tlu_csr_pkt_d.csr_mhpmc5h = csr_mhpmc5h;
   assign tlu_csr_pkt_d.csr_mhpmc6h = csr_mhpmc6h;
   assign tlu_csr_pkt_d.csr_mhpme3 = csr_mhpme3;
   assign tlu_csr_pkt_d.csr_mhpme4 = csr_mhpme4;
   assign tlu_csr_pkt_d.csr_mhpme5 = csr_mhpme5;
   assign tlu_csr_pkt_d.csr_mhpme6 = csr_mhpme6;
   assign tlu_csr_pkt_d.csr_mitctl0 = csr_mitctl0;
   assign tlu_csr_pkt_d.csr_mitctl1 = csr_mitctl1;
   assign tlu_csr_pkt_d.csr_mitb0 = csr_mitb0;
   assign tlu_csr_pkt_d.csr_mitb1 = csr_mitb1;
   assign tlu_csr_pkt_d.csr_mitcnt0 = csr_mitcnt0;
   assign tlu_csr_pkt_d.csr_mitcnt1 = csr_mitcnt1;
   assign tlu_csr_pkt_d.csr_mpmc = csr_mpmc;
   assign tlu_csr_pkt_d.csr_mcountinhibit = csr_mcountinhibit;
   assign tlu_csr_pkt_d.csr_mcpc = csr_mcpc;
   assign tlu_csr_pkt_d.csr_meicpct = csr_meicpct;
   assign tlu_csr_pkt_d.csr_mdeau = csr_mdeau;
   assign tlu_csr_pkt_d.csr_micect = csr_micect;
   assign tlu_csr_pkt_d.csr_miccmect = csr_miccmect;
   assign tlu_csr_pkt_d.csr_mdccmect = csr_mdccmect;
   assign tlu_csr_pkt_d.csr_dicawics = csr_dicawics;
   assign tlu_csr_pkt_d.csr_dicad0h = csr_dicad0h;
   assign tlu_csr_pkt_d.csr_dicad0 = csr_dicad0;
   assign tlu_csr_pkt_d.csr_dicad1 = csr_dicad1;
   assign tlu_csr_pkt_d.csr_dicago = csr_dicago;
   assign tlu_csr_pkt_d.csr_mfdht = csr_mfdht;
   assign tlu_csr_pkt_d.csr_mfdhs = csr_mfdhs;
   assign tlu_csr_pkt_d.csr_mhartnum = csr_mhartnum;
   assign tlu_csr_pkt_d.csr_mhartstart = csr_mhartstart;
   assign tlu_csr_pkt_d.csr_mnmipdel = csr_mnmipdel;
   assign tlu_csr_pkt_d.valid_only = valid_only;
   assign tlu_csr_pkt_d.presync = presync;
   assign tlu_csr_pkt_d.postsync = postsync;
   assign tlu_csr_pkt_d.glob = glob;
   assign tlu_csr_pkt_d.legal = legal;

endmodule


module priority_arbiter_8
  #(
	parameter PRIORITY_WIDTH = 8,
	parameter DATA_WIDTH = 2
	)
   (
	input [7:0][PRIORITY_WIDTH-1:0] priority_i,
	input [7:0][DATA_WIDTH-1:0] 	data_i,
	input [7:0] 			req,
	input [PRIORITY_WIDTH-1:0] 	highest_priority,
	output [DATA_WIDTH-1:0] 	data_o,
	output 			valid,
	output [2:0] 			grant
	);

   // This module accepts 8 input reqs, each req is associated with priority.
   // The data request with highest priority is passed to output.
   //  Priority order: highest priority i/p value to highest priority-1(lowest).
   // It is in wrap around fashion.

   logic [2:0] 			select_lcl;
   logic [7:0][PRIORITY_WIDTH-1:0] 	priority_lcl;

//	  for(genvar i = 0; i<=7; i++)
//		assign priority_lcl[i] = priority_i[i] - highest_priority;
//   endgenerate

  assign priority_lcl[0] = priority_i[0] - highest_priority;
  assign priority_lcl[1] = priority_i[1] - highest_priority;
  assign priority_lcl[2] = priority_i[2] - highest_priority;
  assign priority_lcl[3] = priority_i[3] - highest_priority;
  assign priority_lcl[4] = priority_i[4] - highest_priority;
  assign priority_lcl[5] = priority_i[5] - highest_priority;
  assign priority_lcl[6] = priority_i[6] - highest_priority;
  assign priority_lcl[7] = priority_i[7] - highest_priority;

   lowest_nr_identifier_8
	 #(
	   .NR_WIDTH(PRIORITY_WIDTH)
	   )highest_priority_selector
	   (
		.nr(priority_lcl),
		.req(req),
		.lowest_nr(),
		.lowest_line(select_lcl),
		.lowest_valid(valid)
		);
   assign grant = select_lcl;

   mux_8_1
	 #(
	   .WIDTH (DATA_WIDTH)

	   )mux
	   (
		.in(data_i),
		.sel(select_lcl),
		.out(data_o)


Pre_Silicon-AHB-to_APB-Verification/Checkpoint 3_ SystemVerilog OOP Testbench/VIP_Different_Approach/top.sv

// -----------------------------------------------------------------------------
// Project: AHB APB Bridge Verification
// Module:  Top-level Module
// File:    top.sv
// -----------------------------------------------------------------------------
// Author:  Mohamed Ghonim
// Created: 28-Jul-2023
//
// Description:
// The top-level module of the testbench, ahb_apb_top, integrates all the
// components of the testbench and connects them with the DUT (Device Under
// Verification). The DUT is an AHB to APB bridge, and its module name is
// 'Bridge_Top'.
//
// The top module includes several files:
// 1. transactions.sv - defines the transaction class
// 2. generator.sv - defines the generator class
// 3. interface.sv - defines the interface class
// 4. driver.sv - defines the driver class
// 5. monitor.sv - defines the monitor class
// 6. scoreboard.sv - defines the scoreboard class
// 7. coverage.sv - defines the coverage collector class
// 8. environment.sv - defines the environment class
// 9. test.sv - defines the test class
// 10. bridge_top.v - this is presumably the Verilog source code for the DUT
//
// The top module also generates a clock signal 'clk' with a period of 10 ns
// (half period of 5 ns). The reset signal 'reset' is initialized to 0 and then
// set to 1 after 10 time units.
//
// The test class is instantiated as 'test_h'. The run method of the test
// class is called to start the test.
//
// The simulation is stopped after 100000 time units using the '$stop'
// system task.
//
// The DUT is instantiated as 'dut' and connected to the testbench using an
// instance of the ahb_apb_bfm_if interface named 'bfm'. This interface
// instance is used to drive signals into the DUT and monitor signals coming
// from the DUT.
// -----------------------------------------------------------------------------

`include "transactions.sv"
`include "generator.sv"
`include "interface.sv"
`include "driver.sv"
`include "monitor.sv"
`include "scoreboard.sv"
`include "coverage.sv"
`include "environment.sv"
`include "test.sv"
`include "bridge_top.v"

module ahb_apb_top;

  ahb_apb_bfm_if bfm(clk, reset); // Connect clock and reset

  // Connecting DUT signals with signals present on the interface
// Connecting DUT signals with signals present on the interface
Bridge_Top dut(
    .Hclk(bfm.clk),
    .Hresetn(bfm.resetn),
    .Hwrite(bfm.Hwrite),
    .Hreadyin(bfm.Hreadyin),
    .Htrans(bfm.Htrans),
    .Hwdata(bfm.Hwdata),
    .Haddr(bfm.Haddr),
    .Hrdata(bfm.Hrdata),
    .Hresp(bfm.Hresp),
    .Hreadyout(bfm.Hreadyout),
    .Prdata(bfm.Prdata),
    .Pwdata(bfm.Pwdata),
    .Paddr(bfm.Paddr),
    .Pselx(bfm.Pselx),
    .Pwrite(bfm.Pwrite),
    .Penable(bfm.Penable)
);

  // test ahb_apb_test(bfm); // -> not initialized
    test test_h;
    Transaction trans;
  initial begin
    $display("in top");
    trans = new();
    trans.cov_cg.sample();  // -> to get the coverage
	test_h = new(bfm);
	test_h.run();

  end

 // Initialize clk and reset
  initial begin
    clk = 1;
    reset = 0;
    #10
    reset = 1;

    #100000;
    $stop; // Stops simulation
  end

endmodule

  logic clk, reset;

  // Generates clk with a time period of 5 ns
  always
  begin


/*

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

`timescale 1ns / 1ps

/*
 * AXI4 crossbar (read)
 */
module axi_crossbar_rd #
(
    // 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),
    // Input ID field width (from AXI masters)
    parameter S_ID_WIDTH = 8,
    // Output ID field width (towards AXI slaves)
    // Additional bits required for response routing
    parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT),
    // Propagate aruser signal
    parameter ARUSER_ENABLE = 0,
    // Width of aruser signal
    parameter ARUSER_WIDTH = 1,
    // Propagate ruser signal
    parameter RUSER_ENABLE = 0,
    // Width of ruser signal
    parameter RUSER_WIDTH = 1,
    // Number of concurrent unique IDs for each slave interface
    // S_COUNT concatenated fields of 32 bits
    parameter S_THREADS = {S_COUNT{32'd2}},
    // Number of concurrent operations for each slave interface
    // S_COUNT concatenated fields of 32 bits
    parameter S_ACCEPT = {S_COUNT{32'd16}},
    // 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 = {M_COUNT{{S_COUNT{1'b1}}}},
    // Number of concurrent operations for each master interface
    // M_COUNT concatenated fields of 32 bits
    parameter M_ISSUE = {M_COUNT{32'd4}},
    // Secure master (fail operations based on awprot/arprot)
    // M_COUNT bits
    parameter M_SECURE = {M_COUNT{1'b0}},
    // Slave interface AR channel register type (input)
    // 0 to bypass, 1 for simple buffer, 2 for skid buffer
    parameter S_AR_REG_TYPE = {S_COUNT{2'd0}},
    // Slave interface R channel register type (output)
    // 0 to bypass, 1 for simple buffer, 2 for skid buffer
    parameter S_R_REG_TYPE = {S_COUNT{2'd2}},
    // Master interface AR channel register type (output)
    // 0 to bypass, 1 for simple buffer, 2 for skid buffer
    parameter M_AR_REG_TYPE = {M_COUNT{2'd1}},
    // Master interface R channel register type (input)
    // 0 to bypass, 1 for simple buffer, 2 for skid buffer
    parameter M_R_REG_TYPE = {M_COUNT{2'd0}}
)
(
    input  wire                             clk,
    input  wire                             rst,

    /*
     * AXI slave interfaces
     */
    input  wire [S_COUNT*S_ID_WIDTH-1:0]    s_axi_arid,
    input  wire [S_COUNT*ADDR_WIDTH-1:0]    s_axi_araddr,
    input  wire [S_COUNT*8-1:0]             s_axi_arlen,
    input  wire [S_COUNT*3-1:0]             s_axi_arsize,
    input  wire [S_COUNT*2-1:0]             s_axi_arburst,
    input  wire [S_COUNT-1:0]               s_axi_arlock,
    input  wire [S_COUNT*4-1:0]             s_axi_arcache,
    input  wire [S_COUNT*3-1:0]             s_axi_arprot,
    input  wire [S_COUNT*4-1:0]             s_axi_arqos,
    input  wire [S_COUNT*ARUSER_WIDTH-1:0]  s_axi_aruser,
    input  wire [S_COUNT-1:0]               s_axi_arvalid,
    output wire [S_COUNT-1:0]               s_axi_arready,
    output wire [S_COUNT*S_ID_WIDTH-1:0]    s_axi_rid,
    output wire [S_COUNT*DATA_WIDTH-1:0]    s_axi_rdata,
    output wire [S_COUNT*2-1:0]             s_axi_rresp,
    output wire [S_COUNT-1:0]               s_axi_rlast,
    output wire [S_COUNT*RUSER_WIDTH-1:0]   s_axi_ruser,
    output wire [S_COUNT-1:0]               s_axi_rvalid,
    input  wire [S_COUNT-1:0]               s_axi_rready,

    /*
     * AXI master interfaces
     */
    output wire [M_COUNT*M_ID_WIDTH-1:0]    m_axi_arid,
    output wire [M_COUNT*ADDR_WIDTH-1:0]    m_axi_araddr,
    output wire [M_COUNT*8-1:0]             m_axi_arlen,
    output wire [M_COUNT*3-1:0]             m_axi_arsize,
    output wire [M_COUNT*2-1:0]             m_axi_arburst,
    output wire [M_COUNT-1:0]               m_axi_arlock,
    output wire [M_COUNT*4-1:0]             m_axi_arcache,
    output wire [M_COUNT*3-1:0]             m_axi_arprot,
    output wire [M_COUNT*4-1:0]             m_axi_arqos,
    output wire [M_COUNT*4-1:0]             m_axi_arregion,
    output wire [M_COUNT*ARUSER_WIDTH-1:0]  m_axi_aruser,
    output wire [M_COUNT-1:0]               m_axi_arvalid,
    input  wire [M_COUNT-1:0]               m_axi_arready,
    input  wire [M_COUNT*M_ID_WIDTH-1:0]    m_axi_rid,
    input  wire [M_COUNT*DATA_WIDTH-1:0]    m_axi_rdata,
    input  wire [M_COUNT*2-1:0]             m_axi_rresp,
    input  wire [M_COUNT-1:0]               m_axi_rlast,
    input  wire [M_COUNT*RUSER_WIDTH-1:0]   m_axi_ruser,
    input  wire [M_COUNT-1:0]               m_axi_rvalid,
    output wire [M_COUNT-1:0]               m_axi_rready
);

parameter CL_S_COUNT = $clog2(S_COUNT);
parameter CL_M_COUNT = $clog2(M_COUNT);
parameter M_COUNT_P1 = M_COUNT+1;
parameter CL_M_COUNT_P1 = $clog2(M_COUNT_P1);

integer i;

// check configuration
initial begin
    if (M_ID_WIDTH < S_ID_WIDTH+$clog2(S_COUNT)) begin
        $error("Error: M_ID_WIDTH must be at least $clog2(S_COUNT) larger than S_ID_WIDTH (instance %m)");
        $finish;
    end

    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] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin
            $error("Error: value out of range (instance %m)");
            $finish;
        end
    end
end

wire [S_COUNT*S_ID_WIDTH-1:0]    int_s_axi_arid;
wire [S_COUNT*ADDR_WIDTH-1:0]    int_s_axi_araddr;
wire [S_COUNT*8-1:0]             int_s_axi_arlen;
wire [S_COUNT*3-1:0]             int_s_axi_arsize;
wire [S_COUNT*2-1:0]             int_s_axi_arburst;
wire [S_COUNT-1:0]               int_s_axi_arlock;
wire [S_COUNT*4-1:0]             int_s_axi_arcache;
wire [S_COUNT*3-1:0]             int_s_axi_arprot;
wire [S_COUNT*4-1:0]             int_s_axi_arqos;
wire [S_COUNT*4-1:0]             int_s_axi_arregion;
wire [S_COUNT*ARUSER_WIDTH-1:0]  int_s_axi_aruser;
wire [S_COUNT-1:0]               int_s_axi_arvalid;
wire [S_COUNT-1:0]               int_s_axi_arready;

wire [S_COUNT*M_COUNT-1:0]       int_axi_arvalid;
wire [M_COUNT*S_COUNT-1:0]       int_axi_arready;

wire [M_COUNT*M_ID_WIDTH-1:0]    int_m_axi_rid;
wire [M_COUNT*DATA_WIDTH-1:0]    int_m_axi_rdata;
wire [M_COUNT*2-1:0]             int_m_axi_rresp;
wire [M_COUNT-1:0]               int_m_axi_rlast;
wire [M_COUNT*RUSER_WIDTH-1:0]   int_m_axi_ruser;
wire [M_COUNT-1:0]               int_m_axi_rvalid;
wire [M_COUNT-1:0]               int_m_axi_rready;

wire [M_COUNT*S_COUNT-1:0]       int_axi_rvalid;
wire [S_COUNT*M_COUNT-1:0]       int_axi_rready;

generate

    genvar m, n;

    for (m = 0; m < S_COUNT; m = m + 1) begin : s_ifaces
        // address decode and admission control
        wire [CL_M_COUNT-1:0] a_select;

        wire m_axi_avalid;
        wire m_axi_aready;

        wire m_rc_decerr;
        wire m_rc_valid;
        wire m_rc_ready;

        wire [S_ID_WIDTH-1:0] s_cpl_id;
        wire s_cpl_valid;

        axi_crossbar_addr #(
            .S(m),
            .S_COUNT(S_COUNT),
            .M_COUNT(M_COUNT),
            .ADDR_WIDTH(ADDR_WIDTH),
            .ID_WIDTH(S_ID_WIDTH),
            .S_THREADS(S_THREADS[m*32 +: 32]),
            .S_ACCEPT(S_ACCEPT[m*32 +: 32]),
            .M_REGIONS(M_REGIONS),
            .M_BASE_ADDR(M_BASE_ADDR),
            .M_ADDR_WIDTH(M_ADDR_WIDTH),
            .M_CONNECT(M_CONNECT),
            .M_SECURE(M_SECURE),
            .WC_OUTPUT(0)
        )
        addr_inst (
            .clk(clk),
            .rst(rst),

            /*
             * Address input
             */
            .s_axi_aid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]),
            .s_axi_aaddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
            .s_axi_aprot(int_s_axi_arprot[m*3 +: 3]),
            .s_axi_aqos(int_s_axi_arqos[m*4 +: 4]),
            .s_axi_avalid(int_s_axi_arvalid[m]),
            .s_axi_aready(int_s_axi_arready[m]),

            /*
             * Address output
             */
            .m_axi_aregion(int_s_axi_arregion[m*4 +: 4]),
            .m_select(a_select),
            .m_axi_avalid(m_axi_avalid),
            .m_axi_aready(m_axi_aready),

            /*
             * Write command output
             */
            .m_wc_select(),
            .m_wc_decerr(),
            .m_wc_valid(),
            .m_wc_ready(1'b1),

            /*
             * Response command output
             */
            .m_rc_decerr(m_rc_decerr),
            .m_rc_valid(m_rc_valid),
            .m_rc_ready(m_rc_ready),

            /*
             * Completion input
             */
            .s_cpl_id(s_cpl_id),
            .s_cpl_valid(s_cpl_valid)
        );

        assign int_axi_arvalid[m*M_COUNT +: M_COUNT] = m_axi_avalid << a_select;
        assign m_axi_aready = int_axi_arready[a_select*S_COUNT+m];

        // decode error handling
        reg [S_ID_WIDTH-1:0]  decerr_m_axi_rid_reg = {S_ID_WIDTH{1'b0}}, decerr_m_axi_rid_next;
        reg                   decerr_m_axi_rlast_reg = 1'b0, decerr_m_axi_rlast_next;
        reg                   decerr_m_axi_rvalid_reg = 1'b0, decerr_m_axi_rvalid_next;
        wire                  decerr_m_axi_rready;

        reg [7:0] decerr_len_reg = 8'd0, decerr_len_next;

        assign m_rc_ready = !decerr_m_axi_rvalid_reg;

        always @* begin
            decerr_len_next = decerr_len_reg;
            decerr_m_axi_rid_next = decerr_m_axi_rid_reg;
            decerr_m_axi_rlast_next = decerr_m_axi_rlast_reg;
            decerr_m_axi_rvalid_next = decerr_m_axi_rvalid_reg;

            if (decerr_m_axi_rvalid_reg) begin
                if (decerr_m_axi_rready) begin
                    if (decerr_len_reg > 0) begin
                        decerr_len_next = decerr_len_reg-1;
                        decerr_m_axi_rlast_next = (decerr_len_next == 0);
                        decerr_m_axi_rvalid_next = 1'b1;
                    end else begin
                        decerr_m_axi_rvalid_next = 1'b0;
                    end
                end
            end else if (m_rc_valid && m_rc_ready) begin
                decerr_len_next = int_s_axi_arlen[m*8 +: 8];
                decerr_m_axi_rid_next = int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH];
                decerr_m_axi_rlast_next = (decerr_len_next == 0);
                decerr_m_axi_rvalid_next = 1'b1;
            end
        end

        always @(posedge clk) begin

                decerr_m_axi_rvalid_reg <= 1'b0;
            end else begin
                decerr_m_axi_rvalid_reg <= decerr_m_axi_rvalid_next;
            end

            decerr_m_axi_rid_reg <= decerr_m_axi_rid_next;
            decerr_m_axi_rlast_reg <= decerr_m_axi_rlast_next;
            decerr_len_reg <= decerr_len_next;
        end

        // read response arbitration
        wire [M_COUNT_P1-1:0] r_request;
        wire [M_COUNT_P1-1:0] r_acknowledge;
        wire [M_COUNT_P1-1:0] r_grant;
        wire r_grant_valid;
        wire [CL_M_COUNT_P1-1:0] r_grant_encoded;

        arbiter #(
            .PORTS(M_COUNT_P1),
            .ARB_TYPE_ROUND_ROBIN(1),
            .ARB_BLOCK(1),
            .ARB_BLOCK_ACK(1),
            .ARB_LSB_HIGH_PRIORITY(1)
        )
        r_arb_inst (
            .clk(clk),
            .rst(rst),
            .request(r_request),
            .acknowledge(r_acknowledge),
            .grant(r_grant),
            .grant_valid(r_grant_valid),
            .grant_encoded(r_grant_encoded)
        );

        // read response mux
        wire [S_ID_WIDTH-1:0]  m_axi_rid_mux    = {decerr_m_axi_rid_reg, int_m_axi_rid} >> r_grant_encoded*M_ID_WIDTH;
        wire [DATA_WIDTH-1:0]  m_axi_rdata_mux  = {{DATA_WIDTH{1'b0}}, int_m_axi_rdata} >> r_grant_encoded*DATA_WIDTH;
        wire [1:0]             m_axi_rresp_mux  = {2'b11, int_m_axi_rresp} >> r_grant_encoded*2;
        wire                   m_axi_rlast_mux  = {decerr_m_axi_rlast_reg, int_m_axi_rlast} >> r_grant_encoded;
        wire [RUSER_WIDTH-1:0] m_axi_ruser_mux  = {{RUSER_WIDTH{1'b0}}, int_m_axi_ruser} >> r_grant_encoded*RUSER_WIDTH;
        wire                   m_axi_rvalid_mux = ({decerr_m_axi_rvalid_reg, int_m_axi_rvalid} >> r_grant_encoded) & r_grant_valid;
        wire                   m_axi_rready_mux;

        assign int_axi_rready[m*M_COUNT +: M_COUNT] = (r_grant_valid && m_axi_rready_mux) << r_grant_encoded;
        assign decerr_m_axi_rready = (r_grant_valid && m_axi_rready_mux) && (r_grant_encoded == M_COUNT_P1-1);

        for (n = 0; n < M_COUNT; n = n + 1) begin
            assign r_request[n] = int_axi_rvalid[n*S_COUNT+m] && !r_grant[n];
            assign r_acknowledge[n] = r_grant[n] && int_axi_rvalid[n*S_COUNT+m] && m_axi_rlast_mux && m_axi_rready_mux;
        end

        assign r_request[M_COUNT_P1-1] = decerr_m_axi_rvalid_reg && !r_grant[M_COUNT_P1-1];
        assign r_acknowledge[M_COUNT_P1-1] = r_grant[M_COUNT_P1-1] && decerr_m_axi_rvalid_reg && decerr_m_axi_rlast_reg && m_axi_rready_mux;

        assign s_cpl_id = m_axi_rid_mux;
        assign s_cpl_valid = m_axi_rvalid_mux && m_axi_rready_mux && m_axi_rlast_mux;

        // S side register
        axi_register_rd #(
            .DATA_WIDTH(DATA_WIDTH),
            .ADDR_WIDTH(ADDR_WIDTH),
            .STRB_WIDTH(STRB_WIDTH),
            .ID_WIDTH(S_ID_WIDTH),
            .ARUSER_ENABLE(ARUSER_ENABLE),
            .ARUSER_WIDTH(ARUSER_WIDTH),
            .RUSER_ENABLE(RUSER_ENABLE),
            .RUSER_WIDTH(RUSER_WIDTH),
            .AR_REG_TYPE(S_AR_REG_TYPE[m*2 +: 2]),
            .R_REG_TYPE(S_R_REG_TYPE[m*2 +: 2])
        )
        reg_inst (
            .clk(clk),
            .rst(rst),
            .s_axi_arid(s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]),
            .s_axi_araddr(s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
            .s_axi_arlen(s_axi_arlen[m*8 +: 8]),
            .s_axi_arsize(s_axi_arsize[m*3 +: 3]),
            .s_axi_arburst(s_axi_arburst[m*2 +: 2]),
            .s_axi_arlock(s_axi_arlock[m]),
            .s_axi_arcache(s_axi_arcache[m*4 +: 4]),
            .s_axi_arprot(s_axi_arprot[m*3 +: 3]),
            .s_axi_arqos(s_axi_arqos[m*4 +: 4]),
            .s_axi_arregion(4'd0),
            .s_axi_aruser(s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]),
            .s_axi_arvalid(s_axi_arvalid[m]),
            .s_axi_arready(s_axi_arready[m]),
            .s_axi_rid(s_axi_rid[m*S_ID_WIDTH +: S_ID_WIDTH]),
            .s_axi_rdata(s_axi_rdata[m*DATA_WIDTH +: DATA_WIDTH]),
            .s_axi_rresp(s_axi_rresp[m*2 +: 2]),
            .s_axi_rlast(s_axi_rlast[m]),
            .s_axi_ruser(s_axi_ruser[m*RUSER_WIDTH +: RUSER_WIDTH]),
            .s_axi_rvalid(s_axi_rvalid[m]),
            .s_axi_rready(s_axi_rready[m]),
            .m_axi_arid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]),
            .m_axi_araddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
            .m_axi_arlen(int_s_axi_arlen[m*8 +: 8]),
            .m_axi_arsize(int_s_axi_arsize[m*3 +: 3]),
            .m_axi_arburst(int_s_axi_arburst[m*2 +: 2]),
            .m_axi_arlock(int_s_axi_arlock[m]),
            .m_axi_arcache(int_s_axi_arcache[m*4 +: 4]),
            .m_axi_arprot(int_s_axi_arprot[m*3 +: 3]),
            .m_axi_arqos(int_s_axi_arqos[m*4 +: 4]),
            .m_axi_arregion(),
            .m_axi_aruser(int_s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]),
            .m_axi_arvalid(int_s_axi_arvalid[m]),
            .m_axi_arready(int_s_axi_arready[m]),
            .m_axi_rid(m_axi_rid_mux),
            .m_axi_rdata(m_axi_rdata_mux),
            .m_axi_rresp(m_axi_rresp_mux),
            .m_axi_rlast(m_axi_rlast_mux),
            .m_axi_ruser(m_axi_ruser_mux),
            .m_axi_rvalid(m_axi_rvalid_mux),
            .m_axi_rready(m_axi_rready_mux)
        );
    end // s_ifaces

    for (n = 0; n < M_COUNT; n = n + 1) begin : m_ifaces
        // in-flight transaction count
        wire trans_start;
        wire trans_complete;
        reg [$clog2(M_ISSUE[n*32 +: 32]+1)-1:0] trans_count_reg = 0;

        wire trans_limit = trans_count_reg >= M_ISSUE[n*32 +: 32] && !trans_complete;

        always @(posedge clk) begin
            if (rst) begin
                trans_count_reg <= 0;
            end else begin
                if (trans_start && !trans_complete) begin
                    trans_count_reg <= trans_count_reg + 1;
                end else if (!trans_start && trans_complete) begin
                    trans_count_reg <= trans_count_reg - 1;
                end
            end
        end

        // address arbitration
        wire [S_COUNT-1:0] a_request;
        wire [S_COUNT-1:0] a_acknowledge;
        wire [S_COUNT-1:0] a_grant;
        wire a_grant_valid;
        wire [CL_S_COUNT-1:0] a_grant_encoded;

        arbiter #(
            .PORTS(S_COUNT),
            .ARB_TYPE_ROUND_ROBIN(1),
            .ARB_BLOCK(1),
            .ARB_BLOCK_ACK(1),
            .ARB_LSB_HIGH_PRIORITY(1)
        )
        a_arb_inst (
            .clk(clk),
            .rst(rst),
            .request(a_request),
            .acknowledge(a_acknowledge),
            .grant(a_grant),
            .grant_valid(a_grant_valid),
            .grant_encoded(a_grant_encoded)
        );

        // address mux
        wire [M_ID_WIDTH-1:0]   s_axi_arid_mux     = int_s_axi_arid[a_grant_encoded*S_ID_WIDTH +: S_ID_WIDTH] | (a_grant_encoded << S_ID_WIDTH);
        wire [ADDR_WIDTH-1:0]   s_axi_araddr_mux   = int_s_axi_araddr[a_grant_encoded*ADDR_WIDTH +: ADDR_WIDTH];
        wire [7:0]              s_axi_arlen_mux    = int_s_axi_arlen[a_grant_encoded*8 +: 8];
        wire [2:0]              s_axi_arsize_mux   = int_s_axi_arsize[a_grant_encoded*3 +: 3];
        wire [1:0]              s_axi_arburst_mux  = int_s_axi_arburst[a_grant_encoded*2 +: 2];
        wire                    s_axi_arlock_mux   = int_s_axi_arlock[a_grant_encoded];
        wire [3:0]              s_axi_arcache_mux  = int_s_axi_arcache[a_grant_encoded*4 +: 4];
        wire [2:0]              s_axi_arprot_mux   = int_s_axi_arprot[a_grant_encoded*3 +: 3];
        wire [3:0]              s_axi_arqos_mux    = int_s_axi_arqos[a_grant_encoded*4 +: 4];
        wire [3:0]              s_axi_arregion_mux = int_s_axi_arregion[a_grant_encoded*4 +: 4];
        wire [ARUSER_WIDTH-1:0] s_axi_aruser_mux   = int_s_axi_aruser[a_grant_encoded*ARUSER_WIDTH +: ARUSER_WIDTH];
        wire                    s_axi_arvalid_mux  = int_axi_arvalid[a_grant_encoded*M_COUNT+n] && a_grant_valid;
        wire                    s_axi_arready_mux;

        assign int_axi_arready[n*S_COUNT +: S_COUNT] = (a_grant_valid && s_axi_arready_mux) << a_grant_encoded;

        for (m = 0; m < S_COUNT; m = m + 1) begin
            assign a_request[m] = int_axi_arvalid[m*M_COUNT+n] && !a_grant[m] && !trans_limit;
            assign a_acknowledge[m] = a_grant[m] && int_axi_arvalid[m*M_COUNT+n] && s_axi_arready_mux;
        end

        assign trans_start = s_axi_arvalid_mux && s_axi_arready_mux && a_grant_valid;

        // read response forwarding
        wire [CL_S_COUNT-1:0] r_select = m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH] >> S_ID_WIDTH;

        assign int_axi_rvalid[n*S_COUNT +: S_COUNT] = int_m_axi_rvalid[n] << r_select;
        assign int_m_axi_rready[n] = int_axi_rready[r_select*M_COUNT+n];

        assign trans_complete = int_m_axi_rvalid[n] && int_m_axi_rready[n] && int_m_axi_rlast[n];

        // M side register
        axi_register_rd #(
            .DATA_WIDTH(DATA_WIDTH),
            .ADDR_WIDTH(ADDR_WIDTH),
            .STRB_WIDTH(STRB_WIDTH),
            .ID_WIDTH(M_ID_WIDTH),
            .ARUSER_ENABLE(ARUSER_ENABLE),
            .ARUSER_WIDTH(ARUSER_WIDTH),
            .RUSER_ENABLE(RUSER_ENABLE),
            .RUSER_WIDTH(RUSER_WIDTH),
            .AR_REG_TYPE(M_AR_REG_TYPE[n*2 +: 2]),
            .R_REG_TYPE(M_R_REG_TYPE[n*2 +: 2])
        )
        reg_inst (
            .clk(clk),
            .rst(rst),
            .s_axi_arid(s_axi_arid_mux),
            .s_axi_araddr(s_axi_araddr_mux),
            .s_axi_arlen(s_axi_arlen_mux),
            .s_axi_arsize(s_axi_arsize_mux),
            .s_axi_arburst(s_axi_arburst_mux),
            .s_axi_arlock(s_axi_arlock_mux),
            .s_axi_arcache(s_axi_arcache_mux),
            .s_axi_arprot(s_axi_arprot_mux),
            .s_axi_arqos(s_axi_arqos_mux),
            .s_axi_arregion(s_axi_arregion_mux),
            .s_axi_aruser(s_axi_aruser_mux),
            .s_axi_arvalid(s_axi_arvalid_mux),
            .s_axi_arready(s_axi_arready_mux),
            .s_axi_rid(int_m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]),
            .s_axi_rdata(int_m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]),
            .s_axi_rresp(int_m_axi_rresp[n*2 +: 2]),
            .s_axi_rlast(int_m_axi_rlast[n]),
            .s_axi_ruser(int_m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]),
            .s_axi_rvalid(int_m_axi_rvalid[n]),
            .s_axi_rready(int_m_axi_rready[n]),
            .m_axi_arid(m_axi_arid[n*M_ID_WIDTH +: M_ID_WIDTH]),
            .m_axi_araddr(m_axi_araddr[n*ADDR_WIDTH +: ADDR_WIDTH]),
            .m_axi_arlen(m_axi_arlen[n*8 +: 8]),
            .m_axi_arsize(m_axi_arsize[n*3 +: 3]),
            .m_axi_arburst(m_axi_arburst[n*2 +: 2]),
            .m_axi_arlock(m_axi_arlock[n]),
            .m_axi_arcache(m_axi_arcache[n*4 +: 4]),
            .m_axi_arprot(m_axi_arprot[n*3 +: 3]),
            .m_axi_arqos(m_axi_arqos[n*4 +: 4]),
            .m_axi_arregion(m_axi_arregion[n*4 +: 4]),
            .m_axi_aruser(m_axi_aruser[n*ARUSER_WIDTH +: ARUSER_WIDTH]),
            .m_axi_arvalid(m_axi_arvalid[n]),
            .m_axi_arready(m_axi_arready[n]),
            .m_axi_rid(m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]),
            .m_axi_rdata(m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]),
            .m_axi_rresp(m_axi_rresp[n*2 +: 2]),
            .m_axi_rlast(m_axi_rlast[n]),
            .m_axi_ruser(m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]),
            .m_axi_rvalid(m_axi_rvalid[n]),
            .m_axi_rready(m_axi_rready[n])
        );
    end // m_ifaces

endgenerate

endmodule


// megafunction wizard: %Altera PLL v17.1%
// GENERATION: XML
// pll.v

// Generated using ACDS version 17.1 593

`timescale 1 ps / 1 ps
module pll (
		input  wire        refclk,            //            refclk.clk
		input  wire        rst,               //             reset.reset
		output wire        outclk_0,          //           outclk0.clk
		output wire        outclk_1,          //           outclk1.clk
		output wire        locked,            //            locked.export
		input  wire [63:0] reconfig_to_pll,   //   reconfig_to_pll.reconfig_to_pll
		output wire [63:0] reconfig_from_pll  // reconfig_from_pll.reconfig_from_pll
	);

		.outclk_0          (outclk_0),          //           outclk0.clk
		.outclk_1          (outclk_1),          //           outclk1.clk
		.locked            (locked),            //            locked.export
		.reconfig_to_pll   (reconfig_to_pll),   //   reconfig_to_pll.reconfig_to_pll
		.reconfig_from_pll (reconfig_from_pll)  // reconfig_from_pll.reconfig_from_pll
	);

endmodule
// Retrieval info: <?xml version="1.0"?>
//<!--
//	Generated by Altera MegaWizard Launcher Utility version 1.0
//	************************************************************
//	THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//	************************************************************
//	Copyright (C) 1991-2022 Altera Corporation
//	Any megafunction design, and related net list (encrypted or decrypted),
//	support information, device programming or simulation file, and any other
//	associated documentation or information provided by Altera or a partner
//	under Altera's Megafunction Partnership Program may be used only to
//	program PLD devices (but not masked PLD devices) from Altera.  Any other
//	use of such megafunction design, net list, support information, device
//	programming or simulation file, or any other related documentation or
//	information is prohibited for any other purpose, including, but not
//	limited to modification, reverse engineering, de-compiling, or use with
//	any other silicon devices, unless such use is explicitly licensed under
//	a separate agreement with Altera or a megafunction partner.  Title to
//	the intellectual property, including patents, copyrights, trademarks,
//	trade secrets, or maskworks, embodied in any such megafunction design,
//	net list, support information, device programming or simulation file, or
//	any other related documentation or information provided by Altera or a
//	megafunction partner, remains with Altera, the megafunction partner, or
//	their respective licensors.  No other licenses, including any licenses
//	needed under any third party's intellectual property, are provided herein.
//-->
// Retrieval info: <instance entity-name="altera_pll" version="17.1" >
// Retrieval info: 	<generic name="debug_print_output" value="false" />
// Retrieval info: 	<generic name="debug_use_rbc_taf_method" value="false" />
// Retrieval info: 	<generic name="device_family" value="Cyclone V" />
// Retrieval info: 	<generic name="device" value="5CEBA2F17A7" />
// Retrieval info: 	<generic name="gui_device_speed_grade" value="2" />
// Retrieval info: 	<generic name="gui_pll_mode" value="Fractional-N PLL" />
// Retrieval info: 	<generic name="gui_reference_clock_frequency" value="50.0" />
// Retrieval info: 	<generic name="gui_channel_spacing" value="0.0" />
// Retrieval info: 	<generic name="gui_operation_mode" value="direct" />
// Retrieval info: 	<generic name="gui_feedback_clock" value="Global Clock" />
// Retrieval info: 	<generic name="gui_fractional_cout" value="32" />
// Retrieval info: 	<generic name="gui_dsm_out_sel" value="1st_order" />
// Retrieval info: 	<generic name="gui_use_locked" value="true" />
// Retrieval info: 	<generic name="gui_en_adv_params" value="false" />
// Retrieval info: 	<generic name="gui_number_of_clocks" value="2" />
// Retrieval info: 	<generic name="gui_multiply_factor" value="1" />
// Retrieval info: 	<generic name="gui_frac_multiply_factor" value="1" />
// Retrieval info: 	<generic name="gui_divide_factor_n" value="1" />
// Retrieval info: 	<generic name="gui_cascade_counter0" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency0" value="53.6852" />
// Retrieval info: 	<generic name="gui_divide_factor_c0" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency0" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units0" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift0" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg0" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift0" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle0" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter1" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency1" value="107.3704" />
// Retrieval info: 	<generic name="gui_divide_factor_c1" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency1" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units1" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift1" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg1" value="-60.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift1" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle1" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter2" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency2" value="54.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c2" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency2" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units2" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift2" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg2" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift2" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle2" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter3" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency3" value="10.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c3" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency3" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units3" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift3" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg3" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift3" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle3" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter4" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency4" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c4" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency4" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units4" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift4" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg4" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift4" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle4" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter5" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency5" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c5" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency5" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units5" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift5" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg5" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift5" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle5" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter6" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency6" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c6" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency6" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units6" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift6" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg6" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift6" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle6" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter7" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency7" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c7" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency7" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units7" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift7" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg7" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift7" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle7" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter8" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency8" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c8" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency8" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units8" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift8" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg8" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift8" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle8" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter9" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency9" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c9" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency9" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units9" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift9" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg9" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift9" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle9" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter10" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency10" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c10" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency10" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units10" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift10" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg10" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift10" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle10" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter11" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency11" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c11" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency11" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units11" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift11" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg11" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift11" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle11" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter12" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency12" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c12" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency12" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units12" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift12" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg12" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift12" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle12" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter13" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency13" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c13" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency13" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units13" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift13" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg13" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift13" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle13" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter14" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency14" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c14" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency14" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units14" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift14" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg14" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift14" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle14" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter15" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency15" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c15" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency15" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units15" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift15" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg15" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift15" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle15" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter16" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency16" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c16" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency16" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units16" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift16" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg16" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift16" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle16" value="50" />
// Retrieval info: 	<generic name="gui_cascade_counter17" value="false" />
// Retrieval info: 	<generic name="gui_output_clock_frequency17" value="100.0" />
// Retrieval info: 	<generic name="gui_divide_factor_c17" value="1" />
// Retrieval info: 	<generic name="gui_actual_output_clock_frequency17" value="0 MHz" />
// Retrieval info: 	<generic name="gui_ps_units17" value="ps" />
// Retrieval info: 	<generic name="gui_phase_shift17" value="0" />
// Retrieval info: 	<generic name="gui_phase_shift_deg17" value="0.0" />
// Retrieval info: 	<generic name="gui_actual_phase_shift17" value="0" />
// Retrieval info: 	<generic name="gui_duty_cycle17" value="50" />
// Retrieval info: 	<generic name="gui_pll_auto_reset" value="On" />
// Retrieval info: 	<generic name="gui_pll_bandwidth_preset" value="Auto" />
// Retrieval info: 	<generic name="gui_en_reconf" value="true" />
// Retrieval info: 	<generic name="gui_en_dps_ports" value="false" />
// Retrieval info: 	<generic name="gui_en_phout_ports" value="false" />
// Retrieval info: 	<generic name="gui_phout_division" value="1" />
// Retrieval info: 	<generic name="gui_mif_generate" value="false" />
// Retrieval info: 	<generic name="gui_enable_mif_dps" value="false" />
// Retrieval info: 	<generic name="gui_dps_cntr" value="C0" />
// Retrieval info: 	<generic name="gui_dps_num" value="1" />
// Retrieval info: 	<generic name="gui_dps_dir" value="Positive" />
// Retrieval info: 	<generic name="gui_refclk_switch" value="false" />
// Retrieval info: 	<generic name="gui_refclk1_frequency" value="100.0" />
// Retrieval info: 	<generic name="gui_switchover_mode" value="Automatic Switchover" />
// Retrieval info: 	<generic name="gui_switchover_delay" value="0" />
// Retrieval info: 	<generic name="gui_active_clk" value="false" />
// Retrieval info: 	<generic name="gui_clk_bad" value="false" />
// Retrieval info: 	<generic name="gui_enable_cascade_out" value="false" />
// Retrieval info: 	<generic name="gui_cascade_outclk_index" value="0" />
// Retrieval info: 	<generic name="gui_enable_cascade_in" value="false" />
// Retrieval info: 	<generic name="gui_pll_cascading_mode" value="Create an adjpllin signal to connect with an upstream PLL" />
// Retrieval info: </instance>
// IPFS_FILES : pll.vo
// RELATED_FILES: pll.v, pll_0002.v

	pll_0002 pll_inst (
		.refclk            (refclk),            //            refclk.clk


    input rst_sync,
    output logic wb_clk_o,
    output logic wb_rst_o
);

  assign wb_clk_o = clk;

  always_ff @(posedge clk) begin
    wb_rst_o <= rst_sync;
  end

endmodule


//********************************************************************************
// SPDX-License-Identifier: Apache-2.0
// Copyright 2019 Western Digital Corporation or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//********************************************************************************
//********************************************************************************
// Function: Top level file for Icache, Fetch, Branch prediction & Aligner
// BFF -> F1 -> F2 -> A
//********************************************************************************

module ifu
   import swerv_types::*;
(
   input logic free_clk,
   input logic active_clk,
   input logic clk,
   input logic clk_override,
   input logic rst_l,

   input logic dec_ib3_valid_d, dec_ib2_valid_d, // mass balance for decode buffer

   input logic dec_ib0_valid_eff_d,   // effective valid taking decode into account
   input logic dec_ib1_valid_eff_d,   // effective valid taking decode into account

   input logic        exu_i0_br_ret_e4, // i0 branch commit is a ret
   input logic        exu_i1_br_ret_e4, // i1 branch commit is a ret
   input logic        exu_i0_br_call_e4, // i0 branch commit is a call
   input logic        exu_i1_br_call_e4, // i1 branch commit is a call

   input logic exu_flush_final, // flush, includes upper and lower
   input logic dec_tlu_flush_err_wb , // flush due to parity error.
   input logic dec_tlu_flush_noredir_wb, // don't fetch, validated with exu_flush_final
   input logic dec_tlu_dbg_halted, // halted, used for leaving IDLE state
   input logic dec_tlu_pmu_fw_halted, // Core is halted
   input logic [31:1] exu_flush_path_final, // flush fetch address
   input logic        exu_flush_upper_e2,    // flush upper, either i0 or i1

   input logic [31:0]  dec_tlu_mrac_ff ,// Side_effect , cacheable for each region
   input logic         dec_tlu_fence_i_wb, // fence.i, invalidate icache, validated with exu_flush_final
   input logic         dec_tlu_flush_leak_one_wb, // ignore bp for leak one fetches

   input logic                       dec_tlu_bpred_disable, // disable all branch prediction
   input logic                       dec_tlu_core_ecc_disable,  // disable ecc checking and flagging

   // AXI Write Channels - IFU never writes. So, 0 out mostly
   output logic                           ifu_axi_awvalid,
   input  logic                           ifu_axi_awready,
   output logic [`RV_IFU_BUS_TAG-1:0]     ifu_axi_awid,
   output logic [31:0]                    ifu_axi_awaddr,
   output logic [3:0]                     ifu_axi_awregion,
   output logic [7:0]                     ifu_axi_awlen,
   output logic [2:0]                     ifu_axi_awsize,
   output logic [1:0]                     ifu_axi_awburst,
   output logic                           ifu_axi_awlock,
   output logic [3:0]                     ifu_axi_awcache,
   output logic [2:0]                     ifu_axi_awprot,
   output logic [3:0]                     ifu_axi_awqos,

   output logic                           ifu_axi_wvalid,
   input  logic                           ifu_axi_wready,
   output logic [63:0]                    ifu_axi_wdata,
   output logic [7:0]                     ifu_axi_wstrb,
   output logic                           ifu_axi_wlast,

   input  logic                           ifu_axi_bvalid,
   output logic                           ifu_axi_bready,
   input  logic [1:0]                     ifu_axi_bresp,
   input  logic [`RV_IFU_BUS_TAG-1:0]     ifu_axi_bid,

   // AXI Read Channels
   output logic                           ifu_axi_arvalid,
   input  logic                           ifu_axi_arready,
   output logic [`RV_IFU_BUS_TAG-1:0]     ifu_axi_arid,
   output logic [31:0]                    ifu_axi_araddr,
   output logic [3:0]                     ifu_axi_arregion,
   output logic [7:0]                     ifu_axi_arlen,
   output logic [2:0]                     ifu_axi_arsize,
   output logic [1:0]                     ifu_axi_arburst,
   output logic                           ifu_axi_arlock,
   output logic [3:0]                     ifu_axi_arcache,
   output logic [2:0]                     ifu_axi_arprot,
   output logic [3:0]                     ifu_axi_arqos,

   input  logic                           ifu_axi_rvalid,
   output logic                           ifu_axi_rready,
   input  logic [`RV_IFU_BUS_TAG-1:0]     ifu_axi_rid,
   input  logic [63:0]                    ifu_axi_rdata,
   input  logic [1:0]                     ifu_axi_rresp,
   input  logic                           ifu_axi_rlast,

 //// AHB LITE BUS
//`ifdef RV_BUILD_AHB_LITE
   input  logic                      ifu_bus_clk_en,

   input  logic                      dma_iccm_req,
   input  logic                      dma_iccm_stall_any,
   input  logic [31:0]               dma_mem_addr,
   input  logic [2:0]                dma_mem_sz,
   input  logic                      dma_mem_write,
   input  logic [63:0]               dma_mem_wdata,

   output logic                      iccm_dma_ecc_error,
   output logic                      iccm_dma_rvalid,
   output logic [63:0]               iccm_dma_rdata,
   output logic                      iccm_ready,

//`endif

   output logic [1:0] ifu_pmu_instr_aligned,
   output logic       ifu_pmu_align_stall,
   output logic       ifu_pmu_fetch_stall,

//   I$ & ITAG Ports
   output logic [31:3]               ic_rw_addr,         // Read/Write addresss to the Icache.
   output logic [3:0]                ic_wr_en,           // Icache write enable, when filling the Icache.
   output logic                      ic_rd_en,           // Icache read  enable.
`ifdef RV_ICACHE_ECC
   output logic [83:0]               ic_wr_data,         // Data to fill to the Icache. With ECC
   input  logic [167:0]              ic_rd_data ,        // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC
   input  logic [24:0]               ictag_debug_rd_data,// Debug icache tag.
   output logic [41:0]               ic_debug_wr_data,   // Debug wr cache.
   output logic [41:0]               ifu_ic_debug_rd_data,
`else
   output logic [67:0]               ic_wr_data,         // Data to fill to the Icache. With Parity
   input  logic [135:0]              ic_rd_data ,        // Data read from Icache. 2x64bits + parity bits. F2 stage. With Parity
   input  logic [20:0]               ictag_debug_rd_data,// Debug icache tag.
   output logic [33:0]               ic_debug_wr_data,   // Debug wr cache.
   output logic [33:0]               ifu_ic_debug_rd_data,
`endif

   output logic [127:0]              ic_premux_data,     // Premux data to be muxed with each way of the Icache.
   output logic                      ic_sel_premux_data, // Select the premux data.

   output logic [15:2]               ic_debug_addr,      // Read/Write addresss to the Icache.
   output logic                      ic_debug_rd_en,     // Icache debug rd
   output logic                      ic_debug_wr_en,     // Icache debug wr
   output logic                      ic_debug_tag_array, // Debug tag array
   output logic [3:0]                ic_debug_way,       // Debug way. Rd or Wr.

   output logic [3:0]                ic_tag_valid,       // Valid bits when accessing the Icache. One valid bit per way. F2 stage

   input  logic [3:0]                ic_rd_hit,          // Compare hits from Icache tags. Per way.  F2 stage
   input  logic                      ic_tag_perr,        // Icache Tag parity error

`ifdef RV_ICCM_ENABLE
   // ICCM ports
   output logic [`RV_ICCM_BITS-1:2]               iccm_rw_addr,       // ICCM read/write address.
   output logic                      iccm_wren,          // ICCM write enable (through the DMA)
   output logic                      iccm_rden,          // ICCM read enable.
   output logic [77:0]               iccm_wr_data,       // ICCM write data.
   output logic [2:0]                iccm_wr_size,       // ICCM write location within DW.

   input  logic [155:0]              iccm_rd_data,       // Data read from ICCM.
`endif

// Perf counter sigs
   output logic       ifu_pmu_ic_miss, // ic miss
   output logic       ifu_pmu_ic_hit, // ic hit
   output logic       ifu_pmu_bus_error, // iside bus error
   output logic       ifu_pmu_bus_busy,  // iside bus busy
   output logic       ifu_pmu_bus_trxn, // iside bus transactions

   output logic	 ifu_i0_valid,        // Instruction 0 valid. From Aligner to Decode
   output logic	 ifu_i1_valid,        // Instruction 1 valid. From Aligner to Decode
   output logic	 ifu_i0_icaf,         // Instruction 0 access fault. From Aligner to Decode
   output logic	 ifu_i1_icaf,         // Instruction 1 access fault. From Aligner to Decode
   output logic  ifu_i0_icaf_f1,      // Instruction 0 has access fault on second fetch group
   output logic  ifu_i1_icaf_f1,      // Instruction 1 has access fault on second fetch group
   output logic	 ifu_i0_perr,         // Instruction 0 parity error. From Aligner to Decode
   output logic	 ifu_i1_perr,         // Instruction 1 parity error. From Aligner to Decode
   output logic	 ifu_i0_sbecc,        // Instruction 0 has single bit ecc error
   output logic	 ifu_i1_sbecc,        // Instruction 1 has single bit ecc error
   output logic	 ifu_i0_dbecc,        // Instruction 0 has double bit ecc error
   output logic	 ifu_i1_dbecc,        // Instruction 1 has double bit ecc error
   output logic  iccm_dma_sb_error,   // Single Bit ECC error from a DMA access
   output logic[31:0] ifu_i0_instr,   // Instruction 0 . From Aligner to Decode
   output logic[31:0] ifu_i1_instr,   // Instruction 1 . From Aligner to Decode
   output logic[31:1] ifu_i0_pc,      // Instruction 0 pc. From Aligner to Decode
   output logic[31:1] ifu_i1_pc,      // Instruction 1 pc. From Aligner to Decode
   output logic ifu_i0_pc4,           // Instruction 0 is 4 byte. From Aligner to Decode
   output logic ifu_i1_pc4,           // Instruction 1 is 4 byte. From Aligner to Decode
   output logic [15:0] ifu_illegal_inst, // Illegal instruction.

   output logic ifu_miss_state_idle,   // There is no outstanding miss. Cache miss state is idle.

   output br_pkt_t i0_brp,           // Instruction 0 branch packet. From Aligner to Decode
   output br_pkt_t i1_brp,           // Instruction 1 branch packet. From Aligner to Decode

   input predict_pkt_t  exu_mp_pkt, // mispredict packet
   input logic [`RV_BHT_GHR_RANGE] exu_mp_eghr, // execute ghr

   input br_tlu_pkt_t dec_tlu_br0_wb_pkt, // slot0 update/error pkt
   input br_tlu_pkt_t dec_tlu_br1_wb_pkt, // slot1 update/error pkt
   input dec_tlu_flush_lower_wb,

   input rets_pkt_t exu_rets_e1_pkt, // E1 return stack packet
   input rets_pkt_t exu_rets_e4_pkt, // E4 return stack packet

   // pc's  used to maintain and update the BP RET stacks
`ifdef REAL_COMM_RS
   input logic [31:1] exu_i0_pc_e1,
   input logic [31:1] exu_i1_pc_e1,
   input logic [31:1] dec_tlu_i0_pc_e4,
   input logic [31:1] dec_tlu_i1_pc_e4,
`endif

   output logic [15:0] ifu_i0_cinst,
   output logic [15:0] ifu_i1_cinst,

/// Icache debug
   input  cache_debug_pkt_t        dec_tlu_ic_diag_pkt ,
   output logic                    ifu_ic_debug_rd_data_valid,

   input logic scan_mode
   );

   localparam TAGWIDTH = 2 ;
   localparam IDWIDTH  = 2 ;

   logic 		   ifu_fb_consume1, ifu_fb_consume2;
   logic [31:1] 	   ifc_fetch_addr_f2;
   logic                   ifc_fetch_uncacheable_f1;

   logic [7:0] 	 ifu_fetch_val;  // valids on a 2B boundary, left justified [7] implies valid fetch
   logic [31:1]  ifu_fetch_pc;   // starting pc of fetch

   logic [31:1] ifc_fetch_addr_f1;

   logic 	ic_crit_wd_rdy;
   logic 	ic_write_stall;
   logic        ic_dma_active;
   logic        ifc_dma_access_ok;
   logic        ifc_iccm_access_f1;
   logic        ifc_region_acc_fault_f1;
   logic        ic_access_fault_f2;
   logic        ifu_ic_mb_empty;

   logic ic_hit_f2;

   // fetch control
   ifu_ifc_ctl ifc (.*
		    );

`ifdef RV_BTB_48
   logic [7:0][1:0] ifu_bp_way_f2; // way indication; right justified
`else
   logic [7:0] 	ifu_bp_way_f2; // way indication; right justified
`endif
   logic  ifu_bp_kill_next_f2; // kill next fetch; taken target found
   logic [31:1] ifu_bp_btb_target_f2; //  predicted target PC
   logic [7:1] 	ifu_bp_inst_mask_f2; // tell ic which valids to kill because of a taken branch; right justified
   logic [7:0] 	ifu_bp_hist1_f2; // history counters for all 4 potential branches; right justified
   logic [7:0] 	ifu_bp_hist0_f2; // history counters for all 4 potential branches; right justified
   logic [11:0] ifu_bp_poffset_f2; // predicted target
   logic [7:0] 	ifu_bp_ret_f2; // predicted ret ; right justified
   logic [7:0] 	ifu_bp_pc4_f2; // pc4 indication; right justified
   logic [7:0] 	ifu_bp_valid_f2; // branch valid, right justified
   logic [`RV_BHT_GHR_RANGE] ifu_bp_fghr_f2;

   // branch predictor
   ifu_bp_ctl bp (.*);

   logic [7:0]   ic_fetch_val_f2;
   logic [127:0] ic_data_f2;
   logic [127:0] ifu_fetch_data;
   logic ifc_fetch_req_f1_raw, ifc_fetch_req_f1, ifc_fetch_req_f2;
   logic ic_rd_parity_final_err;  // This fetch has a  data_cache or tag  parity error.
   logic iccm_rd_ecc_single_err;  // This fetch has an iccm single error.
   logic iccm_rd_ecc_double_err;  // This fetch has an iccm double error.

   icache_err_pkt_t ic_error_f2;

   logic         ifu_icache_fetch_f2 ;
   logic [16:2]  ifu_icache_error_index;       //  Index with parity error
   logic         ifu_icache_error_val;   //  Parity error
   logic         ifu_icache_sb_error_val;

   assign ifu_fetch_data[127:0] = ic_data_f2[127:0];
   assign ifu_fetch_val[7:0] = ic_fetch_val_f2[7:0];
   assign ifu_fetch_pc[31:1] = ifc_fetch_addr_f2[31:1];

   // aligner
   ifu_aln_ctl aln (.*);

   // icache
   ifu_mem_ctl mem_ctl
     (.*,
      .fetch_addr_f1(ifc_fetch_addr_f1),
      .ifu_icache_error_index(ifu_icache_error_index[16:6]),
      .ic_hit_f2(ic_hit_f2),
      .ic_data_f2(ic_data_f2[127:0])
      );

   // Performance debug info
   //
   //
`ifdef DUMP_BTB_ON
   logic 	      exu_mp_valid; // conditional branch mispredict
   logic exu_mp_way; // conditional branch mispredict
   logic exu_mp_ataken; // direction is actual taken
   logic exu_mp_boffset; // branch offsett
   logic exu_mp_pc4; // branch is a 4B inst
   logic exu_mp_call; // branch is a call inst
   logic exu_mp_ret; // branch is a ret inst
   logic exu_mp_ja; // branch is a jump always
   logic [1:0] exu_mp_hist; // new history
   logic [11:0] exu_mp_tgt; // target offset
   logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] exu_mp_addr; // BTB/BHT address
   logic [1:0] 				exu_mp_bank; // write bank; based on branch PC[3:2]
   logic [`RV_BTB_BTAG_SIZE-1:0] exu_mp_btag; // branch tag
   logic [`RV_BHT_GHR_RANGE] exu_mp_fghr; // original fetch ghr (for correcting dir)

   assign exu_mp_valid = exu_mp_pkt.misp; // conditional branch mispredict
   assign exu_mp_ataken = exu_mp_pkt.ataken;  // direction is actual taken
   assign exu_mp_boffset = exu_mp_pkt.boffset;  // branch offset
   assign exu_mp_pc4 = exu_mp_pkt.pc4;  // branch is a 4B inst
   assign exu_mp_call = exu_mp_pkt.pcall;  // branch is a call inst
   assign exu_mp_ret = exu_mp_pkt.pret;  // branch is a ret inst
   assign exu_mp_ja = exu_mp_pkt.pja;  // branch is a jump always
   assign exu_mp_way = exu_mp_pkt.way;  // branch is a jump always
   assign exu_mp_hist[1:0] = exu_mp_pkt.hist[1:0];  // new history
   assign exu_mp_tgt[11:0]  = exu_mp_pkt.toffset[11:0] ;  // target offset
   assign exu_mp_addr[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO]  = exu_mp_pkt.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] ;  // BTB/BHT address
   assign exu_mp_bank[1:0]  = exu_mp_pkt.bank[1:0] ;  // write bank = exu_mp_pkt.;  based on branch PC[3:2]
   assign exu_mp_btag = exu_mp_pkt.btag[`RV_BTB_BTAG_SIZE-1:0] ;  // branch tag
   assign exu_mp_fghr[`RV_BHT_GHR_RANGE]  = exu_mp_pkt.fghr[`RV_BHT_GHR_RANGE] ;  // original fetch ghr (for correcting dir)

   logic [`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO] btb_rd_addr_f2;
 `define DEC `CPU_TOP.dec
 `define EXU `CPU_TOP.exu
   rvbtb_addr_hash f2hash(.pc(ifc_fetch_addr_f2[31:1]), .hash(btb_rd_addr_f2[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO]));
   logic [31:0] mppc_ns, mppc;
   assign mppc_ns[31:1] = `EXU.exu_i0_flush_upper_e1 ? `DEC.decode.i0_pc_e1[31:1] : (`EXU.exu_i1_flush_upper_e1 ? `DEC.decode.i1_pc_e1[31:1] : (`EXU.exu_i0_flush_lower_e4 ?  `DEC.decode.i0_pc_e4[31:1] :  `DEC.decode.i1_pc_e4[31:1]));
   assign mppc_ns[0] = 1'b0;
   logic [3:0] ic_rd_hit_f2;
   rvdff #(36)  mdseal_ff (.*, .din({mppc_ns[31:0], mem_ctl.ic_rd_hit[3:0]}), .dout({mppc[31:0],ic_rd_hit_f2[3:0]}));
logic [2:0] tmp_bnk;
assign tmp_bnk[2:0] = encode8_3(bp.btb_sel_f2[7:0]);
   always @(negedge clk) begin
      if(`DEC.tlu.mcyclel[31:0] == 32'h0000_0010) begin
	 $display("BTB_CONFIG: %d",`RV_BTB_ARRAY_DEPTH*4);
	 `ifndef BP_NOGSHARE
	 $display("BHT_CONFIG: %d gshare: 1",`RV_BHT_ARRAY_DEPTH*4);
	 `else
	 $display("BHT_CONFIG: %d gshare: 0",`RV_BHT_ARRAY_DEPTH*4);
	 `endif
	 $display("RS_CONFIG: %d", `RV_RET_STACK_SIZE);
      end
       if(exu_flush_final & ~(dec_tlu_br0_wb_pkt.br_error | dec_tlu_br0_wb_pkt.br_start_error | dec_tlu_br1_wb_pkt.br_error | dec_tlu_br1_wb_pkt.br_start_error) & (exu_mp_pkt.misp | exu_mp_pkt.ataken))
	 $display("%7d BTB_MP  : index: %0h bank: %0h call: %b ret: %b ataken: %b hist: %h valid: %b tag: %h targ: %h eghr: %b pred: %b ghr_index: %h brpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha, exu_mp_addr[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO], exu_mp_bank[1:0], exu_mp_call, exu_mp_ret, exu_mp_ataken, exu_mp_hist[1:0], exu_mp_valid, exu_mp_pkt.btag[`RV_BTB_BTAG_SIZE-1:0], {exu_flush_path_final[31:1], 1'b0}, exu_mp_eghr[`RV_BHT_GHR_RANGE], exu_mp_valid, bp.bht_wr_addr0, mppc[31:0], exu_mp_pkt.way);
     for(int i = 0; i < 8; i++) begin
      if(ifu_bp_valid_f2[i] & ifc_fetch_req_f2)
	$display("%7d BTB_HIT : index: %0h bank: %0h call: %b ret: %b taken: %b strength: %b tag: %h targ: %h ghr: %4b ghr_index: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,btb_rd_addr_f2[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO],encode8_3(bp.btb_sel_f2[7:0]), bp.btb_rd_call_f2, bp.btb_rd_ret_f2, ifu_bp_hist1_f2[tmp_bnk], ifu_bp_hist0_f2[tmp_bnk], bp.fetch_rd_tag_f2[`RV_BTB_BTAG_SIZE-1:0], {ifu_bp_btb_target_f2[31:1], 1'b0}, bp.fghr[`RV_BHT_GHR_RANGE], bp.bht_rd_addr_f1, ifu_bp_way_f2[tmp_bnk]);
     end
`ifdef RV_BTB_48
      for(int y = 0; y < 4; y++) begin
	 for(int z = 0; z < 4; z++) begin
	    if(bp.lru_bank_sel[y][z])
	      $display("%7d BTB_LRU: index: %0h bank: %0h newlru %h", `DEC.tlu.mcyclel[31:0]+32'ha, z,y,bp.lru_bank_wr_data[y][z]);
	 end
      end
`endif
      if(dec_tlu_br0_wb_pkt.valid & ~(dec_tlu_br0_wb_pkt.br_error | dec_tlu_br0_wb_pkt.br_start_error))
	$display("%7d BTB_UPD0: ghr_index: %0h bank: %0h hist: %h  way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,bp.br0_hashed_wb[`RV_BHT_ADDR_HI:`RV_BHT_ADDR_LO],{dec_tlu_br0_wb_pkt.bank[1:0],dec_tlu_br0_wb_pkt.middle}, dec_tlu_br0_wb_pkt.hist, dec_tlu_br0_wb_pkt.way);
      if(dec_tlu_br1_wb_pkt.valid & ~(dec_tlu_br1_wb_pkt.br_error | dec_tlu_br1_wb_pkt.br_start_error))
	$display("%7d BTB_UPD1: ghr_index: %0h bank: %0h hist: %h  way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,bp.br1_hashed_wb[`RV_BHT_ADDR_HI:`RV_BHT_ADDR_LO],{dec_tlu_br1_wb_pkt.bank[1:0],dec_tlu_br1_wb_pkt.middle}, dec_tlu_br1_wb_pkt.hist, dec_tlu_br1_wb_pkt.way);
      if(dec_tlu_br0_wb_pkt.br_error | dec_tlu_br0_wb_pkt.br_start_error)
	$display("%7d BTB_ERR0: index: %0h bank: %0h start: %b rfpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,dec_tlu_br0_wb_pkt.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO],dec_tlu_br0_wb_pkt.bank[1:0], dec_tlu_br0_wb_pkt.br_start_error, {exu_flush_path_final[31:1], 1'b0}, dec_tlu_br0_wb_pkt.way);
      if(dec_tlu_br1_wb_pkt.br_error | dec_tlu_br1_wb_pkt.br_start_error)
	$display("%7d BTB_ERR1: index: %0h bank: %0h start: %b rfpc: %h way: %h", `DEC.tlu.mcyclel[31:0]+32'ha,dec_tlu_br1_wb_pkt.index[`RV_BTB_ADDR_HI:`RV_BTB_ADDR_LO],dec_tlu_br1_wb_pkt.bank[1:0], dec_tlu_br1_wb_pkt.br_start_error, {exu_flush_path_final[31:1], 1'b0}, dec_tlu_br1_wb_pkt.way);
   end // always @ (negedge clk)
      function [2:0] encode8_3;
      input [7:0] in;

      encode8_3[2] = |in[7:4];

      encode8_3[0] = in[7] | in[5] | in[3] | in[1];

   endfunction
`endif
endmodule // ifu


`ifndef __TINY_SYNTH_TONE_GENERATOR_AGGREGATE_FIXED_PARAM__
`define __TINY_SYNTH_TONE_GENERATOR_AGGREGATE_FIXED_PARAM__

`include "../../hdl/tone_generator_saw.vh"
`include "../../hdl/tone_generator_pulse.vh"
`include "../../hdl/tone_generator_triangle.vh"
`include "../../hdl/tone_generator_noise.vh"

/* =========================================================
 * Phase-accumulator tone-generator (with fixed parameters)
 * =========================================================
 *
 * This is a version of tone_generator with fixed (immutable)
 * parameters - this is so it can synthesise down to a simpler
 * implementation.
 *
 * This module aggregates the other tone generators together.
 *
 * It houses the accumulator and the logic for incrementing it
 * at a given frequency.
 *
 * It allows individual tone generators to be selected and logically
 * "ANDed" into the output stream.
 *
 * It also has provision for syncing oscillators together based on
 * when they overflow, and proving the accumulator MSB for ring
 * modulation purposes.
 */
module tone_generator_fixed_param #(
  parameter FREQ_BITS = 16,
  parameter PULSEWIDTH_BITS = 12,
  parameter OUTPUT_BITS = 12,
  parameter ACCUMULATOR_BITS = 24,
  parameter WAVEFORM = 1
) (
  input [FREQ_BITS-1:0] tone_freq,
  input [PULSEWIDTH_BITS-1:0] pulse_width,
  input main_clk,
  input sample_clk,
  input rst,
  output reg signed [OUTPUT_BITS-1:0] dout,
  output wire accumulator_msb,
  output wire accumulator_overflow,

  input wire en_ringmod,
  input wire ringmod_source,

  input wire en_sync,
  input wire sync_source
);

  reg [ACCUMULATOR_BITS:0] accumulator;

  generate
    if (WAVEFORM == 1)
      tone_generator_triangle #(
          .ACCUMULATOR_BITS(ACCUMULATOR_BITS),
          .OUTPUT_BITS(OUTPUT_BITS)
      ) triangle_generator (
          .accumulator(accumulator[ACCUMULATOR_BITS-1:0]),
          .dout(wave_out),
          .en_ringmod(en_ringmod),
          .ringmod_source(ringmod_source)
        );
    if (WAVEFORM == 2)
      tone_generator_saw  #(
          .ACCUMULATOR_BITS(ACCUMULATOR_BITS),
          .OUTPUT_BITS(OUTPUT_BITS)
        ) saw(
          .accumulator(accumulator[ACCUMULATOR_BITS-1:0]),
          .dout(wave_out)
        );
    if (WAVEFORM == 3)
      tone_generator_pulse  #(
          .ACCUMULATOR_BITS(ACCUMULATOR_BITS),
          .OUTPUT_BITS(OUTPUT_BITS),
          .PULSEWIDTH_BITS(PULSEWIDTH_BITS)
        ) pulse(
          .accumulator(accumulator[ACCUMULATOR_BITS-1:0]),
          .dout(wave_out),
          .pulse_width(pulse_width)
        );
    if (WAVEFORM == 4)
      tone_generator_noise #(
        .OUTPUT_BITS(OUTPUT_BITS)
      ) noise(.clk(accumulator[18]), .rst(rst), .dout(wave_out));
  endgenerate

  always @(posedge main_clk) begin
    if (en_sync && sync_source)
      begin
        accumulator <= 0;
      end
    else
      begin
        accumulator <= accumulator[ACCUMULATOR_BITS-1:0] + tone_freq;
      end
  end

  assign accumulator_overflow = (accumulator[ACCUMULATOR_BITS]);  /* used for syncing to other oscillators */
  assign accumulator_msb = accumulator[ACCUMULATOR_BITS-1];

  always @(posedge sample_clk) begin
    dout <= wave_out ^ (2**(OUTPUT_BITS-1));
  end

endmodule

`endif


// Copyright 2014 Brian Swetland <swetland@frotz.net>
//
// 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.

`timescale 1ns/1ps

// write:
//   slave samples wr, waddr, wdata on posedge clk
//   if wr==1, wdata written to waddr
// read:
//   slave samples rd, raddr on posedge clk
//   if rd==1, read is requested
//   master samples rdata on next posedge clk

interface reg_ifc;

parameter AWIDTH = 2;
parameter DWIDTH = 32;

logic [AWIDTH-1:0]raddr;
logic [AWIDTH-1:0]waddr;
logic rd;
logic wr;
logic [DWIDTH-1:0]rdata;
logic [DWIDTH-1:0]wdata;

modport master (

	input rdata
	);

modport slave (
	input raddr, waddr, rd, wr, wdata,
	output rdata
	);

endinterface


// Copyright 2015, Brian Swetland <swetland@frotz.net>
// Licensed under the Apache License, Version 2.0.

`default_nettype none

module top(
	input clk,
	output reg[15:0]led
	);

wire [15:0]wdata;
wire [15:0]waddr;
wire [15:0]raddr;
wire [15:0]rdata;
wire wr;
wire rd;

assign led = raddr;

sram ram0(
        .clk(clk),
        .waddr(waddr),
        .wdata(wdata),
        .we(wr),
        .raddr(raddr),
        .rdata(rdata),
        .re(rd)
	);

cpu
`ifdef BIGCPU
        #(
        .RWIDTH(32),
        .SWIDTH(5)
        )
`endif
        cpu0(
        .clk(clk),
        .mem_raddr_o(raddr),
        .mem_rdata_i(rdata),
        .mem_waddr_o(waddr),
        .mem_wdata_o(wdata),
        .mem_wr_o(wr),
        .mem_rd_o(rd)
        );

endmodule

module sram(
	input clk,
	input [15:0]waddr,
	input [15:0]wdata,
	input [15:0]raddr,
	output reg [15:0]rdata,
	input we,
	input re
	);

		rdata <= mem[raddr[11:0]];
end

endmodule

reg [15:0]mem[0:4095];

always @(posedge clk) begin