1. Initial version of westbone interface files copied from turbo8051 open core project
2. Initial version of RISCV Open core project copied from Syntacore SCR1 package
diff --git a/verilog/rtl/lib/wb_crossbar.v b/verilog/rtl/lib/wb_crossbar.v
new file mode 100644
index 0000000..9eb8f29
--- /dev/null
+++ b/verilog/rtl/lib/wb_crossbar.v
@@ -0,0 +1,399 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// OMS 8051 cores common library Module ////
+//// ////
+//// This file is part of the OMS 8051 cores project ////
+//// http://www.opencores.org/cores/oms8051mini/ ////
+//// ////
+//// Description ////
+//// OMS 8051 definitions. ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// Revision : Nov 26, 2016
+//// v-0.0 - Dinesh.A, Nov 26, 2016
+//// 1. Initial Version
+//// v-0.1 - Dinesh.A, Jan 19, 2017
+//// 1. Lint warning fixes, Seperated resetable and non
+// resetable logic
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+/**********************************************
+ Web-bone cross bar M-Master By S-Slave
+**********************************************/
+
+module wb_crossbar (
+
+ rst_n ,
+ clk ,
+
+
+ // Master Interface Signal
+ wbd_taddr_master ,
+ wbd_din_master ,
+ wbd_dout_master ,
+ wbd_adr_master ,
+ wbd_be_master ,
+ wbd_we_master ,
+ wbd_ack_master ,
+ wbd_stb_master ,
+ wbd_cyc_master ,
+ wbd_err_master ,
+ wbd_rty_master ,
+
+ // Slave Interface Signal
+ wbd_din_slave ,
+ wbd_dout_slave ,
+ wbd_adr_slave ,
+ wbd_be_slave ,
+ wbd_we_slave ,
+ wbd_ack_slave ,
+ wbd_stb_slave ,
+ wbd_cyc_slave ,
+ wbd_err_slave ,
+ wbd_rty_slave
+ );
+
+parameter WB_SLAVE = 4 ;
+parameter WB_MASTER = 4 ;
+
+parameter D_WD = 16; // Data Width
+parameter BE_WD = 2; // Byte Enable
+parameter ADR_WD = 28; // Address Width
+parameter TAR_WD = 4; // Target Width
+
+input clk; // CLK_I The clock input [CLK_I] coordinates all activities
+ // for the internal logic within the WISHBONE interconnect.
+ // All WISHBONE output signals are registered at the
+ // rising edge of [CLK_I].
+ // All WISHBONE input signals must be stable before the
+ // rising edge of [CLK_I].
+input rst_n; // RST_I The reset input [RST_I] forces the WISHBONE interface
+ // to restart. Furthermore, all internal self-starting state
+ // machines will be forced into an initial state.
+
+input [(WB_MASTER *TAR_WD)-1:0] wbd_taddr_master; // target address from master
+input [WB_MASTER-1:0] wbd_stb_master;
+ // STB_O The strobe output [STB_O] indicates a valid data
+ // transfer cycle. It is used to qualify various other signals
+ // on the interface such as [SEL_O(7..0)]. The SLAVE must
+ // assert either the [ACK_I], [ERR_I] or [RTY_I] signals in
+ // response to every assertion of the [STB_O] signal.
+output [WB_SLAVE-1:0] wbd_stb_slave;
+ // STB_O The strobe output [STB_O] indicates a valid data
+ // transfer cycle. It is used to qualify various other signals
+ // on the interface such as [SEL_O(7..0)]. The SLAVE must
+ // assert either the [ACK_I], [ERR_I] or [RTY_I] signals in
+ // response to every assertion of the [STB_O] signal.
+
+input [WB_MASTER-1:0] wbd_we_master;
+ // WE_O The write enable output [WE_O] indicates whether the
+ // current local bus cycle is a READ or WRITE cycle. The
+ // signal is negated during READ cycles, and is asserted
+ // during WRITE cycles.
+output [WB_SLAVE-1:0] wbd_we_slave;
+ // WE_O The write enable output [WE_O] indicates whether the
+ // current local bus cycle is a READ or WRITE cycle. The
+ // signal is negated during READ cycles, and is asserted
+ // during WRITE cycles.
+
+output [WB_MASTER-1:0] wbd_ack_master;
+ // The acknowledge input [ACK_I], when asserted,
+ // indicates the termination of a normal bus cycle.
+ // Also see the [ERR_I] and [RTY_I] signal descriptions.
+input [WB_SLAVE-1:0] wbd_ack_slave;
+ // The acknowledge input [ACK_I], when asserted,
+ // indicates the termination of a normal bus cycle.
+ // Also see the [ERR_I] and [RTY_I] signal descriptions.
+
+input [(WB_MASTER *ADR_WD)-1:0] wbd_adr_master;
+ // The address output array [ADR_O(63..0)] is used
+ // to pass a binary address, with the most significant
+ // address bit at the higher numbered end of the signal array.
+ // The lower array boundary is specific to the data port size.
+ // The higher array boundary is core-specific.
+ // In some cases (such as FIFO interfaces)
+ // the array may not be present on the interface.
+
+output [(WB_SLAVE *ADR_WD)-1:0] wbd_adr_slave;
+ // The address output array [ADR_O(63..0)] is used
+ // to pass a binary address, with the most significant
+ // address bit at the higher numbered end of the signal array.
+ // The lower array boundary is specific to the data port size.
+ // The higher array boundary is core-specific.
+ // In some cases (such as FIFO interfaces)
+ // the array may not be present on the interface.
+
+input [(WB_MASTER * BE_WD)-1:0] wbd_be_master; // Byte Enable
+ // SEL_O(7..0) The select output array [SEL_O(7..0)] indicates
+ // where valid data is expected on the [DAT_I(63..0)] signal
+ // array during READ cycles, and where it is placed on the
+ // [DAT_O(63..0)] signal array during WRITE cycles.
+ // Also see the [DAT_I(63..0)], [DAT_O(63..0)] and [STB_O]
+ // signal descriptions.
+output [(WB_SLAVE * BE_WD)-1:0] wbd_be_slave; // Byte Enable
+ // SEL_O(7..0) The select output array [SEL_O(7..0)] indicates
+ // where valid data is expected on the [DAT_I(63..0)] signal
+ // array during READ cycles, and where it is placed on the
+ // [DAT_O(63..0)] signal array during WRITE cycles.
+ // Also see the [DAT_I(63..0)], [DAT_O(63..0)] and [STB_O]
+ // signal descriptions.
+
+input [WB_MASTER -1:0] wbd_cyc_master;
+ // CYC_O The cycle output [CYC_O], when asserted,
+ // indicates that a valid bus cycle is in progress.
+ // The signal is asserted for the duration of all bus cycles.
+ // For example, during a BLOCK transfer cycle there can be
+ // multiple data transfers. The [CYC_O] signal is asserted
+ // during the first data transfer, and remains asserted
+ // until the last data transfer. The [CYC_O] signal is useful
+ // for interfaces with multi-port interfaces
+ // (such as dual port memories). In these cases,
+ // the [CYC_O] signal requests use of a common bus from an
+ // arbiter. Once the arbiter grants the bus to the MASTER,
+ // it is held until [CYC_O] is negated.
+output [WB_SLAVE -1:0] wbd_cyc_slave;
+ // CYC_O The cycle output [CYC_O], when asserted,
+ // indicates that a valid bus cycle is in progress.
+ // The signal is asserted for the duration of all bus cycles.
+ // For example, during a BLOCK transfer cycle there can be
+ // multiple data transfers. The [CYC_O] signal is asserted
+ // during the first data transfer, and remains asserted
+ // until the last data transfer. The [CYC_O] signal is useful
+ // for interfaces with multi-port interfaces
+ // (such as dual port memories). In these cases,
+ // the [CYC_O] signal requests use of a common bus from an
+ // arbiter. Once the arbiter grants the bus to the MASTER,
+ // it is held until [CYC_O] is negated.
+
+input [(WB_MASTER * D_WD)-1:0] wbd_din_master;
+ // DAT_I(63..0) The data input array [DAT_I(63..0)] is
+ // used to pass binary data. The array boundaries are
+ // determined by the port size. Also see the [DAT_O(63..0)]
+ // and [SEL_O(7..0)] signal descriptions.
+
+output [(WB_SLAVE * D_WD)-1:0] wbd_din_slave;
+ // DAT_I(63..0) The data input array [DAT_I(63..0)] is
+ // used to pass binary data. The array boundaries are
+ // determined by the port size. Also see the [DAT_O(63..0)]
+ // and [SEL_O(7..0)] signal descriptions.
+
+output [(WB_MASTER * D_WD)-1:0] wbd_dout_master;
+ // DAT_O(63..0) The data output array [DAT_O(63..0)] is
+ // used to pass binary data. The array boundaries are
+ // determined by the port size. Also see the [DAT_I(63..0)]
+ // and [SEL_O(7..0)] signal descriptions.
+input [(WB_SLAVE * D_WD)-1:0] wbd_dout_slave;
+ // DAT_O(63..0) The data output array [DAT_O(63..0)] is
+ // used to pass binary data. The array boundaries are
+ // determined by the port size. Also see the [DAT_I(63..0)]
+ // and [SEL_O(7..0)] signal descriptions.
+
+output [WB_MASTER -1:0] wbd_err_master;
+ // ERR_I The error input [ERR_I] indicates an abnormal
+ // cycle termination. The source of the error, and the
+ // response generated by the MASTER is defined by the IP core
+ // supplier in the WISHBONE DATASHEET. Also see the [ACK_I]
+ // and [RTY_I] signal descriptions.
+input [WB_SLAVE -1:0] wbd_err_slave;
+ // ERR_I The error input [ERR_I] indicates an abnormal
+ // cycle termination. The source of the error, and the
+ // response generated by the MASTER is defined by the IP core
+ // supplier in the WISHBONE DATASHEET. Also see the [ACK_I]
+ // and [RTY_I] signal descriptions.
+
+output [WB_MASTER -1:0] wbd_rty_master;
+ // RTY_I The retry input [RTY_I] indicates that the indicates
+ // that the interface is not ready to accept or send data, and
+ // that the cycle should be retried. When and how the cycle is
+ // retried is defined by the IP core supplier in the WISHBONE
+ // DATASHEET. Also see the [ERR_I] and [RTY_I] signal
+ // descriptions.
+input [WB_SLAVE -1:0] wbd_rty_slave;
+ // RTY_I The retry input [RTY_I] indicates that the indicates
+ // that the interface is not ready to accept or send data, and
+ // that the cycle should be retried. When and how the cycle is
+ // retried is defined by the IP core supplier in the WISHBONE
+ // DATASHEET. Also see the [ERR_I] and [RTY_I] signal
+ // descriptions.
+
+
+reg [WB_MASTER-1:0] wbd_ack_master;
+reg [WB_MASTER-1:0] wbd_err_master;
+reg [WB_MASTER-1:0] wbd_rty_master;
+
+
+reg [WB_MASTER-1:0] master_busy; // master busy flag
+reg [WB_SLAVE-1:0] slave_busy; // slave busy flag
+reg [TAR_WD -1:0] master_mx_id[WB_MASTER-1:0];
+reg [TAR_WD -1:0] slave_mx_id [WB_SLAVE-1:0];
+
+wire [TAR_WD-1:0] wbd_taddr_master_t[WB_MASTER-1:0]; // target address from master
+wire [D_WD-1:0] wbd_din_master_t[WB_MASTER-1:0]; // target address from master
+reg [D_WD-1:0] wbd_dout_master_t[WB_MASTER-1:0]; // target address from master
+wire [ADR_WD-1:0] wbd_adr_master_t[WB_MASTER-1:0]; // target address from master
+wire [BE_WD-1:0] wbd_be_master_t[WB_MASTER-1:0]; // target address from master
+
+
+reg [WB_SLAVE-1:0] wbd_stb_slave;
+reg [WB_SLAVE-1:0] wbd_we_slave;
+reg [WB_SLAVE-1:0] wbd_cyc_slave;
+wire [D_WD-1:0] wbd_dout_slave_t[WB_SLAVE-1:0]; // target data towards master
+
+
+reg [D_WD-1:0] wbd_din_slave_t[WB_SLAVE-1:0]; // target address from master
+reg [ADR_WD-1:0] wbd_adr_slave_t[WB_SLAVE-1:0]; // target address from master
+reg [BE_WD-1:0] wbd_be_slave_t[WB_SLAVE-1:0]; // target address from master
+
+integer i,k,l,n;
+
+
+/**********************************************************
+ Re-Arraging the array in seperate two dimensional information
+***********************************************************/
+
+genvar j,m;
+generate
+
+ // Connect the Master Mux
+ for(j=0; j < WB_MASTER ; j = j + 1) begin : master_expand
+ assign wbd_taddr_master_t[j] = wbd_taddr_master[((j+1)*TAR_WD)-1:j * TAR_WD];
+ assign wbd_din_master_t[j] = wbd_din_master[((j+1)*D_WD)-1:j * D_WD];
+ assign wbd_adr_master_t[j] = wbd_adr_master[((j+1)*ADR_WD)-1:j * ADR_WD];
+ assign wbd_be_master_t[j] = wbd_be_master[((j+1)*BE_WD)-1:j * BE_WD];
+
+ assign wbd_dout_master[((j+1)*D_WD)-1:j * D_WD] = wbd_dout_master_t[j];
+ end
+
+ // Connect the Slave Mux
+ for(m=0; m < WB_SLAVE ; m = m + 1) begin : slave_expand
+ assign wbd_din_slave[((m+1)*D_WD)-1:m * D_WD] = wbd_din_slave_t[m];
+ assign wbd_adr_slave[((m+1)*ADR_WD)-1:m * ADR_WD] = wbd_adr_slave_t[m];
+ assign wbd_be_slave[((m+1)*BE_WD)-1:m * BE_WD] = wbd_be_slave_t[m];
+
+ assign wbd_dout_slave_t[m] = wbd_dout_slave[((m+1)*D_WD)-1:m * D_WD];
+
+ end
+endgenerate
+
+always @* begin
+ for(k = 0; k < WB_MASTER; k = k + 1) begin
+ if(master_busy[k] == 1) begin
+ wbd_dout_master_t[k] = wbd_dout_slave_t[master_mx_id[k]];
+ wbd_ack_master[k] = wbd_ack_slave[master_mx_id[k]];
+ wbd_err_master[k] = wbd_err_slave[master_mx_id[k]];
+ wbd_rty_master[k] = wbd_rty_slave[master_mx_id[k]];
+ end else begin
+ wbd_dout_master_t[k] = 0;
+ wbd_ack_master[k] = 0;
+ wbd_err_master[k] = 0;
+ wbd_rty_master[k] = 0;
+ end
+ end
+ for(l = 0; l < WB_SLAVE; l = l + 1) begin
+ if(slave_busy[l] == 1) begin
+ wbd_din_slave_t[l] = wbd_din_master_t[slave_mx_id[l]];
+ wbd_adr_slave_t[l] = wbd_adr_master_t[slave_mx_id[l]];
+ wbd_be_slave_t[l] = wbd_be_master_t[slave_mx_id[l]];
+ wbd_stb_slave[l] = wbd_stb_master[slave_mx_id[l]];
+ wbd_we_slave[l] = wbd_we_master[slave_mx_id[l]];
+ wbd_cyc_slave[l] = wbd_cyc_master[slave_mx_id[l]];
+ end else begin
+ wbd_din_slave_t[l] = 0;
+ wbd_adr_slave_t[l] = 0;
+ wbd_be_slave_t[l] = 0;
+ wbd_stb_slave[l] = 0;
+ wbd_we_slave[l] = 0;
+ wbd_cyc_slave[l] = 0;
+ end
+ end
+end
+
+/*******************************************************
+ Parsing through the master and deciding on mux connectio
+ Step-1: analysis the master from 0 to total master
+ Step-2: If the previously master is not busy,
+ Then check for any new request from the master and
+ check corresponding slave is free or not. If there is
+ master request and requesting slave is free.
+ Then set the master max id to slave id &
+ requesting slave to master number & set the master
+ and slave busy flag
+ Step-3: If the previous state of master is busy and bus-cycle
+ is de-asserted, then reset the master and corresponding
+ slave busy flag
+
+*********************************************************/
+
+always @(negedge rst_n or posedge clk) begin
+ if(rst_n == 0) begin
+ master_busy <= 0;
+ slave_busy <= 0;
+ end else begin
+ for(i = 0; i < WB_MASTER; i = i + 1) begin
+ if(master_busy[i] == 0) begin
+ if(wbd_stb_master[i] & slave_busy[wbd_taddr_master_t[i]] == 0) begin
+ slave_busy[wbd_taddr_master_t[i]] <= 1;
+ master_busy[i] <= 1;
+ end
+ end else if(wbd_cyc_master[i] == 0) begin
+ master_busy[i] <= 0;
+ slave_busy[wbd_taddr_master_t[i]] <= 0;
+ end
+ end
+ end
+end
+
+// Seperated non resetable two dimensional reg
+always @(posedge clk) begin
+ for(n = 0; n < WB_MASTER; n = n + 1) begin
+ if(master_busy[n] == 0) begin
+ if(wbd_stb_master[n] & slave_busy[wbd_taddr_master_t[n]] == 0) begin
+ master_mx_id[n] <= wbd_taddr_master_t[n];
+ slave_mx_id [wbd_taddr_master_t[n]] <= n;
+ // synopsys translate_off
+ // $display("%m:%t: Locking Master : %d with Slave : %d",$time,i,wbd_taddr_master_t[n]);
+ // synopsys translate_on
+ end
+ end else if(wbd_cyc_master[n] == 0) begin
+ if(master_busy[n] == 1) begin
+ // synopsys translate_off
+ // $display("%m:%t: Releasing Master : %d with Slave : %d",$time,i,wbd_taddr_master_t[n]);
+ // synopsys translate_on
+ end
+ end
+ end
+end
+
+
+endmodule
diff --git a/verilog/rtl/lib/wb_interface.v b/verilog/rtl/lib/wb_interface.v
new file mode 100644
index 0000000..aae1695
--- /dev/null
+++ b/verilog/rtl/lib/wb_interface.v
@@ -0,0 +1,383 @@
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// OMS 8051 cores common library Module ////
+//// ////
+//// This file is part of the OMS 8051 cores project ////
+//// http://www.opencores.org/cores/oms8051mini/ ////
+//// ////
+//// Description ////
+//// OMS 8051 definitions. ////
+//// ////
+//// To Do: ////
+//// nothing ////
+//// ////
+//// Author(s): ////
+//// - Dinesh Annayya, dinesha@opencores.org ////
+//// ////
+//// Revision : Nov 26, 2016 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2000 Authors and OPENCORES.ORG ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer. ////
+//// ////
+//// This source file is free software; you can redistribute it ////
+//// and/or modify it under the terms of the GNU Lesser General ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any ////
+//// later version. ////
+//// ////
+//// This source is distributed in the hope that it will be ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
+//// PURPOSE. See the GNU Lesser General Public License for more ////
+//// details. ////
+//// ////
+//// You should have received a copy of the GNU Lesser General ////
+//// Public License along with this source; if not, download it ////
+//// from http://www.opencores.org/lgpl.shtml ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module wb_interface (
+ rst ,
+ clk ,
+
+ dma_req_i ,
+ dma_write_i ,
+ dma_addr_i ,
+ dma_length_i ,
+ dma_ack_o ,
+ dma_done_o ,
+
+ dma_start_o ,
+ dma_wr_o ,
+ dma_rd_o ,
+ dma_last_o ,
+ dma_wdata_i ,
+ dma_rdata_o ,
+
+ // external memory
+ wbd_dat_i ,
+ wbd_dat_o ,
+ wbd_adr_o ,
+ wbd_be_o ,
+ wbd_we_o ,
+ wbd_ack_i ,
+ wbd_stb_o ,
+ wbd_cyc_o ,
+ wbd_err_i
+
+
+ );
+
+
+
+input rst ;
+input clk ;
+
+input dma_req_i ;
+input dma_write_i ;
+input [25:0] dma_addr_i ;
+input [7:0] dma_length_i ;
+output dma_ack_o ;
+output dma_done_o ; // indicates end of DMA transaction
+
+output dma_start_o ;
+output dma_wr_o ;
+output dma_rd_o ;
+output dma_last_o ;
+input [31:0] dma_wdata_i ;
+output [31:0] dma_rdata_o ;
+
+//--------------------------------
+// WB interface
+//--------------------------------
+input [31:0] wbd_dat_i ; // data input
+output [31:0] wbd_dat_o ; // data output
+output [23:0] wbd_adr_o ; // address
+output [3:0] wbd_be_o ; // byte enable
+output wbd_we_o ; // write
+input wbd_ack_i ; // acknowlegement
+output wbd_stb_o ; // strobe/request
+output wbd_cyc_o ; // wb cycle
+input wbd_err_i ; // we error
+
+//------------------------------------
+// Reg Declaration
+//--------------------------------
+reg [2:0] state ;
+reg [2:0] state_d ;
+reg [7:0] preq_len ; // pending request length in bytes
+reg wbd_we_o ; // westbone write req
+reg [23:0] wbd_adr_o ; // westnone address
+reg dma_ack_o ; // dma ack
+reg [7:0] twbtrans ; // total westbone transaction
+reg dma_wr_o ; // dma write request
+reg dma_rd_o ; // dma read request
+reg [31:0] temp_data ; // temp holding data
+reg [1:0] be_sof ; // Byte enable starting alignment
+reg [31:0] wbd_dat_o ; // westbone data out
+reg [3:0] wbd_be_o ; // west bone byte enable
+reg [31:0] dma_rdata_o ; // dma read data
+reg wbd_stb_o ;
+reg dma_start_o ; // dma first transfer
+reg dma_last_o ; // dma last transfer
+
+parameter WB_IDLE = 3'b000;
+parameter WB_REQ = 3'b001;
+parameter WB_WR_PHASE = 3'b010;
+parameter WB_RD_PHASE_SOF = 3'b011;
+parameter WB_RD_PHASE_CONT = 3'b100;
+
+assign dma_done_o = (state == WB_IDLE) && (state_d != WB_IDLE);
+
+always @(posedge rst or posedge clk)
+begin
+ if(rst) begin
+ state <= WB_IDLE;
+ state_d <= WB_IDLE;
+ wbd_we_o <= 0;
+ wbd_adr_o <= 0;
+ preq_len <= 0;
+ dma_ack_o <= 0;
+ twbtrans <= 0;
+ dma_wr_o <= 0;
+ dma_rd_o <= 0;
+ temp_data <= 0;
+ be_sof <= 0;
+ wbd_dat_o <= 0;
+ wbd_be_o <= 0;
+ dma_rdata_o <= 0;
+ wbd_stb_o <= 0;
+ dma_start_o <= 0;
+ dma_last_o <= 0;
+ end
+ else begin
+ state_d <= state;
+ case(state)
+ WB_IDLE :
+ begin
+ if(dma_req_i)
+ begin
+ dma_ack_o <= 1;
+ wbd_we_o <= dma_write_i;
+ wbd_adr_o <= dma_addr_i[25:2];
+ be_sof <= dma_addr_i[1] << 1 + dma_addr_i[0];
+ preq_len <= dma_length_i;
+ // total wb transfer
+ twbtrans <= dma_length_i[7:2] +
+ |(dma_length_i[1:0]) +
+ |(dma_addr_i[1:0]);
+ state <= WB_REQ;
+ end
+ dma_wr_o <= 0;
+ dma_rd_o <= 0;
+ wbd_stb_o <= 0;
+ dma_start_o <= 0;
+ end
+ WB_REQ :
+ begin
+ dma_ack_o <= 0;
+ wbd_stb_o <= 1;
+ if(wbd_we_o) begin
+ dma_wr_o <= 1;
+ dma_start_o <= 1;
+ temp_data <= dma_wdata_i;
+ if(be_sof == 0) begin
+ wbd_dat_o <= dma_wdata_i;
+ wbd_be_o <= 4'b1111;
+ preq_len <= preq_len - 4;
+ end
+ else if(be_sof == 1) begin
+ wbd_dat_o <= {dma_wdata_i[23:0],8'h0};
+ wbd_be_o <= 4'b1110;
+ preq_len <= preq_len - 3;
+ end
+ else if(be_sof == 2) begin
+ wbd_dat_o <= {dma_wdata_i[15:0],16'h0};
+ wbd_be_o <= 4'b1100;
+ preq_len <= preq_len - 2;
+ end
+ else begin
+ wbd_dat_o <= {dma_wdata_i[7:0],23'h0};
+ wbd_be_o <= 4'b1000;
+ preq_len <= preq_len - 1;
+ end
+ twbtrans <= twbtrans -1;
+ state <= WB_WR_PHASE;
+ if(twbtrans == 1)
+ dma_last_o <= 1;
+ end
+ else begin
+ state <= WB_RD_PHASE_SOF;
+ end
+ end
+ WB_WR_PHASE :
+ begin
+ dma_start_o <= 0;
+ if(wbd_ack_i) begin
+ if(twbtrans == 1)
+ dma_last_o <= 1;
+ else
+ dma_last_o <= 0;
+ if(twbtrans > 0) begin
+ temp_data <= dma_wdata_i;
+ twbtrans <= twbtrans -1;
+ if(be_sof == 0) begin
+ wbd_dat_o <= dma_wdata_i;
+ end
+ else if(be_sof == 1) begin
+ wbd_dat_o <= {dma_wdata_i[23:0],temp_data[31:24]};
+ end
+ else if(be_sof == 2) begin
+ wbd_dat_o <= {dma_wdata_i[15:0],temp_data[31:16]};
+ end
+ else begin
+ wbd_dat_o <= {dma_wdata_i[7:0],temp_data[31:8]};
+ end
+
+ if(twbtrans > 1) begin // If the Pending Transfer is more than 1
+ dma_wr_o <= 1;
+ wbd_be_o <= 4'b1111;
+ preq_len <= preq_len - 4;
+ end
+ else begin // for last write access
+ wbd_be_o <= preq_len[1:0] == 2'b00 ? 4'b1111:
+ preq_len[1:0] == 2'b01 ? 4'b0001:
+ preq_len[1:0] == 2'b10 ? 4'b0011: 4'b0111;
+
+ case({be_sof[1:0],preq_len[1:0]})
+ // Start alignment = 0
+ 4'b0001 : dma_wr_o <= 1;
+ 4'b0010 : dma_wr_o <= 1;
+ 4'b0011 : dma_wr_o <= 1;
+ 4'b0000 : dma_wr_o <= 1;
+ // Start alignment = 1
+ 4'b0101 : dma_wr_o <= 0;
+ 4'b0110 : dma_wr_o <= 1;
+ 4'b0111 : dma_wr_o <= 1;
+ 4'b0100 : dma_wr_o <= 1;
+ // Start alignment = 2
+ 4'b1001 : dma_wr_o <= 0;
+ 4'b1010 : dma_wr_o <= 0;
+ 4'b1011 : dma_wr_o <= 1;
+ 4'b1000 : dma_wr_o <= 1;
+ // Start alignment = 3
+ 4'b1101 : dma_wr_o <= 0;
+ 4'b1110 : dma_wr_o <= 0;
+ 4'b1111 : dma_wr_o <= 0;
+ 4'b1100 : dma_wr_o <= 1;
+ endcase
+ end
+ end
+ else begin
+ dma_wr_o <= 0;
+ wbd_stb_o <= 0;
+ state <= WB_IDLE;
+ end
+ end
+ else begin
+ dma_last_o <= 0;
+ dma_wr_o <= 0;
+ end
+ end
+ WB_RD_PHASE_SOF :
+ begin
+ if(wbd_ack_i) begin
+ twbtrans <= twbtrans -1;
+ if(twbtrans == 1) begin // If the Pending Transfer is 1
+ dma_rd_o <= 1;
+ dma_start_o<= 1;
+ if(be_sof == 0) begin
+ dma_rdata_o <= wbd_dat_i;
+ preq_len <= preq_len - 4;
+ end
+ else if(be_sof == 1) begin
+ dma_rdata_o <= {8'h0,wbd_dat_i[31:24]};
+ preq_len <= preq_len - 3;
+ end
+ else if(be_sof == 2) begin
+ dma_rdata_o <= {16'h0,wbd_dat_i[31:16]};
+ preq_len <= preq_len - 2;
+ end
+ else begin
+ dma_rdata_o <= {23'h0,wbd_dat_i[31:8]};
+ preq_len <= preq_len - 0;
+ end
+ dma_last_o <= 1;
+ state <= WB_IDLE;
+ end
+ else begin // pending transction is more than 1
+ if(be_sof == 0) begin
+ dma_rdata_o <= wbd_dat_i;
+ dma_rd_o <= 1;
+ dma_start_o <= 1;
+ preq_len <= preq_len - 4;
+ end
+ else if(be_sof == 1) begin
+ temp_data <= {8'h0,wbd_dat_i[31:24]};
+ dma_rd_o <= 0;
+ preq_len <= preq_len - 3;
+ end
+ else if(be_sof == 2) begin
+ temp_data <= {16'h0,wbd_dat_i[31:16]};
+ preq_len <= preq_len - 2;
+ end
+ else begin
+ temp_data <= {23'h0,wbd_dat_i[31:8]};
+ preq_len <= preq_len - 0;
+ end
+ state <= WB_RD_PHASE_CONT;
+ end
+ end
+ else begin
+ dma_rd_o <= 0;
+ end
+ end
+ WB_RD_PHASE_CONT:
+ begin
+ dma_start_o <= 0;
+ if(wbd_ack_i) begin
+ dma_rd_o <= 1;
+ twbtrans <= twbtrans -1;
+ if(be_sof == 0) begin
+ dma_rdata_o <= wbd_dat_i;
+ preq_len <= preq_len - 4;
+ end
+ else if(be_sof == 1) begin
+ dma_rdata_o <= {wbd_dat_i[7:0],temp_data[23:0]};
+ temp_data <= {8'h0,wbd_dat_i[31:8]};
+ preq_len <= preq_len - 3;
+ end
+ else if(be_sof == 2) begin
+ dma_rdata_o <= {wbd_dat_i[15:0],temp_data[15:0]};
+ temp_data <= {16'h0,wbd_dat_i[31:16]};
+ preq_len <= preq_len - 2;
+ end
+ else begin
+ dma_rdata_o <= {wbd_dat_i[23:0],temp_data[7:0]};
+ temp_data <= {24'h0,wbd_dat_i[31:23]};
+ preq_len <= preq_len - 1;
+ end
+ if(twbtrans == 1) begin // If the it's last transfer
+ dma_last_o <= 1;
+ state <= WB_IDLE;
+ end
+ end
+ else begin
+ dma_last_o <= 0;
+ dma_rd_o <= 0;
+ end
+ end
+ endcase
+ end
+end
+
+
+
+endmodule
diff --git a/verilog/rtl/syntacore_scr1/.gitignore b/verilog/rtl/syntacore_scr1/.gitignore
new file mode 100644
index 0000000..7a71ac8
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/.gitignore
@@ -0,0 +1,2 @@
+build/**
+sim/tests/benchmarks/coremark/src/**
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/.gitmodules b/verilog/rtl/syntacore_scr1/.gitmodules
new file mode 100644
index 0000000..937d721
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "dependencies/riscv-tests"]
+ path = dependencies/riscv-tests
+ url = https://github.com/riscv/riscv-tests
+[submodule "dependencies/riscv-compliance"]
+ path = dependencies/riscv-compliance
+ url = https://github.com/riscv/riscv-compliance
+[submodule "dependencies/coremark"]
+ path = dependencies/coremark
+ url = https://github.com/eembc/coremark
diff --git a/verilog/rtl/syntacore_scr1/LICENSE b/verilog/rtl/syntacore_scr1/LICENSE
new file mode 100644
index 0000000..0d753ad
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/LICENSE
@@ -0,0 +1,23 @@
+# Solderpad Hardware Licence Version 2.0
+
+This licence (the “Licence”) operates as a wraparound licence to the Apache License Version 2.0 (the “Apache License”) and grants to You the rights, and imposes the obligations, set out in the Apache License (which can be found here: http://apache.org/licenses/LICENSE-2.0), with the following extensions. It must be read in conjunction with the Apache License. Section 1 below modifies definitions in the Apache License, and section 2 below replaces sections 2 of the Apache License. You may, at your option, choose to treat any Work released under this License as released under the Apache License (thus ignoring all sections written below entirely). Words in italics indicate changes rom the Apache License, but are indicative and not to be taken into account in interpretation.
+
+1. The definitions set out in the Apache License are modified as follows:
+
+Copyright any reference to ‘copyright’ (whether capitalised or not) includes ‘Rights’ (as defined below).
+
+Contribution also includes any design, as well as any work of authorship.
+
+Derivative Works shall not include works that remain reversibly separable from, or merely link (or bind by name) or physically connect to or interoperate with the interfaces of the Work and Derivative Works thereof.
+
+Object form shall mean any form resulting from mechanical transformation or translation of a Source form or the application of a Source form to physical material, including but not limited to compiled object code, generated documentation, the instantiation of a hardware design or physical object and conversions to other media types, including intermediate forms such as bytecodes, FPGA bitstreams, moulds, artwork and semiconductor topographies (mask works).
+
+Rights means copyright and any similar right including design right (whether registered or unregistered), semiconductor topography (mask) rights and database rights (but excluding Patents and Trademarks).
+
+Source form shall mean the preferred form for making modifications, including but not limited to source code, net lists, board layouts, CAD files, documentation source, and configuration files.
+
+Work also includes a design or work of authorship, whether in Source form or other Object form.
+
+2. Grant of Licence
+
+2.1 Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license under the Rights to reproduce, prepare Derivative Works of, make, adapt, repair, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form and do anything in relation to the Work as if the Rights did not exist.
diff --git a/verilog/rtl/syntacore_scr1/Makefile b/verilog/rtl/syntacore_scr1/Makefile
new file mode 100644
index 0000000..adb33c5
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/Makefile
@@ -0,0 +1,293 @@
+#------------------------------------------------------------------------------
+# Makefile for SCR1
+#------------------------------------------------------------------------------
+
+# PARAMETERS
+
+# CFG = <MAX, BASE, MIN, CUSTOM>
+# BUS = <AHB, AXI>
+
+export CFG ?= MAX
+export BUS ?= AHB
+
+ifeq ($(CFG), MAX)
+# Predefined configuration SCR1_CFG_RV32IMC_MAX
+ override ARCH := IMC
+ override VECT_IRQ := 1
+ override IPIC := 1
+ override TCM := 1
+ override SIM_CFG_DEF := SCR1_CFG_RV32IMC_MAX
+else
+ ifeq ($(CFG), BASE)
+ # Predefined configuration SCR1_CFG_RV32IC_BASE
+ override ARCH := IC
+ override VECT_IRQ := 1
+ override IPIC := 1
+ override TCM := 1
+ override SIM_CFG_DEF := SCR1_CFG_RV32IC_BASE
+ else
+ ifeq ($(CFG), MIN)
+ # Predefined configuration SCR1_CFG_RV32EC_MIN
+ override ARCH := EC
+ override VECT_IRQ := 0
+ override IPIC := 0
+ override TCM := 1
+ override SIM_CFG_DEF := SCR1_CFG_RV32EC_MIN
+ else
+ # CUSTOM configuration. Parameters can be overwritten
+ # These options are for compiling tests only. Set the corresponding RTL parameters manually in the file scr1_arch_description.svh.
+ # ARCH = <IMC, IC, IM, I, EMC, EM, EC, E>
+ # VECT_IRQ = <0, 1>
+ # IPIC = <0, 1>
+ # TCM = <0, 1>
+ ARCH ?= IMC
+ VECT_IRQ ?= 0
+ IPIC ?= 0
+ TCM ?= 0
+ SIM_CFG_DEF = SCR1_CFG_$(CFG)
+ endif
+ endif
+endif
+
+# export all overrided variables
+export ARCH
+export VECT_IRQ
+export IPIC
+export TCM
+export SIM_CFG_DEF
+
+ARCH_lowercase = $(shell echo $(ARCH) | tr A-Z a-z)
+BUS_lowercase = $(shell echo $(BUS) | tr A-Z a-z)
+
+ifeq ($(ARCH_lowercase),)
+ ARCH_tmp = imc
+else
+ ifneq (,$(findstring e,$(ARCH_lowercase)))
+ ARCH_tmp += e
+ EXT_CFLAGS += -D__RVE_EXT
+ else
+ ARCH_tmp += i
+ endif
+ ifneq (,$(findstring m,$(ARCH_lowercase)))
+ ARCH_tmp := $(ARCH_tmp)m
+ endif
+ ifneq (,$(findstring c,$(ARCH_lowercase)))
+ ARCH_tmp := $(ARCH_tmp)c
+ EXT_CFLAGS += -D__RVC_EXT
+ endif
+endif
+
+override ARCH=$(ARCH_tmp)
+
+# Use this parameter to enable tracelog
+TRACE ?= 0
+
+ifeq ($(TRACE), 1)
+ export SIM_TRACE_DEF = SCR1_TRACE_LOG_EN
+else
+ export SIM_TRACE_DEF = SCR1_TRACE_LOG_DIS
+endif
+
+
+# Use this parameter to pass additional options for simulation build command
+SIM_BUILD_OPTS ?=
+
+# Use this parameter to set the list of tests to run
+# TARGETS = <riscv_isa, riscv_compliance, coremark, dhrystone21, hello, isr_sample>
+export TARGETS :=
+
+
+export ABI ?= ilp32
+# Testbench memory delay patterns\
+ (FFFFFFFF - no delay, 00000000 - random delay, 00000001 - max delay)
+imem_pattern ?= FFFFFFFF
+dmem_pattern ?= FFFFFFFF
+
+VCS_OPTS ?=
+MODELSIM_OPTS ?=
+NCSIM_OPTS ?=
+VERILATOR_OPTS ?=
+
+current_goal := $(MAKECMDGOALS:run_%=%)
+ifeq ($(current_goal),)
+ current_goal := verilator
+endif
+
+# Paths
+export root_dir := $(shell pwd)
+export tst_dir := $(root_dir)/sim/tests
+export inc_dir := $(tst_dir)/common
+export bld_dir := $(root_dir)/build/$(current_goal)_$(BUS)_$(CFG)_$(ARCH)_IPIC_$(IPIC)_TCM_$(TCM)_VIRQ_$(VECT_IRQ)_TRACE_$(TRACE)
+
+test_results := $(bld_dir)/test_results.txt
+test_info := $(bld_dir)/test_info
+sim_results := $(bld_dir)/sim_results.txt
+
+todo_list := $(bld_dir)/todo.txt
+# Environment
+export CROSS_PREFIX ?= riscv64-unknown-elf-
+export RISCV_GCC ?= $(CROSS_PREFIX)gcc
+export RISCV_OBJDUMP ?= $(CROSS_PREFIX)objdump -D
+export RISCV_OBJCOPY ?= $(CROSS_PREFIX)objcopy -O verilog
+export RISCV_READELF ?= $(CROSS_PREFIX)readelf -s
+#--
+ifneq (,$(findstring axi,$(BUS_lowercase)))
+export rtl_top_files := axi_top.files
+export rtl_tb_files := axi_tb.files
+export top_module := scr1_top_tb_axi
+else
+export rtl_top_files := ahb_top.files
+export rtl_tb_files := ahb_tb.files
+export top_module := scr1_top_tb_ahb
+endif
+
+ifneq (,$(findstring e,$(ARCH_lowercase)))
+# Tests can be compiled for RVE only if gcc version 8.0.0 or higher
+ GCCVERSIONGT7 := $(shell expr `$(RISCV_GCC) -dumpfullversion | cut -f1 -d'.'` \> 7)
+ ifeq "$(GCCVERSIONGT7)" "1"
+ ABI := ilp32e
+ endif
+endif
+
+#--
+ifeq (,$(findstring e,$(ARCH_lowercase)))
+# These tests cannot be compiled for RVE
+
+ # Comment this target if you don't want to run the riscv_isa
+ TARGETS += riscv_isa
+
+ # Comment this target if you don't want to run the riscv_compliance
+ TARGETS += riscv_compliance
+endif
+
+# Comment this target if you don't want to run the isr_sample
+TARGETS += isr_sample
+
+# Comment this target if you don't want to run the coremark
+TARGETS += coremark
+
+# Comment this target if you don't want to run the dhrystone
+TARGETS += dhrystone21
+
+# Comment this target if you don't want to run the hello test
+TARGETS += hello
+
+# Targets
+.PHONY: tests run_modelsim run_vcs run_ncsim run_verilator run_verilator_wf
+
+default: clean_test_list run_verilator
+
+clean_test_list:
+ rm -f $(test_info)
+
+echo_out: tests
+ @echo " Test | build | simulation " ;
+ @echo "$$(cat $(test_results))"
+
+tests: $(TARGETS)
+
+$(test_info): clean_hex tests
+ cd $(bld_dir)
+
+isr_sample: | $(bld_dir)
+ $(MAKE) -C $(tst_dir)/isr_sample ARCH=$(ARCH) IPIC=$(IPIC) VECT_IRQ=$(VECT_IRQ)
+
+dhrystone21: | $(bld_dir)
+ $(MAKE) -C $(tst_dir)/benchmarks/dhrystone21 EXT_CFLAGS="$(EXT_CFLAGS)" ARCH=$(ARCH)
+
+coremark: | $(bld_dir)
+ -$(MAKE) -C $(tst_dir)/benchmarks/coremark EXT_CFLAGS="$(EXT_CFLAGS)" ARCH=$(ARCH)
+
+riscv_isa: | $(bld_dir)
+ $(MAKE) -C $(tst_dir)/riscv_isa ARCH=$(ARCH)
+
+riscv_compliance: | $(bld_dir)
+ $(MAKE) -C $(tst_dir)/riscv_compliance ARCH=$(ARCH)
+
+hello: | $(bld_dir)
+ -$(MAKE) -C $(tst_dir)/hello EXT_CFLAGS="$(EXT_CFLAGS)" ARCH=$(ARCH)
+
+clean_hex: | $(bld_dir)
+ $(RM) $(bld_dir)/*.hex
+
+$(bld_dir):
+ mkdir -p $(bld_dir)
+
+run_vcs: $(test_info)
+ $(MAKE) -C $(root_dir)/sim build_vcs SIM_CFG_DEF=$(SIM_CFG_DEF) SIM_TRACE_DEF=$(SIM_TRACE_DEF) SIM_BUILD_OPTS=$(SIM_BUILD_OPTS);
+ printf "" > $(test_results);
+ cd $(bld_dir); \
+ $(bld_dir)/simv -V \
+ +test_info=$(test_info) \
+ +test_results=$(test_results) \
+ +imem_pattern=$(imem_pattern) \
+ +dmem_pattern=$(dmem_pattern) \
+ $(VCS_OPTS) | tee $(sim_results) ;\
+ printf " Test | build | simulation \n" ; \
+ printf "$$(cat $(test_results)) \n"
+run_modelsim: $(test_info)
+ $(MAKE) -C $(root_dir)/sim build_modelsim SIM_CFG_DEF=$(SIM_CFG_DEF) SIM_TRACE_DEF=$(SIM_TRACE_DEF) SIM_BUILD_OPTS=$(SIM_BUILD_OPTS); \
+ printf "" > $(test_results); \
+ cd $(bld_dir); \
+ vsim -c -do "run -all" +nowarn3691 \
+ +test_info=$(test_info) \
+ +test_results=$(test_results) \
+ +imem_pattern=$(imem_pattern) \
+ +dmem_pattern=$(dmem_pattern) \
+ work.$(top_module) \
+ $(MODELSIM_OPTS) | tee $(sim_results) ;\
+ printf "Simulation performed on $$(vsim -version) \n" ;\
+ printf " Test | build | simulation \n" ; \
+ printf "$$(cat $(test_results)) \n"
+
+run_ncsim: $(test_info)
+ $(MAKE) -C $(root_dir)/sim build_ncsim SIM_CFG_DEF=$(SIM_CFG_DEF) SIM_TRACE_DEF=$(SIM_TRACE_DEF) SIM_BUILD_OPTS=$(SIM_BUILD_OPTS);
+ printf "" > $(test_results);
+ cd $(bld_dir); \
+ irun \
+ -R \
+ -64bit \
+ +test_info=$(test_info) \
+ +test_results=$(test_results) \
+ +imem_pattern=$(imem_pattern) \
+ +dmem_pattern=$(dmem_pattern) \
+ $(NCSIM_OPTS) | tee $(sim_results) ;\
+ printf "Simulation performed on $$(irun -version) \n" ;\
+ printf " Test | build | simulation \n" ; \
+ printf "$$(cat $(test_results)) \n"
+
+run_verilator: $(test_info)
+ $(MAKE) -C $(root_dir)/sim build_verilator SIM_CFG_DEF=$(SIM_CFG_DEF) SIM_TRACE_DEF=$(SIM_TRACE_DEF) SIM_BUILD_OPTS=$(SIM_BUILD_OPTS);
+ printf "" > $(test_results);
+ cd $(bld_dir); \
+ echo $(top_module) | tee $(sim_results); \
+ $(bld_dir)/verilator/V$(top_module) \
+ +test_info=$(test_info) \
+ +test_results=$(test_results) \
+ +imem_pattern=$(imem_pattern) \
+ +dmem_pattern=$(dmem_pattern) \
+ $(VERILATOR_OPTS) | tee -a $(sim_results) ;\
+ printf "Simulation performed on $$(verilator -version) \n" ;\
+ printf " Test | build | simulation \n" ; \
+ printf "$$(cat $(test_results)) \n"
+
+run_verilator_wf: $(test_info)
+ $(MAKE) -C $(root_dir)/sim build_verilator_wf SIM_CFG_DEF=$(SIM_CFG_DEF) SIM_TRACE_DEF=$(SIM_TRACE_DEF) SIM_BUILD_OPTS=$(SIM_BUILD_OPTS);
+ printf "" > $(test_results);
+ cd $(bld_dir); \
+ echo $(top_module) | tee $(sim_results); \
+ $(bld_dir)/verilator/V$(top_module) \
+ +test_info=$(test_info) \
+ +test_results=$(test_results) \
+ +imem_pattern=$(imem_pattern) \
+ +dmem_pattern=$(dmem_pattern) \
+ $(VERILATOR_OPTS) | tee -a $(sim_results) ;\
+ printf "Simulation performed on $$(verilator -version) \n" ;\
+ printf " Test | build | simulation \n" ; \
+ printf "$$(cat $(test_results)) \n"
+clean:
+ $(MAKE) -C $(tst_dir)/benchmarks/dhrystone21 clean
+ $(MAKE) -C $(tst_dir)/riscv_isa clean
+ $(MAKE) -C $(tst_dir)/riscv_compliance clean
+ $(RM) -R $(root_dir)/build/*
+ $(RM) $(test_info)
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/README.md b/verilog/rtl/syntacore_scr1/README.md
new file mode 100644
index 0000000..0fb6648
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/README.md
@@ -0,0 +1,197 @@
+# SCR1 RISC-V Core
+
+SCR1 is an open-source and free to use RISC-V compatible MCU-class core, designed and maintained by Syntacore. It is industry-grade and silicon-proven (including full-wafer production), works out of the box in all major EDA flows and Verilator, and comes with extensive collateral and documentation.
+
+![SCR1 cluster](./docs/img/scr1_cluster.svg)
+
+## Key features
+
+* Open sourced under SHL-license (see LICENSE file) - unrestricted commercial use allowed
+* RV32I or RV32E ISA base + optional RVM and RVC standard extensions
+* Machine privilege mode only
+* 2 to 4 stage pipeline
+* Optional Integrated Programmable Interrupt Controller with 16 IRQ lines
+* Optional RISC-V Debug subsystem with JTAG interface
+* Optional on-chip Tightly-Coupled Memory
+* 32-bit AXI4/AHB-Lite external interface
+* Written in SystemVerilog
+* Optimized for area and power
+* 3 predefined recommended configurations
+* A number of fine-tuning options for custom configuration
+* Verification suite provided
+* Extensive documentation
+
+For more information on core architecture, see [SCR1 External Architecture Specification](https://github.com/syntacore/scr1/blob/master/docs/scr1_eas.pdf).
+
+For more information on project usage, see [SCR1 User Manual](https://github.com/syntacore/scr1/blob/master/docs/scr1_um.pdf).
+
+## Repository contents
+
+|Folder | Description
+|------ | -----------
+|**dependencies** | **Dependent submodules**
+|├─ riscv-tests | Common source files for RISC-V ISA tests
+|├─ riscv-compliance | Common source files for RISC-V Compliance tests
+|└─ coremark | Common source files for EEMBC's CoreMark® benchmark
+|**docs** | **SCR1 documentation**
+|├─ scr1_eas.pdf | SCR1 External Architecture Specification
+|└─ scr1_um.pdf | SCR1 User Manual
+|**sim** | **Tests and scripts for simulation**
+|├─ tests/common | Common source files for tests
+|├─ tests/riscv_isa | RISC-V ISA tests platform specific source files
+|├─ tests/riscv_compliance | RISC-V Compliance platform specific source files
+|├─ tests/benchmarks/dhrystone21 | Dhrystone 2.1 benchmark source files
+|├─ tests/benchmarks/coremark | EEMBC's CoreMark® benchmark platform specific source files
+|├─ tests/isr_sample | Sample program "Interrupt Service Routine"
+|├─ tests/hello | Sample program "Hello"
+|└─ verilator_wrap | Wrappers for Verilator simulation
+|**src** | **SCR1 RTL source and testbench files**
+|├─ includes | Header files
+|├─ core | Core top source files
+|├─ top | Cluster source files
+|└─ tb | Testbench files
+
+## SCR1 source file lists
+
+SCR1 source file lists of SCR1 can be found in [./src](https://github.com/syntacore/scr1/tree/master/src):
+
+* **core.files** - all synthesized file sources of the SCR1 core
+* **ahb_top.files** - synthesized file sources of AHB cluster
+* **axi_top.files** - synthesized file sources of AXI cluster
+* **ahb_tb.files** - testbench file sources for AHB cluster (for simulation only)
+* **axi_tb.files** - testbench file sources for AXI cluster (for simulation only)
+
+Library with header files to include is [./src/includes/](https://github.com/syntacore/scr1/tree/master/src/includes)
+
+## Simulation quick start guide
+
+The project contains testbenches, test sources and scripts to quickly start the SCR1 simulation. Before starting the simulation, make sure you have:
+
+* installed RISC-V GCC toolchain,
+* installed one of the supported simulators,
+* initialized submodules with test sources.
+
+### Requirements
+
+#### Operating system
+
+GCC toolchain and make-scripts are supported by most popular Linux-like operating systems.
+
+To run from Windows you can use an additional compatibility layer, such as WSL or Cygwin.
+
+#### RISC-V GCC toolchain
+
+RISC-V GCC toolchain is required to compile the software. You can use pre-built binaries or build the toolchain from scratch.
+
+##### Using pre-built binary tools
+
+Pre-built RISC-V GCC toolchain with support for all SCR1 architectural configurations is available for download from http://syntacore.com/page/products/sw-tools.
+
+1. Download the archive for your platform.
+2. Extract the archive to preferred directory `<GCC_INSTALL_PATH>`.
+3. Add the `<GCC_INSTALL_PATH>/bin` folder to the $PATH environment variable:
+```
+ export PATH=<GCC_INSTALL_PATH>/bin:$PATH
+```
+
+##### Building tools from source
+
+You can build the RISC-V GCC toolchain from sources, stored in official repo https://github.com/riscv/riscv-gnu-toolchain
+
+Instructions on how to prepare and build the toolchain can be found on https://github.com/riscv/riscv-gnu-toolchain/blob/master/README.md
+
+We recommend using the multilib compiler. Please note that RV32IC, RV32E, RV32EM, RV32EMC, RV32EC architectural configurations are not included in the compiler by default. If you plan to use them, you will need to include the appropriate libraries by yourself before building.
+
+After the building, be sure to add the `<GCC_INSTALL_PATH>/bin` folder to the $PATH environment variable
+
+
+#### HDL simulators
+
+Currently supported simulators:
+
+* Verilator (last verified version: v4.102)
+* Intel ModelSim (last verified version: INTEL FPGA STARTER EDITION vsim 2020.1_3)
+* Mentor Graphics ModelSim (last verified version: Modelsim PE Student Edition 10.4a)
+* Synopsys VCS (last verified version: vcs-mx_vL-2016.06)
+* Cadence NCSim
+
+Please note that RTL simulator executables should be in your $PATH variable.
+
+#### Tests preparation
+
+The simulation package includes the following tests:
+
+* **hello** - "Hello" sample program
+* **isr_sample** - "Interrupt Service Routine" sample program
+* **riscv_isa** - RISC-V ISA tests (submodule)
+* **riscv_compliance** - RISC-V Compliance tests (submodule)
+* **dhrystone21** - Dhrystone 2.1 benchmark
+* **coremark** - EEMBC's CoreMark® benchmark (submodule)
+
+After the main SCR1 repository has been cloned execute the following command:
+```
+ git submodule update --init --recursive
+```
+
+This command will initialized submodules with test sources.
+
+### Running simulation
+
+To build RTL, compile and run tests from the repo root folder you have to call Makefile.
+By default, you may simply call Makefile without any parameters:
+``` sh
+ make
+```
+
+In this case simulation will run on Verilator with following parameters: `CFG=MAX BUS=AHB TRACE=0 TARGETS="hello isr_sample riscv_isa riscv_compliance dhrystone21 coremark"`.
+
+Makefile supports:
+
+* choice of simulator - `run_<SIMULATOR> = <run_vcs, run_modelsim, run_ncsim, run_verilator, run_verilator_wf>`
+* selection of external interface - `BUS = <AHB, AXI>`,
+* configuration setup - `CFG = <MAX, BASE, MIN, CUSTOM>`,
+* parameters for CUSTOM configuration - `ARCH = <IMC, IC, IM, I, EMC, EM, EC, E>, VECT_IRQ = <0, 1>, IPIC = <0, 1>, TCM = <0, 1>`
+* tests subset to run - `TARGETS = <hello, isr_sample, riscv_isa, riscv_compliance, dhrystone21, coremark>`
+* enabling tracelog - `TRACE = <0, 1>`
+* and any additional options to pass to the simulator - `SIM_BUILD_OPTS`.
+
+Examples:
+``` sh
+ make run_verilator_wf CFG=MAX BUS=AXI TARGETS="riscv_isa riscv_compliance" TRACE=1
+ make run_vcs CFG=BASE BUS=AHB TARGETS="dhrystone21 coremark" SIM_BUILD_OPTS="-gui"
+ make run_modelsim CFG=CUSTOM BUS=AXI ARCH=I VECT_IRQ=1 IPIC=1 TCM=0 TARGETS=isr_sample
+```
+
+Build and run parameters can be configured in the `./Makefile`.
+
+After all the tests have finished, the results can be found in `build/<SIM_CFG>/test_results.txt`.
+
+**IMPORTANT:** To ensure correct rebuild, please clean build directory between simulation runs:
+``` sh
+ make clean
+```
+
+Please refer to the *"Simulation environment"* chapter of the [SCR1 User Manual](https://github.com/syntacore/scr1/blob/master/docs/scr1_um.pdf) for more information on setting up a simulation run.
+
+## SCR1 SDKs
+
+FPGA-based SDKs are available at the <https://github.com/syntacore/scr1-sdk>.
+
+Repo contains:
+
+* Pre-build images and open designs for several standard FPGAs boards:
+ * Digilent Arty (Xilinx)
+ * Digilent Nexys 4 DDR (Xilinx)
+ * Arria V GX Starter (Intel)
+ * Terasic DE10-Lite (Intel)
+* Software package:
+ * Bootloader
+ * Zephyr RTOS
+ * Tests\SW samples
+* User Guides for SDKs and tools
+
+## Contacts
+
+Report an issue: <https://github.com/syntacore/scr1/issues>
+
+Ask a question: scr1@syntacore.com
diff --git a/verilog/rtl/syntacore_scr1/docs/img/scr1_cluster.svg b/verilog/rtl/syntacore_scr1/docs/img/scr1_cluster.svg
new file mode 100644
index 0000000..15af238
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/docs/img/scr1_cluster.svg
@@ -0,0 +1,619 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Создано Microsoft Visio, экспорт SVG scr1_cluster.svg scr1_cluster -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
+ xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="5.73958in" height="5.11458in"
+ viewBox="0 0 413.25 368.25" xml:space="preserve" color-interpolation-filters="sRGB" class="st12">
+ <v:documentProperties v:langID="2057" v:viewMarkup="false"/>
+
+ <style type="text/css">
+ <![CDATA[
+ .st1 {fill:#dcedfa;stroke:#243740;stroke-linecap:butt;stroke-width:0.75}
+ .st2 {fill:#b1ddf0;stroke:#243740;stroke-linecap:butt;stroke-width:0.75}
+ .st3 {fill:#b0e3e6;stroke:#243740;stroke-linecap:butt;stroke-width:0.75}
+ .st4 {fill:none}
+ .st5 {stroke:#243740;stroke-linecap:butt;stroke-width:1.5}
+ .st6 {fill:#243740;stroke:#243740;stroke-linecap:butt;stroke-width:1.5}
+ .st7 {fill:none;stroke:none;stroke-linecap:butt;stroke-width:0.75}
+ .st8 {fill:#243740;font-family:Calibri;font-size:0.75em;font-weight:bold}
+ .st9 {fill:#243740;font-family:Calibri;font-size:0.833336em;font-weight:bold}
+ .st10 {fill:#0c0c0c;font-family:Calibri;font-size:0.833336em;font-weight:bold}
+ .st11 {font-size:1em}
+ .st12 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+ ]]>
+ </style>
+
+ <g v:mID="0" v:index="1" v:groupContext="foregroundPage">
+ <title>scr1_cluster</title>
+ <v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="19" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
+ <g id="shape2-1" v:mID="2" v:groupContext="shape" transform="translate(60.375,-30.375)">
+ <title>Лист.2</title>
+ <path d="M0 356.55 A11.7003 11.7003 -180 0 0 11.7 368.25 L280.8 368.25 A11.7003 11.7003 -180 0 0 292.5 356.55 L292.5
+ 42.45 A11.7003 11.7003 -180 0 0 280.8 30.75 L11.7 30.75 A11.7003 11.7003 -180 0 0 0 42.45 L0 356.55 Z"
+ class="st1"/>
+ </g>
+ <g id="shape3-3" v:mID="3" v:groupContext="shape" transform="translate(67.875,-210.375)">
+ <title>Лист.3</title>
+ <path d="M0 362.85 A5.40013 5.40013 -180 0 0 5.4 368.25 L272.1 368.25 A5.40013 5.40013 -180 0 0 277.5 362.85 L277.5 238.65
+ A5.40013 5.40013 -180 0 0 272.1 233.25 L5.4 233.25 A5.40013 5.40013 -180 0 0 0 238.65 L0 362.85 Z"
+ class="st2"/>
+ </g>
+ <g id="shape4-5" v:mID="4" v:groupContext="shape" transform="translate(75.375,-217.875)">
+ <title>Лист.4</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape5-7" v:mID="5" v:groupContext="shape" transform="translate(142.875,-217.875)">
+ <title>Лист.5</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape6-9" v:mID="6" v:groupContext="shape" transform="translate(210.375,-217.875)">
+ <title>Лист.6</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape7-11" v:mID="7" v:groupContext="shape" transform="translate(277.875,-217.875)">
+ <title>Лист.7</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape8-13" v:mID="8" v:groupContext="shape" transform="translate(142.875,-255.375)">
+ <title>Лист.8</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape9-15" v:mID="9" v:groupContext="shape" transform="translate(75.375,-255.375)">
+ <title>Лист.9</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape10-17" v:mID="10" v:groupContext="shape" transform="translate(210.375,-255.375)">
+ <title>Лист.10</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape11-19" v:mID="11" v:groupContext="shape" transform="translate(52.305,-307.635)">
+ <title>Лист.11</title>
+ <path d="M16.14 368.01 L8.07 368.01 L8.07 368.23 L0 368.25 L16.14 368.01 Z" class="st4"/>
+ <path d="M16.14 368.01 L8.07 368.01 L8.07 368.23 L0 368.25" class="st5"/>
+ </g>
+ <g id="shape12-22" v:mID="12" v:groupContext="shape" transform="translate(68.445,-305.25)">
+ <title>Лист.12</title>
+ <path d="M5.25 365.62 L0 368.25 L0 363 L5.25 365.62 Z" class="st6"/>
+ </g>
+ <g id="shape13-24" v:mID="13" v:groupContext="shape" transform="translate(47.055,-305.01)">
+ <title>Лист.13</title>
+ <path d="M0 365.63 L5.24 363 L5.25 368.25 L0 365.63 Z" class="st6"/>
+ </g>
+ <g id="shape14-26" v:mID="14" v:groupContext="shape" transform="translate(75.375,-292.875)">
+ <title>Лист.14</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 -0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape15-28" v:mID="15" v:groupContext="shape" transform="translate(277.875,-255.375)">
+ <title>Лист.15</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape16-30" v:mID="16" v:groupContext="shape" transform="translate(142.875,-292.875)">
+ <title>Лист.16</title>
+ <path d="M0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 -0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape17-32" v:mID="17" v:groupContext="shape" transform="translate(344.805,-307.635)">
+ <title>Лист.17</title>
+ <path d="M0 368.01 L8.07 368.01 L8.07 368.23 L16.14 368.25 L0 368.01 Z" class="st4"/>
+ <path d="M0 368.01 L8.07 368.01 L8.07 368.23 L16.14 368.25" class="st5"/>
+ </g>
+ <g id="shape18-35" v:mID="18" v:groupContext="shape" transform="translate(339.555,-305.25)">
+ <title>Лист.18</title>
+ <path d="M0 365.62 L5.25 363 L5.25 368.25 L0 365.62 Z" class="st6"/>
+ </g>
+ <g id="shape19-37" v:mID="19" v:groupContext="shape" transform="translate(360.945,-305.01)">
+ <title>Лист.19</title>
+ <path d="M5.25 365.63 L0 368.25 L0.01 363 L5.25 365.63 Z" class="st6"/>
+ </g>
+ <g id="shape20-39" v:mID="20" v:groupContext="shape" transform="translate(277.875,-292.875)">
+ <title>Лист.20</title>
+ <path d="M-0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 -0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape21-41" v:mID="21" v:groupContext="shape" transform="translate(210.375,-292.875)">
+ <title>Лист.21</title>
+ <path d="M-0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L55.5 368.25 A4.5001 4.5001 -180 0 0 60 363.75 L60 342.75 A4.5001
+ 4.5001 -180 0 0 55.5 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 -0 342.75 L0 363.75 Z" class="st3"/>
+ </g>
+ <g id="shape22-43" v:mID="22" v:groupContext="shape" transform="translate(150.375,-123.375)">
+ <title>Лист.22</title>
+ <path d="M0 360.37 A7.87518 7.87518 -180 0 0 7.87 368.25 L104.62 368.25 A7.87518 7.87518 -180 0 0 112.5 360.37 L112.5
+ 323.63 A7.87518 7.87518 -180 0 0 104.62 315.75 L7.87 315.75 A7.87518 7.87518 -180 0 0 0 323.63 L0 360.37
+ Z" class="st2"/>
+ </g>
+ <g id="shape23-45" v:mID="23" v:groupContext="shape" transform="translate(195.375,-85.875)">
+ <title>Лист.23</title>
+ <path d="M-0 363.75 A4.5001 4.5001 -180 0 0 4.5 368.25 L63 368.25 A4.5001 4.5001 -180 0 0 67.5 363.75 L67.5 342.75 A4.5001
+ 4.5001 -180 0 0 63 338.25 L4.5 338.25 A4.5001 4.5001 -180 0 0 -0 342.75 L0 363.75 Z" class="st2"/>
+ </g>
+ <g id="shape24-47" v:mID="24" v:groupContext="shape" transform="translate(120.375,-149.625)">
+ <title>Лист.24</title>
+ <path d="M0 359.43 L0 368.25 L23.07 368.25 L0 359.43 Z" class="st4"/>
+ <path d="M0 359.43 L0 368.25 L23.07 368.25" class="st5"/>
+ </g>
+ <g id="shape25-50" v:mID="25" v:groupContext="shape" transform="translate(117.75,-158.445)">
+ <title>Лист.25</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape26-52" v:mID="26" v:groupContext="shape" transform="translate(143.445,-147)">
+ <title>Лист.26</title>
+ <path d="M5.25 365.63 L0 368.25 L0 363 L5.25 365.63 Z" class="st6"/>
+ </g>
+ <g id="shape27-54" v:mID="27" v:groupContext="shape" transform="translate(105.375,-202.305)">
+ <title>Лист.27</title>
+ <path d="M0 368.25 L0 359.61 L0 368.25 Z" class="st4"/>
+ <path d="M0 368.25 L0 359.61" class="st5"/>
+ </g>
+ <g id="shape28-57" v:mID="28" v:groupContext="shape" transform="translate(102.75,-197.055)">
+ <title>Лист.28</title>
+ <path d="M2.63 368.25 L0 363 L5.25 363 L2.63 368.25 Z" class="st6"/>
+ </g>
+ <g id="shape29-59" v:mID="29" v:groupContext="shape" transform="translate(102.75,-210.945)">
+ <title>Лист.29</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape30-61" v:mID="30" v:groupContext="shape" transform="translate(75.375,-165.375)">
+ <title>Лист.30</title>
+ <path d="M0 368.25 L12 338.25 L48 338.25 L60 368.25 L0 368.25 Z" class="st2"/>
+ </g>
+ <g id="shape31-63" v:mID="31" v:groupContext="shape" transform="translate(269.805,-149.625)">
+ <title>Лист.31</title>
+ <path d="M23.07 359.43 L23.07 368.25 L0 368.25 L23.07 359.43 Z" class="st4"/>
+ <path d="M23.07 359.43 L23.07 368.25 L0 368.25" class="st5"/>
+ </g>
+ <g id="shape32-66" v:mID="32" v:groupContext="shape" transform="translate(290.25,-158.445)">
+ <title>Лист.32</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape33-68" v:mID="33" v:groupContext="shape" transform="translate(264.555,-147)">
+ <title>Лист.33</title>
+ <path d="M0 365.63 L5.25 363 L5.25 368.25 L0 365.63 Z" class="st6"/>
+ </g>
+ <g id="shape34-70" v:mID="34" v:groupContext="shape" transform="translate(277.875,-165.375)">
+ <title>Лист.34</title>
+ <path d="M0 368.25 L12 338.25 L48 338.25 L60 368.25 L0 368.25 Z" class="st2"/>
+ </g>
+ <g id="shape35-72" v:mID="35" v:groupContext="shape" transform="translate(307.875,-202.305)">
+ <title>Лист.35</title>
+ <path d="M0 359.61 L0 368.25 L0 359.61 Z" class="st4"/>
+ <path d="M0 359.61 L0 368.25" class="st5"/>
+ </g>
+ <g id="shape36-75" v:mID="36" v:groupContext="shape" transform="translate(305.25,-210.945)">
+ <title>Лист.36</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape37-77" v:mID="37" v:groupContext="shape" transform="translate(305.25,-197.055)">
+ <title>Лист.37</title>
+ <path d="M2.63 368.25 L0 363 L5.25 363 L2.63 368.25 Z" class="st6"/>
+ </g>
+ <g id="shape38-79" v:mID="38" v:groupContext="shape" transform="translate(269.805,-100.875)">
+ <title>Лист.38</title>
+ <path d="M0 368.25 L38.07 368.25 L38.07 310.68 L0 368.25 Z" class="st4"/>
+ <path d="M0 368.25 L38.07 368.25 L38.07 310.68" class="st5"/>
+ </g>
+ <g id="shape39-82" v:mID="39" v:groupContext="shape" transform="translate(264.555,-98.25)">
+ <title>Лист.39</title>
+ <path d="M0 365.62 L5.25 363 L5.25 368.25 L0 365.62 Z" class="st6"/>
+ </g>
+ <g id="shape40-84" v:mID="40" v:groupContext="shape" transform="translate(305.25,-158.445)">
+ <title>Лист.40</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape41-86" v:mID="41" v:groupContext="shape" transform="translate(90.375,-89.805)">
+ <title>Лист.41</title>
+ <path d="M0 368.25 L0 299.61 L0 368.25 Z" class="st4"/>
+ <path d="M0 368.25 L0 299.61" class="st5"/>
+ </g>
+ <g id="shape42-89" v:mID="42" v:groupContext="shape" transform="translate(87.75,-84.555)">
+ <title>Лист.42</title>
+ <path d="M2.63 368.25 L0 363 L5.25 363 L2.63 368.25 Z" class="st6"/>
+ </g>
+ <g id="shape43-91" v:mID="43" v:groupContext="shape" transform="translate(87.75,-158.445)">
+ <title>Лист.43</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape44-93" v:mID="44" v:groupContext="shape" transform="translate(75.375,-45.375)">
+ <title>Лист.44</title>
+ <path d="M0 362.62 A5.62513 5.62513 -180 0 0 5.63 368.25 L54.38 368.25 A5.62513 5.62513 -180 0 0 60 362.62 L60 336.38
+ A5.62513 5.62513 -180 0 0 54.38 330.75 L5.62 330.75 A5.62513 5.62513 -180 0 0 0 336.38 L0 362.62 Z"
+ class="st2"/>
+ </g>
+ <g id="shape45-95" v:mID="45" v:groupContext="shape" transform="translate(277.875,-45.375)">
+ <title>Лист.45</title>
+ <path d="M0 362.62 A5.62513 5.62513 -180 0 0 5.63 368.25 L54.38 368.25 A5.62513 5.62513 -180 0 0 60 362.62 L60 336.38
+ A5.62513 5.62513 -180 0 0 54.38 330.75 L5.62 330.75 A5.62513 5.62513 -180 0 0 0 336.38 L0 362.62 Z"
+ class="st2"/>
+ </g>
+ <g id="shape46-97" v:mID="46" v:groupContext="shape" transform="translate(322.875,-89.805)">
+ <title>Лист.46</title>
+ <path d="M0 299.61 L0 368.25 L0 299.61 Z" class="st4"/>
+ <path d="M0 299.61 L0 368.25" class="st5"/>
+ </g>
+ <g id="shape47-100" v:mID="47" v:groupContext="shape" transform="translate(320.25,-158.445)">
+ <title>Лист.47</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape48-102" v:mID="48" v:groupContext="shape" transform="translate(320.25,-84.555)">
+ <title>Лист.48</title>
+ <path d="M2.63 368.25 L0 363 L5.25 363 L2.63 368.25 Z" class="st6"/>
+ </g>
+ <g id="shape49-104" v:mID="49" v:groupContext="shape" transform="translate(367.875,-300.375)">
+ <title>Лист.49</title>
+ <rect x="0" y="353.25" width="45" height="15" class="st7"/>
+ </g>
+ <g id="shape50-106" v:mID="50" v:groupContext="shape" transform="translate(354.35,-302.925)">
+ <title>Лист.50</title>
+ <desc>JTAG I/F</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="36.025" cy="362.85" width="72.06" height="10.8"/>
+ <rect x="0" y="357.45" width="72.05" height="10.8" class="st7"/>
+ <text x="20.5" y="365.55" class="st8" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>JTAG I/F</text> </g>
+ <g id="shape51-109" v:mID="51" v:groupContext="shape" transform="translate(0.375,-300.375)">
+ <title>Лист.51</title>
+ <rect x="0" y="353.25" width="45" height="15" class="st7"/>
+ </g>
+ <g id="shape52-111" v:mID="52" v:groupContext="shape" transform="translate(-8.65,-302.925)">
+ <title>Лист.52</title>
+ <desc>IRQ I/F</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="31.525" cy="362.85" width="63.05" height="10.8"/>
+ <rect x="0" y="357.45" width="63.05" height="10.8" class="st7"/>
+ <text x="18.49" y="365.55" class="st8" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>IRQ I/F</text> </g>
+ <g id="shape53-114" v:mID="53" v:groupContext="shape" transform="translate(67.875,-0.375)">
+ <title>Лист.53</title>
+ <rect x="0" y="353.25" width="75" height="15" class="st7"/>
+ </g>
+ <g id="shape54-116" v:mID="54" v:groupContext="shape" transform="translate(55.85,-2.925)">
+ <title>Лист.54</title>
+ <desc>AHB/AXI I/F</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="49.525" cy="362.85" width="99.05" height="10.8"/>
+ <rect x="0" y="357.45" width="99.05" height="10.8" class="st7"/>
+ <text x="24.37" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>AHB/AXI I/F</text> </g>
+ <g id="shape55-119" v:mID="55" v:groupContext="shape" transform="translate(105.375,-22.305)">
+ <title>Лист.55</title>
+ <path d="M0 352.11 L0 368.25 L0 352.11 Z" class="st4"/>
+ <path d="M0 352.11 L0 368.25" class="st5"/>
+ </g>
+ <g id="shape56-122" v:mID="56" v:groupContext="shape" transform="translate(102.75,-38.445)">
+ <title>Лист.56</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape57-124" v:mID="57" v:groupContext="shape" transform="translate(102.75,-17.055)">
+ <title>Лист.57</title>
+ <path d="M2.63 368.25 L0 363 L5.25 363 L2.63 368.25 Z" class="st6"/>
+ </g>
+ <g id="shape58-126" v:mID="58" v:groupContext="shape" transform="translate(270.375,-0.375)">
+ <title>Лист.58</title>
+ <rect x="0" y="353.25" width="75" height="15" class="st7"/>
+ </g>
+ <g id="shape59-128" v:mID="59" v:groupContext="shape" transform="translate(258.35,-2.925)">
+ <title>Лист.59</title>
+ <desc>AHB/AXI I/F</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="49.525" cy="362.85" width="99.06" height="10.8"/>
+ <rect x="0" y="357.45" width="99.05" height="10.8" class="st7"/>
+ <text x="24.37" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>AHB/AXI I/F</text> </g>
+ <g id="shape60-131" v:mID="60" v:groupContext="shape" transform="translate(307.875,-22.305)">
+ <title>Лист.60</title>
+ <path d="M0 352.11 L0 368.25 L0 352.11 Z" class="st4"/>
+ <path d="M0 352.11 L0 368.25" class="st5"/>
+ </g>
+ <g id="shape61-134" v:mID="61" v:groupContext="shape" transform="translate(305.25,-38.445)">
+ <title>Лист.61</title>
+ <path d="M2.63 363 L5.25 368.25 L0 368.25 L2.63 363 Z" class="st6"/>
+ </g>
+ <g id="shape62-136" v:mID="62" v:groupContext="shape" transform="translate(305.25,-17.055)">
+ <title>Лист.62</title>
+ <path d="M2.63 368.25 L0 363 L5.25 363 L2.63 368.25 Z" class="st6"/>
+ </g>
+ <g id="shape63-138" v:mID="63" v:groupContext="shape" transform="translate(67.875,-349.125)">
+ <title>Лист.63</title>
+ <rect x="0" y="353.25" width="82.5" height="15" class="st7"/>
+ </g>
+ <g id="shape64-140" v:mID="64" v:groupContext="shape" transform="translate(82.675,-351.45)">
+ <title>Лист.64</title>
+ <desc>SCR1 cluster</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="43.325" cy="362.85" width="86.65" height="10.8"/>
+ <rect x="0" y="357.45" width="86.65" height="10.8" class="st7"/>
+ <text x="0" y="365.85" class="st10" v:langID="2057"><v:paragraph/><v:tabList/>SCR1 cluster</text> </g>
+ <g id="shape65-143" v:mID="65" v:groupContext="shape" transform="translate(75.375,-326.625)">
+ <title>Лист.65</title>
+ <rect x="0" y="353.25" width="75" height="15" class="st7"/>
+ </g>
+ <g id="shape66-145" v:mID="66" v:groupContext="shape" transform="translate(76.85,-329.175)">
+ <title>Лист.66</title>
+ <desc>SCR1 core</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="0" y="365.85" class="st10" v:langID="2057"><v:paragraph/><v:tabList/>SCR1 core</text> </g>
+ <g id="shape67-148" v:mID="67" v:groupContext="shape" transform="translate(90.375,-300.375)">
+ <title>Лист.67</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape68-150" v:mID="68" v:groupContext="shape" transform="translate(64.125,-301.95)">
+ <title>Лист.68</title>
+ <desc>Interrupt Controller</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.05" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="23.5" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Interrupt <v:lf/><tspan
+ x="21.65" dy="1.2em" class="st11">Controller</tspan></text> </g>
+ <g id="shape69-154" v:mID="69" v:groupContext="shape" transform="translate(157.875,-300.375)">
+ <title>Лист.69</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape70-156" v:mID="70" v:groupContext="shape" transform="translate(132.35,-302.925)">
+ <title>Лист.70</title>
+ <desc>System Control Unit</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="26.99" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>System <v:lf/><tspan
+ x="17.59" dy="1.2em" class="st11">Control Unit</tspan></text> </g>
+ <g id="shape71-160" v:mID="71" v:groupContext="shape" transform="translate(225.375,-300.375)">
+ <title>Лист.71</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape72-162" v:mID="72" v:groupContext="shape" transform="translate(204.35,-302.925)">
+ <title>Лист.72</title>
+ <desc>Debug Module</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="36.025" cy="362.85" width="72.06" height="10.8"/>
+ <rect x="0" y="357.45" width="72.05" height="10.8" class="st7"/>
+ <text x="23.96" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Debug <v:lf/><tspan
+ x="21.47" dy="1.2em" class="st11">Module</tspan></text> </g>
+ <g id="shape73-166" v:mID="73" v:groupContext="shape" transform="translate(292.875,-300.375)">
+ <title>Лист.73</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape74-168" v:mID="74" v:groupContext="shape" transform="translate(267.35,-302.925)">
+ <title>Лист.74</title>
+ <desc>TAP Controller</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="33.18" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>TAP<v:lf/><tspan
+ x="21.65" dy="1.2em" class="st11">Controller</tspan></text> </g>
+ <g id="shape75-172" v:mID="75" v:groupContext="shape" transform="translate(90.375,-262.875)">
+ <title>Лист.75</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape76-174" v:mID="76" v:groupContext="shape" transform="translate(64.85,-265.425)">
+ <title>Лист.76</title>
+ <desc>Control-Status Register File</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.05" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="13.57" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Control-Status <v:lf/><tspan
+ x="17.71" dy="1.2em" class="st11">Register File</tspan></text> </g>
+ <g id="shape77-178" v:mID="77" v:groupContext="shape" transform="translate(191.625,-142.125)">
+ <title>Лист.77</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape78-180" v:mID="78" v:groupContext="shape" transform="translate(162,-144)">
+ <title>Лист.78</title>
+ <desc>Tightly-Coupled Memory</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="45" cy="362.85" width="90" height="10.8"/>
+ <rect x="0" y="357.45" width="90" height="10.8" class="st7"/>
+ <text x="12.25" y="359.85" class="st9" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Tightly-Coupled <tspan
+ x="27.21" dy="1.2em" class="st11">Memory</tspan></text> </g>
+ <g id="shape79-184" v:mID="79" v:groupContext="shape" transform="translate(214.125,-93.375)">
+ <title>Лист.79</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape80-186" v:mID="80" v:groupContext="shape" transform="translate(206.6,-95.925)">
+ <title>Лист.80</title>
+ <desc>Timer</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="22.525" cy="362.85" width="45.05" height="10.8"/>
+ <rect x="0" y="357.45" width="45.05" height="10.8" class="st7"/>
+ <text x="10.46" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>Timer</text> </g>
+ <g id="shape81-189" v:mID="81" v:groupContext="shape" transform="translate(157.875,-225.375)">
+ <title>Лист.81</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape82-191" v:mID="82" v:groupContext="shape" transform="translate(132.35,-227.925)">
+ <title>Лист.82</title>
+ <desc>Instruction Decode Unit</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="20.16" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Instruction <v:lf/><tspan
+ x="17.41" dy="1.2em" class="st11">Decode Unit</tspan></text> </g>
+ <g id="shape83-195" v:mID="83" v:groupContext="shape" transform="translate(225.375,-225.375)">
+ <title>Лист.83</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape84-197" v:mID="84" v:groupContext="shape" transform="translate(199.85,-227.925)">
+ <title>Лист.84</title>
+ <desc>Execution Unit</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="22.2" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Execution <v:lf/><tspan
+ x="32.51" dy="1.2em" class="st11">Unit</tspan></text> </g>
+ <g id="shape85-201" v:mID="85" v:groupContext="shape" transform="translate(292.875,-225.375)">
+ <title>Лист.85</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape86-203" v:mID="86" v:groupContext="shape" transform="translate(267.35,-227.925)">
+ <title>Лист.86</title>
+ <desc>Load-Store Unit</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="20.22" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Load-Store <v:lf/><tspan
+ x="32.51" dy="1.2em" class="st11">Unit</tspan></text> </g>
+ <g id="shape87-207" v:mID="87" v:groupContext="shape" transform="translate(225.375,-262.875)">
+ <title>Лист.87</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape88-209" v:mID="88" v:groupContext="shape" transform="translate(199.85,-265.425)">
+ <title>Лист.88</title>
+ <desc>Trigger Debug Unit</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="27.46" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Trigger <v:lf/><tspan
+ x="19.42" dy="1.2em" class="st11">Debug Unit</tspan></text> </g>
+ <g id="shape89-213" v:mID="89" v:groupContext="shape" transform="translate(90.375,-67.875)">
+ <title>Лист.89</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape90-215" v:mID="90" v:groupContext="shape" transform="translate(87.35,-66.675)">
+ <title>Лист.90</title>
+ <desc>IMEM</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="18.025" cy="362.85" width="36.05" height="10.8"/>
+ <rect x="0" y="357.45" width="36.05" height="10.8" class="st7"/>
+ <text x="5.51" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>IMEM</text> </g>
+ <g id="shape91-218" v:mID="91" v:groupContext="shape" transform="translate(90.375,-58.875)">
+ <title>Лист.91</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape92-220" v:mID="92" v:groupContext="shape" transform="translate(73.85,-57.675)">
+ <title>Лист.92</title>
+ <desc>AHB/AXI</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="31.525" cy="362.85" width="63.05" height="10.8"/>
+ <rect x="0" y="357.45" width="63.05" height="10.8" class="st7"/>
+ <text x="13.27" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>AHB/AXI</text> </g>
+ <g id="shape93-223" v:mID="93" v:groupContext="shape" transform="translate(90.375,-49.875)">
+ <title>Лист.93</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape94-225" v:mID="94" v:groupContext="shape" transform="translate(78.35,-48.675)">
+ <title>Лист.94</title>
+ <desc>bridge</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="27.025" cy="362.85" width="54.05" height="10.8"/>
+ <rect x="0" y="357.45" width="54.05" height="10.8" class="st7"/>
+ <text x="13.77" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>bridge</text> </g>
+ <g id="shape95-228" v:mID="95" v:groupContext="shape" transform="translate(292.875,-67.875)">
+ <title>Лист.95</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape96-230" v:mID="96" v:groupContext="shape" transform="translate(289.85,-66.675)">
+ <title>Лист.96</title>
+ <desc>DMEM</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="18.025" cy="362.85" width="36.05" height="10.8"/>
+ <rect x="0" y="357.45" width="36.05" height="10.8" class="st7"/>
+ <text x="3.69" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>DMEM</text> </g>
+ <g id="shape97-233" v:mID="97" v:groupContext="shape" transform="translate(292.875,-58.875)">
+ <title>Лист.97</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape98-235" v:mID="98" v:groupContext="shape" transform="translate(276.35,-57.675)">
+ <title>Лист.98</title>
+ <desc>AHB/AXI</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="31.525" cy="362.85" width="63.05" height="10.8"/>
+ <rect x="0" y="357.45" width="63.05" height="10.8" class="st7"/>
+ <text x="13.27" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>AHB/AXI</text> </g>
+ <g id="shape99-238" v:mID="99" v:groupContext="shape" transform="translate(292.875,-49.875)">
+ <title>Лист.99</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape100-240" v:mID="100" v:groupContext="shape" transform="translate(280.85,-48.675)">
+ <title>Лист.100</title>
+ <desc>bridge</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="27.025" cy="362.85" width="54.05" height="10.8"/>
+ <rect x="0" y="357.45" width="54.05" height="10.8" class="st7"/>
+ <text x="13.77" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>bridge</text> </g>
+ <g id="shape101-243" v:mID="101" v:groupContext="shape" transform="translate(90.375,-180.375)">
+ <title>Лист.101</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape102-245" v:mID="102" v:groupContext="shape" transform="translate(87.35,-179.175)">
+ <title>Лист.102</title>
+ <desc>IMEM</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="18.025" cy="362.85" width="36.05" height="10.8"/>
+ <rect x="0" y="357.45" width="36.05" height="10.8" class="st7"/>
+ <text x="5.51" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>IMEM</text> </g>
+ <g id="shape103-248" v:mID="103" v:groupContext="shape" transform="translate(90.375,-171.375)">
+ <title>Лист.103</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape104-250" v:mID="104" v:groupContext="shape" transform="translate(78.35,-170.175)">
+ <title>Лист.104</title>
+ <desc>router</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="27.025" cy="362.85" width="54.05" height="10.8"/>
+ <rect x="0" y="357.45" width="54.05" height="10.8" class="st7"/>
+ <text x="13.85" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>router</text> </g>
+ <g id="shape105-253" v:mID="105" v:groupContext="shape" transform="translate(292.875,-180.375)">
+ <title>Лист.105</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape106-255" v:mID="106" v:groupContext="shape" transform="translate(289.85,-179.175)">
+ <title>Лист.106</title>
+ <desc>DMEM</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="18.025" cy="362.85" width="36.05" height="10.8"/>
+ <rect x="0" y="357.45" width="36.05" height="10.8" class="st7"/>
+ <text x="3.69" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>DMEM</text> </g>
+ <g id="shape107-258" v:mID="107" v:groupContext="shape" transform="translate(292.875,-171.375)">
+ <title>Лист.107</title>
+ <rect x="0" y="360.75" width="30" height="7.5" class="st7"/>
+ </g>
+ <g id="shape108-260" v:mID="108" v:groupContext="shape" transform="translate(280.85,-170.175)">
+ <title>Лист.108</title>
+ <desc>router</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="27.025" cy="362.85" width="54.05" height="10.8"/>
+ <rect x="0" y="357.45" width="54.05" height="10.8" class="st7"/>
+ <text x="13.85" y="365.85" class="st9" v:langID="2057"><v:paragraph v:horizAlign="1"/><v:tabList/>router</text> </g>
+ <g id="shape109-263" v:mID="109" v:groupContext="shape" transform="translate(157.875,-262.875)">
+ <title>Лист.109</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape110-265" v:mID="110" v:groupContext="shape" transform="translate(132.35,-265.425)">
+ <title>Лист.110</title>
+ <desc>Multi-Port Register File</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="21.06" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Multi-Port <v:lf/><tspan
+ x="17.71" dy="1.2em" class="st11">Register File</tspan></text> </g>
+ <g id="shape111-269" v:mID="111" v:groupContext="shape" transform="translate(292.875,-262.875)">
+ <title>Лист.111</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape112-271" v:mID="112" v:groupContext="shape" transform="translate(267.35,-265.425)">
+ <title>Лист.112</title>
+ <desc>Hart Debug Unit</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.06" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="32.31" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hart <v:lf/><tspan
+ x="19.42" dy="1.2em" class="st11">Debug Unit</tspan></text> </g>
+ <g id="shape113-275" v:mID="113" v:groupContext="shape" transform="translate(90.375,-225.375)">
+ <title>Лист.113</title>
+ <rect x="0" y="353.25" width="30" height="15" class="st7"/>
+ </g>
+ <g id="shape114-277" v:mID="114" v:groupContext="shape" transform="translate(64.85,-227.925)">
+ <title>Лист.114</title>
+ <desc>Instruction Fetch Unit</desc>
+ <v:textBlock v:margins="rect(0,0,0,0)"/>
+ <v:textRect cx="40.525" cy="362.85" width="81.05" height="10.8"/>
+ <rect x="0" y="357.45" width="81.05" height="10.8" class="st7"/>
+ <text x="20.16" y="360.15" class="st8" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Instruction<v:newlineChar/><tspan
+ x="21.3" dy="1.2em" class="st11">Fetch Unit</tspan></text> </g>
+ </g>
+</svg>
diff --git a/verilog/rtl/syntacore_scr1/docs/scr1_eas.pdf b/verilog/rtl/syntacore_scr1/docs/scr1_eas.pdf
new file mode 100644
index 0000000..e436e1c
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/docs/scr1_eas.pdf
Binary files differ
diff --git a/verilog/rtl/syntacore_scr1/docs/scr1_um.pdf b/verilog/rtl/syntacore_scr1/docs/scr1_um.pdf
new file mode 100644
index 0000000..07a69d1
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/docs/scr1_um.pdf
Binary files differ
diff --git a/verilog/rtl/syntacore_scr1/src/ahb_top.files b/verilog/rtl/syntacore_scr1/src/ahb_top.files
new file mode 100644
index 0000000..603839e
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/ahb_top.files
@@ -0,0 +1,8 @@
+top/scr1_dmem_router.sv
+top/scr1_imem_router.sv
+top/scr1_dp_memory.sv
+top/scr1_tcm.sv
+top/scr1_timer.sv
+top/scr1_dmem_ahb.sv
+top/scr1_imem_ahb.sv
+top/scr1_top_ahb.sv
diff --git a/verilog/rtl/syntacore_scr1/src/axi_tb.files b/verilog/rtl/syntacore_scr1/src/axi_tb.files
new file mode 100644
index 0000000..383dc9b
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/axi_tb.files
@@ -0,0 +1,3 @@
+core/pipeline/scr1_tracelog.sv
+tb/scr1_memory_tb_axi.sv
+tb/scr1_top_tb_axi.sv
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/src/axi_top.files b/verilog/rtl/syntacore_scr1/src/axi_top.files
new file mode 100644
index 0000000..24f4b8e
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/axi_top.files
@@ -0,0 +1,7 @@
+top/scr1_dmem_router.sv
+top/scr1_imem_router.sv
+top/scr1_dp_memory.sv
+top/scr1_tcm.sv
+top/scr1_timer.sv
+top/scr1_mem_axi.sv
+top/scr1_top_axi.sv
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/src/core.files b/verilog/rtl/syntacore_scr1/src/core.files
new file mode 100644
index 0000000..ca5de45
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core.files
@@ -0,0 +1,21 @@
+core/pipeline/scr1_pipe_hdu.sv
+core/pipeline/scr1_pipe_tdu.sv
+core/pipeline/scr1_ipic.sv
+core/pipeline/scr1_pipe_csr.sv
+core/pipeline/scr1_pipe_exu.sv
+core/pipeline/scr1_pipe_ialu.sv
+core/pipeline/scr1_pipe_idu.sv
+core/pipeline/scr1_pipe_ifu.sv
+core/pipeline/scr1_pipe_lsu.sv
+core/pipeline/scr1_pipe_mprf.sv
+core/pipeline/scr1_pipe_top.sv
+core/primitives/scr1_reset_cells.sv
+core/primitives/scr1_cg.sv
+core/scr1_clk_ctrl.sv
+core/scr1_tapc_shift_reg.sv
+core/scr1_tapc.sv
+core/scr1_tapc_synchronizer.sv
+core/scr1_core_top.sv
+core/scr1_dm.sv
+core/scr1_dmi.sv
+core/scr1_scu.sv
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_ipic.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_ipic.sv
new file mode 100644
index 0000000..312dc4c
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_ipic.sv
@@ -0,0 +1,605 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_ipic.sv>
+/// @brief Integrated Programmable Interrupt Controller (IPIC)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Synchronizes IRQ lines (optional)
+ // - Detects level and edge (with optional lines inversion) of IRQ lines
+ // - Setups interrupts handling (mode, inversion, enable)
+ // - Provides information about pending interrupts and interrupts currently in
+ // service
+ // - Generates interrupt request to CSR
+ //
+ // Structure:
+ // - IRQ lines handling (synchronization, level and edge detection) logic
+ // - IPIC registers:
+ // - CISV
+ // - CICSR
+ // - EOI
+ // - SOI
+ // - IDX
+ // - IPR
+ // - ISVR
+ // - IER
+ // - IMR
+ // - IINVR
+ // - ICSR
+ // - Priority interrupt generation logic
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_IPIC_EN
+
+`include "scr1_ipic.svh"
+
+module scr1_ipic
+(
+ // Common
+ input logic rst_n, // IPIC reset
+ input logic clk, // IPIC clock
+
+ // External Interrupt lines
+ input logic [SCR1_IRQ_LINES_NUM-1:0] soc2ipic_irq_lines_i, // External IRQ lines
+
+ // CSR <-> IPIC interface
+ input logic csr2ipic_r_req_i, // IPIC read request
+ input logic csr2ipic_w_req_i, // IPIC write request
+ input logic [2:0] csr2ipic_addr_i, // IPIC address
+ input logic [`SCR1_XLEN-1:0] csr2ipic_wdata_i, // IPIC write data
+ output logic [`SCR1_XLEN-1:0] ipic2csr_rdata_o, // IPIC read data
+ output logic ipic2csr_irq_m_req_o // IRQ request from IPIC
+);
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+typedef struct {
+ logic vd;
+ logic idx;
+} type_scr1_search_one_2_s;
+
+typedef struct {
+ logic vd;
+ logic [SCR1_IRQ_VECT_WIDTH-1:0] idx;
+} type_scr1_search_one_16_s;
+
+typedef struct packed {
+ logic ip;
+ logic ie;
+ logic im;
+ logic inv;
+ logic is;
+ logic [SCR1_IRQ_LINES_WIDTH-1:0] line;
+} type_scr1_icsr_m_s;
+
+typedef struct packed {
+ logic ip;
+ logic ie;
+} type_scr1_cicsr_s;
+
+//-------------------------------------------------------------------------------
+// Local functions declaration
+//-------------------------------------------------------------------------------
+
+function automatic type_scr1_search_one_2_s scr1_search_one_2(
+ input logic [1:0] din
+);
+ type_scr1_search_one_2_s tmp;
+begin
+ tmp.vd = |din;
+ tmp.idx = ~din[0];
+ return tmp;
+end
+endfunction : scr1_search_one_2
+
+function automatic type_scr1_search_one_16_s scr1_search_one_16(
+ input logic [15:0] din
+);
+begin
+ logic [7:0] stage1_vd;
+ logic [3:0] stage2_vd;
+ logic [1:0] stage3_vd;
+
+ logic stage1_idx [7:0];
+ logic [1:0] stage2_idx [3:0];
+ logic [2:0] stage3_idx [1:0];
+ type_scr1_search_one_16_s result;
+
+ // Stage 1
+ for (int unsigned i=0; i<8; ++i) begin
+ type_scr1_search_one_2_s tmp;
+ tmp = scr1_search_one_2(din[(i+1)*2-1-:2]);
+ stage1_vd[i] = tmp.vd;
+ stage1_idx[i] = tmp.idx;
+ end
+
+ // Stage 2
+ for (int unsigned i=0; i<4; ++i) begin
+ type_scr1_search_one_2_s tmp;
+ tmp = scr1_search_one_2(stage1_vd[(i+1)*2-1-:2]);
+ stage2_vd[i] = tmp.vd;
+ stage2_idx[i] = (~tmp.idx) ? {tmp.idx, stage1_idx[2*i]} : {tmp.idx, stage1_idx[2*i+1]};
+ end
+
+ // Stage 3
+ for (int unsigned i=0; i<2; ++i) begin
+ type_scr1_search_one_2_s tmp;
+ tmp = scr1_search_one_2(stage2_vd[(i+1)*2-1-:2]);
+ stage3_vd[i] = tmp.vd;
+ stage3_idx[i] = (~tmp.idx) ? {tmp.idx, stage2_idx[2*i]} : {tmp.idx, stage2_idx[2*i+1]};
+ end
+
+ // Stage 4
+ result.vd = |stage3_vd;
+ result.idx = (stage3_vd[0]) ? {1'b0, stage3_idx[0]} : {1'b1, stage3_idx[1]};
+
+ return result;
+end
+endfunction : scr1_search_one_16
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// IRQ lines handling signals
+//------------------------------------------------------------------------------
+
+logic [SCR1_IRQ_VECT_NUM-1:0] irq_lines; // Internal IRQ lines
+`ifdef SCR1_IPIC_SYNC_EN
+logic [SCR1_IRQ_VECT_NUM-1:0] irq_lines_sync;
+`endif // SCR1_IPIC_SYNC_EN
+logic [SCR1_IRQ_VECT_NUM-1:0] irq_lines_dly; // Internal IRQ lines delayed for 1 cycle
+logic [SCR1_IRQ_VECT_NUM-1:0] irq_edge_detected; // IRQ lines edge detected flags
+logic [SCR1_IRQ_VECT_NUM-1:0] irq_lvl; // IRQ lines level
+
+// IPIC registers
+//------------------------------------------------------------------------------
+
+// CISV register
+logic ipic_cisv_upd; // Current Interrupt Vecotr in Service register update
+logic [SCR1_IRQ_VECT_WIDTH-1:0] ipic_cisv_ff; // Current Interrupt Vector in Service register
+logic [SCR1_IRQ_VECT_WIDTH-1:0] ipic_cisv_next; // Current Interrupt Vector in Service register next value
+
+// CICS register (CICSR)
+logic cicsr_wr_req; // Write request to Current Interrupt Control Status register
+type_scr1_cicsr_s ipic_cicsr; // Current Interrupt Control Status register
+
+// EOI register
+logic eoi_wr_req; // Write request to End of Interrupt register
+logic ipic_eoi_req; // Request to end the interrupt that is currently in service
+
+// SOI register
+logic soi_wr_req; // Write request to Start of Interrupt register
+logic ipic_soi_req; // Request to start the interrupt
+
+// IDX register (IDXR)
+logic idxr_wr_req; // Write request to Index register
+logic [SCR1_IRQ_IDX_WIDTH-1:0] ipic_idxr_ff; // Index register
+
+// IP register (IPR)
+logic ipic_ipr_upd; // Interrupt pending register update
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_ff; // Interrupt pending register
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_next; // Interrupt pending register next value
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_clr_cond; // Interrupt pending clear condition
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_clr_req; // Interrupt pending clear request
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_clr; // Interrupt pending clear operation
+
+// ISV register (ISVR)
+logic ipic_isvr_upd; // Interrupt Serviced register update
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_isvr_ff; // Interrupt Serviced register
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_isvr_next; // Interrupt Serviced register next value
+
+// IE register (IER)
+logic ipic_ier_upd; // Interrupt enable register update
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ier_ff; // Interrupt enable register
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ier_next; // Interrupt enable register next value
+
+// IM register (IMR)
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_imr_ff; // Interrupt mode register
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_imr_next; // Interrupt mode register next value
+
+// IINV register (IINVR)
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_iinvr_ff; // Interrupt Inversion register
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_iinvr_next; // Interrupt Inversion register next value
+
+// ICS register (ICSR)
+logic icsr_wr_req; // Write request to Interrupt Control Status register
+type_scr1_icsr_m_s ipic_icsr; // Interrupt Control Status register
+
+// Priority interrupt generation signals
+//------------------------------------------------------------------------------
+
+// Serviced interrupt signals
+logic irq_serv_vd; // There is an interrupt in service
+logic [SCR1_IRQ_VECT_WIDTH-1:0] irq_serv_idx; // Index of an interrupt that is currently in service
+
+// Requested interrupt signals
+logic irq_req_vd; // There is a requested interrupt
+logic [SCR1_IRQ_VECT_WIDTH-1:0] irq_req_idx; // Index of a requested interrupt
+
+// Interrupt requested on "end of the previous interrupt" signals
+logic irq_eoi_req_vd; // There is a requested interrupt when the previous one has ended
+logic [SCR1_IRQ_VECT_WIDTH-1:0] irq_eoi_req_idx; // Index of an interrupt requested when the previous one has ended
+
+logic [SCR1_IRQ_VECT_NUM-1:0] irq_req_v; // Vector of interrupts that are pending and enabled
+
+logic irq_start_vd; // Request to start an interrupt is valid
+logic irq_hi_prior_pnd; // There is a pending IRQ with a priority higher than of the interrupt that is currently in service
+
+type_scr1_search_one_16_s irr_priority; // Structure for vd and idx of the requested interrupt
+type_scr1_search_one_16_s isvr_priority_eoi; // Structure for vd and idx of the interrupt requested when the previous interrupt has ended
+logic [SCR1_IRQ_VECT_NUM-1:0] ipic_isvr_eoi; // Interrupt Serviced register when the previous interrupt has ended
+
+//------------------------------------------------------------------------------
+// IRQ lines handling
+//------------------------------------------------------------------------------
+
+`ifdef SCR1_IPIC_SYNC_EN
+// IRQ lines synchronization
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ irq_lines_sync <= '0;
+ irq_lines <= '0;
+ end else begin
+ irq_lines_sync <= soc2ipic_irq_lines_i;
+ irq_lines <= irq_lines_sync;
+ end
+end
+`else // SCR1_IPIC_SYNC_EN
+assign irq_lines = soc2ipic_irq_lines_i;
+`endif // SCR1_IPIC_SYNC_EN
+
+// IRQ lines level detection
+//------------------------------------------------------------------------------
+
+assign irq_lvl = irq_lines ^ ipic_iinvr_next;
+
+// IRQ lines edge detection
+//------------------------------------------------------------------------------
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ irq_lines_dly <= '0;
+ end else begin
+ irq_lines_dly <= irq_lines;
+ end
+end
+
+assign irq_edge_detected = (irq_lines_dly ^ irq_lines) & irq_lvl;
+
+//------------------------------------------------------------------------------
+// IPIC registers read/write interface
+//------------------------------------------------------------------------------
+
+// Read Logic
+//------------------------------------------------------------------------------
+
+// Read data multiplexer
+always_comb begin
+ ipic2csr_rdata_o = '0;
+
+ if (csr2ipic_r_req_i) begin
+ case (csr2ipic_addr_i)
+ SCR1_IPIC_CISV : begin
+ ipic2csr_rdata_o[SCR1_IRQ_VECT_WIDTH-1:0] = irq_serv_vd
+ ? ipic_cisv_ff
+ : SCR1_IRQ_VOID_VECT_NUM;
+ end
+ SCR1_IPIC_CICSR : begin
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_IP] = ipic_cicsr.ip;
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_IE] = ipic_cicsr.ie;
+ end
+ SCR1_IPIC_IPR : begin
+ ipic2csr_rdata_o = `SCR1_XLEN'(ipic_ipr_ff);
+ end
+ SCR1_IPIC_ISVR : begin
+ ipic2csr_rdata_o = `SCR1_XLEN'(ipic_isvr_ff);
+ end
+ SCR1_IPIC_EOI,
+ SCR1_IPIC_SOI : begin
+ ipic2csr_rdata_o = '0;
+ end
+ SCR1_IPIC_IDX : begin
+ ipic2csr_rdata_o = `SCR1_XLEN'(ipic_idxr_ff);
+ end
+ SCR1_IPIC_ICSR : begin
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_IP] = ipic_icsr.ip;
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_IE] = ipic_icsr.ie;
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_IM] = ipic_icsr.im;
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_INV] = ipic_icsr.inv;
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_PRV_MSB:
+ SCR1_IPIC_ICSR_PRV_LSB] = SCR1_IPIC_PRV_M;
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_IS] = ipic_icsr.is;
+ ipic2csr_rdata_o[SCR1_IPIC_ICSR_LN_MSB-1:
+ SCR1_IPIC_ICSR_LN_LSB] = ipic_icsr.line;
+ end
+ default : begin
+ ipic2csr_rdata_o = 'x;
+ end
+ endcase
+ end
+end
+
+// Write logic
+//------------------------------------------------------------------------------
+
+// Register selection
+always_comb begin
+ cicsr_wr_req = 1'b0;
+ eoi_wr_req = 1'b0;
+ soi_wr_req = 1'b0;
+ idxr_wr_req = 1'b0;
+ icsr_wr_req = 1'b0;
+ if (csr2ipic_w_req_i) begin
+ case (csr2ipic_addr_i)
+ SCR1_IPIC_CISV : begin end // Quiet Read-Only
+ SCR1_IPIC_CICSR: cicsr_wr_req = 1'b1;
+ SCR1_IPIC_IPR : begin end
+ SCR1_IPIC_ISVR : begin end // Quiet Read-Only
+ SCR1_IPIC_EOI : eoi_wr_req = 1'b1;
+ SCR1_IPIC_SOI : soi_wr_req = 1'b1;
+ SCR1_IPIC_IDX : idxr_wr_req = 1'b1;
+ SCR1_IPIC_ICSR : icsr_wr_req = 1'b1;
+ default : begin // Illegal IPIC register address
+ cicsr_wr_req = 'x;
+ eoi_wr_req = 'x;
+ soi_wr_req = 'x;
+ idxr_wr_req = 'x;
+ icsr_wr_req = 'x;
+ end
+ endcase
+ end
+end
+
+//------------------------------------------------------------------------------
+// IPIC registers
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - Current Interrupt Vector in Service (CISV) register
+ // - Current Interrupt Control Status (CICSR) register
+ // - End of Interrupt (EOI) register
+ // - Start of Interrupt (SOI) register
+ // - Index (IDX) register
+ // - Interrupt Pending Register (IPR)
+ // - Interrupt Serviced Register (ISVR)
+ // - Interrupt Enable Register (IER)
+ // - Interrupt Mode Register (IMR)
+ // - Interrupt Inversion Register (IINVR)
+ // - Interrupt Control Status Register (ICSR)
+//
+
+// CISV register
+//------------------------------------------------------------------------------
+// Contains number of the interrupt vector currently in service. When no
+// interrupts are in service, contains number of the void interrupt vector (0x10).
+// The register cannot contain all 0's
+
+assign ipic_cisv_upd = irq_start_vd | ipic_eoi_req;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ ipic_cisv_ff <= SCR1_IRQ_VOID_VECT_NUM;
+ end else if (ipic_cisv_upd) begin
+ ipic_cisv_ff <= ipic_cisv_next;
+ end
+end
+
+assign ipic_cisv_next = irq_start_vd ? irq_req_idx
+ : ipic_eoi_req ? irq_eoi_req_vd ? irq_eoi_req_idx
+ : SCR1_IRQ_VOID_VECT_NUM
+ : 1'b0;
+
+assign irq_serv_idx = ipic_cisv_ff[SCR1_IRQ_VECT_WIDTH-2:0];
+assign irq_serv_vd = ~ipic_cisv_ff[SCR1_IRQ_VECT_WIDTH-1];
+
+// CICSR register
+//------------------------------------------------------------------------------
+// Shows whether the interrupt currently in service is pending and enabled
+
+assign ipic_cicsr.ip = ipic_ipr_ff[irq_serv_idx] & irq_serv_vd;
+assign ipic_cicsr.ie = ipic_ier_ff[irq_serv_idx] & irq_serv_vd;
+
+// EOI register
+//------------------------------------------------------------------------------
+// Writing any value to EOI register ends the interrupt which is currently in service
+
+assign ipic_eoi_req = eoi_wr_req & irq_serv_vd;
+
+// SOI register
+//------------------------------------------------------------------------------
+// Writing any value to SOI activates start of interrupt if one of the following
+// conditions is true:
+// - There is at least one pending interrupt with IE and ISR is zero
+// - There is at least one pending interrupt with IE and higher priority than the
+// interrupts currently in service
+
+assign ipic_soi_req = soi_wr_req & irq_req_vd;
+
+// IDX register
+//------------------------------------------------------------------------------
+// Defines the number of interrupt vector which is accessed through the IPIC_ICSR
+// register
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ ipic_idxr_ff <= '0;
+ end else if (idxr_wr_req) begin
+ ipic_idxr_ff <= csr2ipic_wdata_i[SCR1_IRQ_IDX_WIDTH-1:0];
+ end
+end
+
+// IPR
+//------------------------------------------------------------------------------
+// For every IRQ line shows whether there is a pending interrupt
+
+assign ipic_ipr_upd = (ipic_ipr_next != ipic_ipr_ff);
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ ipic_ipr_ff <= '0;
+ end else if (ipic_ipr_upd) begin
+ ipic_ipr_ff <= ipic_ipr_next;
+ end
+end
+
+always_comb begin
+ ipic_ipr_clr_req = '0;
+ if (csr2ipic_w_req_i) begin
+ case (csr2ipic_addr_i)
+ SCR1_IPIC_CICSR: ipic_ipr_clr_req[irq_serv_idx] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IP]
+ & irq_serv_vd;
+ SCR1_IPIC_IPR : ipic_ipr_clr_req = csr2ipic_wdata_i[SCR1_IRQ_VECT_NUM-1:0];
+ SCR1_IPIC_SOI : ipic_ipr_clr_req[irq_req_idx] = irq_req_vd;
+ SCR1_IPIC_ICSR : ipic_ipr_clr_req[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IP];
+ default : begin end
+ endcase
+ end
+end
+
+assign ipic_ipr_clr_cond = ~irq_lvl | ipic_imr_next;
+assign ipic_ipr_clr = ipic_ipr_clr_req & ipic_ipr_clr_cond;
+
+always_comb begin
+ ipic_ipr_next = '0;
+ for (int unsigned i=0; i<SCR1_IRQ_VECT_NUM; ++i) begin
+ ipic_ipr_next[i] = ipic_ipr_clr[i] ? 1'b0
+ : ~ipic_imr_ff[i] ? irq_lvl[i]
+ : ipic_ipr_ff[i] | irq_edge_detected[i];
+ end
+end
+
+// ISVR
+//------------------------------------------------------------------------------
+// For every IRQ line shows whether the interrupt is in service or not
+
+assign ipic_isvr_upd = irq_start_vd | ipic_eoi_req;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ ipic_isvr_ff <= '0;
+ end else if (ipic_isvr_upd) begin
+ ipic_isvr_ff <= ipic_isvr_next;
+ end
+end
+
+always_comb begin
+ ipic_isvr_eoi = ipic_isvr_ff;
+ if (irq_serv_vd) begin
+ ipic_isvr_eoi[irq_serv_idx] = 1'b0;
+ end
+end
+
+always_comb begin
+ ipic_isvr_next = ipic_isvr_ff;
+ if (irq_start_vd) begin
+ ipic_isvr_next[irq_req_idx] = 1'b1;
+ end else if (ipic_eoi_req) begin
+ ipic_isvr_next = ipic_isvr_eoi;
+ end
+end
+
+// IER
+//------------------------------------------------------------------------------
+// Enables/disables interrupt for every IRQ line
+
+assign ipic_ier_upd = cicsr_wr_req | icsr_wr_req;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ ipic_ier_ff <= '0;
+ end else if (ipic_ier_upd) begin
+ ipic_ier_ff <= ipic_ier_next;
+ end
+end
+
+always_comb begin
+ ipic_ier_next = ipic_ier_ff;
+ if (cicsr_wr_req) begin
+ ipic_ier_next[irq_serv_idx] = irq_serv_vd
+ ? csr2ipic_wdata_i[SCR1_IPIC_ICSR_IE]
+ : ipic_ier_ff[irq_serv_idx];
+ end else if (icsr_wr_req) begin
+ ipic_ier_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IE];
+ end
+end
+
+// IMR
+//------------------------------------------------------------------------------
+// For every IRQ line sets either Level (0) or Edge (1) detection
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ ipic_imr_ff <= '0;
+ end else if (icsr_wr_req) begin
+ ipic_imr_ff <= ipic_imr_next;
+ end
+end
+
+always_comb begin
+ ipic_imr_next = ipic_imr_ff;
+ if (icsr_wr_req) begin
+ ipic_imr_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IM];
+ end
+end
+
+// IINVR
+//------------------------------------------------------------------------------
+// For every IRQ line defines whether it should be inverted or not
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ ipic_iinvr_ff <= '0;
+ end else if (icsr_wr_req) begin
+ ipic_iinvr_ff <= ipic_iinvr_next;
+ end
+end
+
+always_comb begin
+ ipic_iinvr_next = ipic_iinvr_ff;
+ if (icsr_wr_req) begin
+ ipic_iinvr_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_INV];
+ end
+end
+
+// ICSR
+//------------------------------------------------------------------------------
+// Holds control and status information about the interrupt defined by Index Register
+
+assign ipic_icsr.ip = ipic_ipr_ff [ipic_idxr_ff];
+assign ipic_icsr.ie = ipic_ier_ff [ipic_idxr_ff];
+assign ipic_icsr.im = ipic_imr_ff [ipic_idxr_ff];
+assign ipic_icsr.inv = ipic_iinvr_ff[ipic_idxr_ff];
+assign ipic_icsr.is = ipic_isvr_ff [ipic_idxr_ff];
+assign ipic_icsr.line = SCR1_IRQ_LINES_WIDTH'(ipic_idxr_ff);
+
+//------------------------------------------------------------------------------
+// Priority IRQ generation logic
+//------------------------------------------------------------------------------
+
+assign irq_req_v = ipic_ipr_ff & ipic_ier_ff;
+
+assign irr_priority = scr1_search_one_16(irq_req_v);
+assign irq_req_vd = irr_priority.vd;
+assign irq_req_idx = irr_priority.idx;
+
+assign isvr_priority_eoi = scr1_search_one_16(ipic_isvr_eoi);
+assign irq_eoi_req_vd = isvr_priority_eoi.vd;
+assign irq_eoi_req_idx = isvr_priority_eoi.idx;
+
+assign irq_hi_prior_pnd = irq_req_idx < irq_serv_idx;
+
+assign ipic2csr_irq_m_req_o = irq_req_vd & (~irq_serv_vd | irq_hi_prior_pnd);
+
+assign irq_start_vd = ipic2csr_irq_m_req_o & ipic_soi_req;
+
+endmodule : scr1_ipic
+
+`endif // SCR1_IPIC_EN
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_csr.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_csr.sv
new file mode 100644
index 0000000..183887d
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_csr.sv
@@ -0,0 +1,1167 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_csr.sv>
+/// @brief Control Status Registers (CSR)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Provides access to RISC-V CSR Machine registers
+ // - Handles events (EXC, IRQ and MRET):
+ // - Setups handling configuration
+ // - Displays events statuses and information
+ // - Generates new PC
+ // - Provides information about the number of executed instructions and elapsed
+ // cycles
+ // - Provides interfaces for IPIC, HDU and TDU registers access
+ //
+ // Structure:
+ // - Events (EXC, IRQ, MRET) logic
+ // - CSR read/write interface
+ // - CSR registers:
+ // - Machine Trap Setup registers
+ // - Machine Trap Handling registers
+ // - Machine Counters/Timers registers
+ // - Non-standard CSRs (MCOUNTEN)
+ // - CSR <-> EXU i/f
+ // - CSR <-> IPIC i/f
+ // - CSR <-> HDU i/f
+ // - CSR <-> TDU i/f
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+`include "scr1_csr.svh"
+`include "scr1_arch_types.svh"
+`include "scr1_riscv_isa_decoding.svh"
+`ifdef SCR1_IPIC_EN
+`include "scr1_ipic.svh"
+`endif // SCR1_IPIC_EN
+`ifdef SCR1_DBG_EN
+`include "scr1_hdu.svh"
+`endif // SCR1_DBG_EN
+`ifdef SCR1_TDU_EN
+`include "scr1_tdu.svh"
+`endif // SCR1_TDU_EN
+
+module scr1_pipe_csr (
+ // Common
+ input logic rst_n, // CSR reset
+ input logic clk, // Gated CSR clock
+`ifdef SCR1_CLKCTRL_EN
+ input logic clk_alw_on, // Not-gated CSR clock
+`endif // SCR1_CLKCTRL_EN
+
+ // SOC signals
+ // IRQ
+ input logic soc2csr_irq_ext_i, // External interrupt request
+ input logic soc2csr_irq_soft_i, // Software interrupt request
+ input logic soc2csr_irq_mtimer_i, // External timer interrupt request
+
+ // Memory-mapped external timer
+ input logic [63:0] soc2csr_mtimer_val_i, // External timer value
+
+ // MHARTID fuse
+ input logic [`SCR1_XLEN-1:0] soc2csr_fuse_mhartid_i, // MHARTID fuse
+
+ // CSR <-> EXU read/write interface
+ input logic exu2csr_r_req_i, // CSR read/write address
+ input logic [SCR1_CSR_ADDR_WIDTH-1:0] exu2csr_rw_addr_i, // CSR read request
+ output logic [`SCR1_XLEN-1:0] csr2exu_r_data_o, // CSR read data
+ input logic exu2csr_w_req_i, // CSR write request
+ input type_scr1_csr_cmd_sel_e exu2csr_w_cmd_i, // CSR write command
+ input logic [`SCR1_XLEN-1:0] exu2csr_w_data_i, // CSR write data
+ output logic csr2exu_rw_exc_o, // CSR read/write access exception
+
+ // CSR <-> EXU event interface
+ input logic exu2csr_take_irq_i, // Take IRQ trap
+ input logic exu2csr_take_exc_i, // Take exception trap
+ input logic exu2csr_mret_update_i, // MRET update CSR
+ input logic exu2csr_mret_instr_i, // MRET instruction
+ input type_scr1_exc_code_e exu2csr_exc_code_i, // Exception code (see scr1_arch_types.svh)
+ input logic [`SCR1_XLEN-1:0] exu2csr_trap_val_i, // Trap value
+ output logic csr2exu_irq_o, // IRQ request
+ output logic csr2exu_ip_ie_o, // Some IRQ pending and locally enabled
+ output logic csr2exu_mstatus_mie_up_o, // MSTATUS or MIE update in the current cycle
+
+`ifdef SCR1_IPIC_EN
+ // CSR <-> IPIC interface
+ output logic csr2ipic_r_req_o, // IPIC read request
+ output logic csr2ipic_w_req_o, // IPIC write request
+ output logic [2:0] csr2ipic_addr_o, // IPIC address
+ output logic [`SCR1_XLEN-1:0] csr2ipic_wdata_o, // IPIC write data
+ input logic [`SCR1_XLEN-1:0] ipic2csr_rdata_i, // IPIC read data
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_DBG_EN
+ // CSR <-> HDU interface
+ output logic csr2hdu_req_o, // Request to HDU
+ output type_scr1_csr_cmd_sel_e csr2hdu_cmd_o, // HDU command
+ output logic [SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0] csr2hdu_addr_o, // HDU address
+ output logic [`SCR1_XLEN-1:0] csr2hdu_wdata_o, // HDU write data
+ input logic [`SCR1_XLEN-1:0] hdu2csr_rdata_i, // HDU read data
+ input type_scr1_csr_resp_e hdu2csr_resp_i, // HDU response
+ input logic hdu2csr_no_commit_i, // Forbid instruction commitment
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+ // CSR <-> TDU interface
+ output logic csr2tdu_req_o, // Request to TDU
+ output type_scr1_csr_cmd_sel_e csr2tdu_cmd_o, // TDU command
+ output logic [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] csr2tdu_addr_o, // TDU address
+ output logic [`SCR1_XLEN-1:0] csr2tdu_wdata_o, // TDU write data
+ input logic [`SCR1_XLEN-1:0] tdu2csr_rdata_i, // TDU read data
+ input type_scr1_csr_resp_e tdu2csr_resp_i, // TDU response
+`endif // SCR1_TDU_EN
+
+ // CSR <-> EXU PC interface
+`ifndef SCR1_CSR_REDUCED_CNT
+ input logic exu2csr_instret_no_exc_i, // Instruction retired (without exception)
+`endif // SCR1_CSR_REDUCED_CNT
+ input logic [`SCR1_XLEN-1:0] exu2csr_pc_curr_i, // Current PC
+ input logic [`SCR1_XLEN-1:0] exu2csr_pc_next_i, // Next PC
+ output logic [`SCR1_XLEN-1:0] csr2exu_new_pc_o // Exception/IRQ/MRET new PC
+);
+
+//------------------------------------------------------------------------------
+// Local parameters
+//------------------------------------------------------------------------------
+
+`ifdef SCR1_RVC_EXT
+ localparam PC_LSB = 1;
+`else
+ localparam PC_LSB = 2;
+`endif
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// Machine Trap Setup registers
+//------------------------------------------------------------------------------
+
+// MSTATUS register
+logic csr_mstatus_upd; // MSTATUS update enable
+logic [`SCR1_XLEN-1:0] csr_mstatus; // Aggregated MSTATUS
+logic csr_mstatus_mie_ff; // MSTATUS: Global interrupt enable
+logic csr_mstatus_mie_next; // MSTATUS: Global interrupt enable next value
+logic csr_mstatus_mpie_ff; // MSTATUS: Global interrupt enable prior to the trap
+logic csr_mstatus_mpie_next; // MSTATUS: Global interrupt enable prior to the trap next value
+
+// MIE register
+logic csr_mie_upd; // MIE update enable
+logic [`SCR1_XLEN-1:0] csr_mie; // Aggregated MIE
+logic csr_mie_mtie_ff; // MIE: Machine timer interrupt enable
+logic csr_mie_meie_ff; // MIE: Machine external interrupt enable
+logic csr_mie_msie_ff; // MIE: Machine software interrupt enable
+
+// MTVEC register
+logic csr_mtvec_upd; // MTVEC update enable
+logic [`SCR1_XLEN-1:SCR1_CSR_MTVEC_BASE_ZERO_BITS] csr_mtvec_base; // MTVEC: Base (upper 26 bits)
+logic csr_mtvec_mode; // MTVEC: Mode (0-direct, 1-vectored) (wired)
+`ifdef SCR1_MTVEC_MODE_EN
+logic csr_mtvec_mode_ff; // MTVEC: Mode (0-direct, 1-vectored) (registered)
+logic csr_mtvec_mode_vect;
+`endif
+
+// Machine Trap Handling registers
+//------------------------------------------------------------------------------
+
+// MSCRATCH register
+logic csr_mscratch_upd; // MSCRATCH update enable
+logic [`SCR1_XLEN-1:0] csr_mscratch_ff; // MSCRATCH
+
+// MEPC register
+logic csr_mepc_upd; // MEPC update enable
+logic [`SCR1_XLEN-1:PC_LSB] csr_mepc_ff; // MEPC registered value
+logic [`SCR1_XLEN-1:PC_LSB] csr_mepc_next; // MEPC next value
+logic [`SCR1_XLEN-1:0] csr_mepc; // MEPC registered value extended to XLEN
+
+// MCAUSE register
+logic csr_mcause_upd; // MCAUSE update enable
+logic csr_mcause_i_ff; // MCAUSE: Interrupt
+logic csr_mcause_i_next; // MCAUSE: Interrupt next value
+type_scr1_exc_code_e csr_mcause_ec_ff; // MCAUSE: Exception code
+type_scr1_exc_code_e csr_mcause_ec_next; // MCAUSE: Exception code next value
+type_scr1_exc_code_e csr_mcause_ec_new; // MCAUSE: Exception code new value (IRQs)
+
+// MTVAL register
+logic csr_mtval_upd; // MTVAL update enable
+logic [`SCR1_XLEN-1:0] csr_mtval_ff; // MTVAL registered value
+logic [`SCR1_XLEN-1:0] csr_mtval_next; // MTVAL next value
+
+// MIP register
+logic [`SCR1_XLEN-1:0] csr_mip; // Aggregated MIP
+logic csr_mip_mtip; // MIP: Machine timer interrupt pending
+logic csr_mip_meip; // MIP: Machine external interrupt pending
+logic csr_mip_msip; // MIP: Machine software interrupt pending
+
+// Machine Counters/Timers registers
+//------------------------------------------------------------------------------
+
+`ifndef SCR1_CSR_REDUCED_CNT
+// MINSTRET register
+logic [1:0] csr_minstret_upd;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:0] csr_minstret;
+logic csr_minstret_lo_inc;
+logic csr_minstret_lo_upd;
+logic [7:0] csr_minstret_lo_ff;
+logic [7:0] csr_minstret_lo_next;
+logic csr_minstret_hi_inc;
+logic csr_minstret_hi_upd;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:8] csr_minstret_hi_ff;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:8] csr_minstret_hi_next;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:8] csr_minstret_hi_new;
+
+// MCYCLE register
+logic [1:0] csr_mcycle_upd;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:0] csr_mcycle;
+logic csr_mcycle_lo_inc;
+logic csr_mcycle_lo_upd;
+logic [7:0] csr_mcycle_lo_ff;
+logic [7:0] csr_mcycle_lo_next;
+logic csr_mcycle_hi_inc;
+logic csr_mcycle_hi_upd;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:8] csr_mcycle_hi_ff;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:8] csr_mcycle_hi_next;
+logic [SCR1_CSR_COUNTERS_WIDTH-1:8] csr_mcycle_hi_new;
+`endif // ~SCR1_CSR_REDUCED_CNT
+
+// Non-standard CSRs
+//------------------------------------------------------------------------------
+
+// MCOUNTEN register
+`ifdef SCR1_MCOUNTEN_EN
+logic csr_mcounten_upd; // MCOUNTEN update enable
+logic [`SCR1_XLEN-1:0] csr_mcounten; // Aggregated MCOUNTEN
+logic csr_mcounten_cy_ff; // Cycle count enable
+logic csr_mcounten_ir_ff; // Instret count enable
+`endif // SCR1_MCOUNTEN_EN
+
+// CSR read/write i/f
+//------------------------------------------------------------------------------
+
+logic [`SCR1_XLEN-1:0] csr_r_data;
+logic [`SCR1_XLEN-1:0] csr_w_data;
+
+// Events (exceptions, interrupts, mret) signals
+//------------------------------------------------------------------------------
+
+// Event flags
+logic e_exc; // Successful exception trap
+logic e_irq; // Successful IRQ trap
+logic e_mret; // MRET instruction
+logic e_irq_nmret; // IRQ trap without MRET instruction
+
+// Interrupt pending & enable signals
+logic csr_eirq_pnd_en; // External IRQ pending and locally enabled
+logic csr_sirq_pnd_en; // Software IRQ pending and locally enabled
+logic csr_tirq_pnd_en; // Timer IRQ pending and locally enabled
+
+// Exception flags
+logic csr_w_exc;
+logic csr_r_exc;
+logic exu_req_no_exc;
+
+// Requests to other modules
+logic csr_ipic_req;
+`ifdef SCR1_DBG_EN
+logic csr_hdu_req;
+`endif // SCR1_DBG_EN
+`ifdef SCR1_TDU_EN
+logic csr_brkm_req;
+`endif // SCR1_TDU_EN
+
+//------------------------------------------------------------------------------
+// Events (IRQ, EXC, MRET)
+//------------------------------------------------------------------------------
+
+// Events priority
+assign e_exc = exu2csr_take_exc_i
+`ifdef SCR1_DBG_EN
+ & ~hdu2csr_no_commit_i
+`endif // SCR1_DBG_EN
+ ;
+assign e_irq = exu2csr_take_irq_i & ~exu2csr_take_exc_i
+`ifdef SCR1_DBG_EN
+ & ~hdu2csr_no_commit_i
+`endif // SCR1_DBG_EN
+ ;
+assign e_mret = exu2csr_mret_update_i
+`ifdef SCR1_DBG_EN
+ & ~hdu2csr_no_commit_i
+`endif // SCR1_DBG_EN
+ ;
+assign e_irq_nmret = e_irq & ~exu2csr_mret_instr_i;
+
+// IRQ pending & enable signals
+assign csr_eirq_pnd_en = csr_mip_meip & csr_mie_meie_ff;
+assign csr_sirq_pnd_en = csr_mip_msip & csr_mie_msie_ff;
+assign csr_tirq_pnd_en = csr_mip_mtip & csr_mie_mtie_ff;
+
+// IRQ exception codes priority
+always_comb begin
+ case (1'b1)
+ csr_eirq_pnd_en: csr_mcause_ec_new = type_scr1_exc_code_e'(SCR1_EXC_CODE_IRQ_M_EXTERNAL);
+ csr_sirq_pnd_en: csr_mcause_ec_new = type_scr1_exc_code_e'(SCR1_EXC_CODE_IRQ_M_SOFTWARE);
+ csr_tirq_pnd_en: csr_mcause_ec_new = type_scr1_exc_code_e'(SCR1_EXC_CODE_IRQ_M_TIMER);
+ default : csr_mcause_ec_new = type_scr1_exc_code_e'(SCR1_EXC_CODE_IRQ_M_EXTERNAL);
+ endcase
+end
+
+assign exu_req_no_exc = ((exu2csr_r_req_i & ~csr_r_exc)
+ | (exu2csr_w_req_i & ~csr_w_exc));
+
+//------------------------------------------------------------------------------
+// CSR read/write interface
+//------------------------------------------------------------------------------
+
+// CSR read logic
+//------------------------------------------------------------------------------
+
+always_comb begin
+ csr_r_data = '0;
+ csr_r_exc = 1'b0;
+`ifdef SCR1_DBG_EN
+ csr_hdu_req = 1'b0;
+`endif // SCR1_DBG_EN
+`ifdef SCR1_TDU_EN
+ csr_brkm_req = 1'b0;
+`endif // SCR1_TDU_EN
+`ifdef SCR1_IPIC_EN
+ csr2ipic_r_req_o = 1'b0;
+`endif // SCR1_IPIC_EN
+
+ casez (exu2csr_rw_addr_i)
+ // Machine Information Registers (read-only)
+ SCR1_CSR_ADDR_MVENDORID : csr_r_data = SCR1_CSR_MVENDORID;
+ SCR1_CSR_ADDR_MARCHID : csr_r_data = SCR1_CSR_MARCHID;
+ SCR1_CSR_ADDR_MIMPID : csr_r_data = SCR1_CSR_MIMPID;
+ SCR1_CSR_ADDR_MHARTID : csr_r_data = soc2csr_fuse_mhartid_i;
+
+ // Machine Trap Setup (read-write)
+ SCR1_CSR_ADDR_MSTATUS : csr_r_data = csr_mstatus;
+ SCR1_CSR_ADDR_MISA : csr_r_data = SCR1_CSR_MISA;
+ SCR1_CSR_ADDR_MIE : csr_r_data = csr_mie;
+ SCR1_CSR_ADDR_MTVEC : csr_r_data = {csr_mtvec_base, 4'd0, 2'(csr_mtvec_mode)};
+
+ // Machine Trap Handling (read-write)
+ SCR1_CSR_ADDR_MSCRATCH : csr_r_data = csr_mscratch_ff;
+ SCR1_CSR_ADDR_MEPC : csr_r_data = csr_mepc;
+ SCR1_CSR_ADDR_MCAUSE : csr_r_data = {csr_mcause_i_ff, type_scr1_csr_mcause_ec_v'(csr_mcause_ec_ff)};
+ SCR1_CSR_ADDR_MTVAL : csr_r_data = csr_mtval_ff;
+ SCR1_CSR_ADDR_MIP : csr_r_data = csr_mip;
+
+ // User Counters/Timers (read-only)
+ {SCR1_CSR_ADDR_HPMCOUNTER_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd1 : csr_r_data = soc2csr_mtimer_val_i[31:0];
+`ifndef SCR1_CSR_REDUCED_CNT
+ 5'd0 : csr_r_data = csr_mcycle[31:0];
+ 5'd2 : csr_r_data = csr_minstret[31:0];
+`endif // SCR1_CSR_REDUCED_CNT
+ default : begin
+ // return 0
+ end
+ endcase
+ end
+
+ {SCR1_CSR_ADDR_HPMCOUNTERH_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd1 : csr_r_data = soc2csr_mtimer_val_i[63:32];
+`ifndef SCR1_CSR_REDUCED_CNT
+ 5'd0 : csr_r_data = csr_mcycle[63:32];
+ 5'd2 : csr_r_data = csr_minstret[63:32];
+`endif // SCR1_CSR_REDUCED_CNT
+ default : begin
+ // return 0
+ end
+ endcase
+ end
+
+ // Machine Counters/Timers (read-write)
+ {SCR1_CSR_ADDR_MHPMCOUNTER_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd1 : csr_r_exc = exu2csr_r_req_i;
+`ifndef SCR1_CSR_REDUCED_CNT
+ 5'd0 : csr_r_data = csr_mcycle[31:0];
+ 5'd2 : csr_r_data = csr_minstret[31:0];
+`endif // SCR1_CSR_REDUCED_CNT
+ default : begin
+ // return 0
+ end
+ endcase
+ end
+
+ {SCR1_CSR_ADDR_MHPMCOUNTERH_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd1 : csr_r_exc = exu2csr_r_req_i;
+`ifndef SCR1_CSR_REDUCED_CNT
+ 5'd0 : csr_r_data = csr_mcycle[63:32];
+ 5'd2 : csr_r_data = csr_minstret[63:32];
+`endif // SCR1_CSR_REDUCED_CNT
+ default : begin
+ // return 0
+ end
+ endcase
+ end
+
+ {SCR1_CSR_ADDR_MHPMEVENT_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd0,
+ 5'd1,
+ 5'd2 : csr_r_exc = exu2csr_r_req_i;
+ default : begin
+ // return 0
+ end
+ endcase
+ end
+
+`ifdef SCR1_MCOUNTEN_EN
+ SCR1_CSR_ADDR_MCOUNTEN : csr_r_data = csr_mcounten;
+`endif // SCR1_MCOUNTEN_EN
+
+`ifdef SCR1_IPIC_EN
+ // IPIC registers
+ SCR1_CSR_ADDR_IPIC_CISV,
+ SCR1_CSR_ADDR_IPIC_CICSR,
+ SCR1_CSR_ADDR_IPIC_IPR,
+ SCR1_CSR_ADDR_IPIC_ISVR,
+ SCR1_CSR_ADDR_IPIC_EOI,
+ SCR1_CSR_ADDR_IPIC_SOI,
+ SCR1_CSR_ADDR_IPIC_IDX,
+ SCR1_CSR_ADDR_IPIC_ICSR : begin
+ csr_r_data = ipic2csr_rdata_i;
+ csr2ipic_r_req_o = exu2csr_r_req_i;
+ end
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_DBG_EN
+ // HDU registers
+ SCR1_HDU_DBGCSR_ADDR_DCSR,
+ SCR1_HDU_DBGCSR_ADDR_DPC,
+ SCR1_HDU_DBGCSR_ADDR_DSCRATCH0,
+ SCR1_HDU_DBGCSR_ADDR_DSCRATCH1 : begin
+ csr_hdu_req = 1'b1;
+ csr_r_data = hdu2csr_rdata_i;
+ end
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+ // TDU registers
+ SCR1_CSR_ADDR_TDU_TSELECT,
+ SCR1_CSR_ADDR_TDU_TDATA1,
+ SCR1_CSR_ADDR_TDU_TDATA2,
+ SCR1_CSR_ADDR_TDU_TINFO: begin
+ csr_brkm_req = 1'b1;
+ csr_r_data = tdu2csr_rdata_i;
+ end
+`endif // SCR1_TDU_EN
+
+ default : begin
+ csr_r_exc = exu2csr_r_req_i;
+ end
+ endcase // exu2csr_rw_addr_i
+end
+
+assign csr2exu_r_data_o = csr_r_data;
+
+// CSR write logic
+//------------------------------------------------------------------------------
+
+always_comb begin
+ case (exu2csr_w_cmd_i)
+ SCR1_CSR_CMD_WRITE : csr_w_data = exu2csr_w_data_i;
+ SCR1_CSR_CMD_SET : csr_w_data = exu2csr_w_data_i | csr_r_data;
+ SCR1_CSR_CMD_CLEAR : csr_w_data = ~exu2csr_w_data_i & csr_r_data;
+ default : csr_w_data = '0;
+ endcase
+end
+
+always_comb begin
+ csr_mstatus_upd = 1'b0;
+ csr_mie_upd = 1'b0;
+ csr_mscratch_upd = 1'b0;
+ csr_mepc_upd = 1'b0;
+ csr_mcause_upd = 1'b0;
+ csr_mtval_upd = 1'b0;
+ csr_mtvec_upd = 1'b0;
+
+`ifndef SCR1_CSR_REDUCED_CNT
+ csr_mcycle_upd = 2'b00;
+ csr_minstret_upd = 2'b00;
+`endif // SCR1_CSR_REDUCED_CNT
+
+`ifdef SCR1_MCOUNTEN_EN
+ csr_mcounten_upd = 1'b0;
+`endif // SCR1_MCOUNTEN_EN
+ csr_w_exc = 1'b0;
+`ifdef SCR1_IPIC_EN
+ csr2ipic_w_req_o = 1'b0;
+`endif // SCR1_IPIC_EN
+
+ if (exu2csr_w_req_i) begin
+ casez (exu2csr_rw_addr_i)
+ // Machine Trap Setup (read-write)
+ SCR1_CSR_ADDR_MSTATUS : csr_mstatus_upd = 1'b1;
+ SCR1_CSR_ADDR_MISA : begin end
+ SCR1_CSR_ADDR_MIE : csr_mie_upd = 1'b1;
+ SCR1_CSR_ADDR_MTVEC : csr_mtvec_upd = 1'b1;
+
+ // Machine Trap Handling (read-write)
+ SCR1_CSR_ADDR_MSCRATCH : csr_mscratch_upd = 1'b1;
+ SCR1_CSR_ADDR_MEPC : csr_mepc_upd = 1'b1;
+ SCR1_CSR_ADDR_MCAUSE : csr_mcause_upd = 1'b1;
+ SCR1_CSR_ADDR_MTVAL : csr_mtval_upd = 1'b1;
+ SCR1_CSR_ADDR_MIP : begin end
+
+ // Machine Counters/Timers (read-write)
+ {SCR1_CSR_ADDR_MHPMCOUNTER_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd1 : csr_w_exc = 1'b1;
+`ifndef SCR1_CSR_REDUCED_CNT
+ 5'd0 : csr_mcycle_upd[0] = 1'b1;
+ 5'd2 : csr_minstret_upd[0] = 1'b1;
+`endif // SCR1_CSR_REDUCED_CNT
+ default : begin
+ // no exception
+ end
+ endcase
+ end
+
+ {SCR1_CSR_ADDR_MHPMCOUNTERH_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd1 : csr_w_exc = 1'b1;
+`ifndef SCR1_CSR_REDUCED_CNT
+ 5'd0 : csr_mcycle_upd[1] = 1'b1;
+ 5'd2 : csr_minstret_upd[1] = 1'b1;
+`endif // SCR1_CSR_REDUCED_CNT
+ default : begin
+ // no exception
+ end
+ endcase
+ end
+
+ {SCR1_CSR_ADDR_MHPMEVENT_MASK, 5'b?????} : begin
+ case (exu2csr_rw_addr_i[4:0])
+ 5'd0,
+ 5'd1,
+ 5'd2 : csr_w_exc = 1'b1;
+ default : begin
+ // no exception
+ end
+ endcase
+ end
+
+`ifdef SCR1_MCOUNTEN_EN
+ SCR1_CSR_ADDR_MCOUNTEN : csr_mcounten_upd = 1'b1;
+`endif // SCR1_MCOUNTEN_EN
+
+`ifdef SCR1_IPIC_EN
+ // IPIC registers
+ SCR1_CSR_ADDR_IPIC_CICSR,
+ SCR1_CSR_ADDR_IPIC_IPR,
+ SCR1_CSR_ADDR_IPIC_EOI,
+ SCR1_CSR_ADDR_IPIC_SOI,
+ SCR1_CSR_ADDR_IPIC_IDX,
+ SCR1_CSR_ADDR_IPIC_ICSR : begin
+ csr2ipic_w_req_o = 1'b1;
+ end
+ SCR1_CSR_ADDR_IPIC_CISV,
+ SCR1_CSR_ADDR_IPIC_ISVR : begin
+ // no exception on write
+ end
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_DBG_EN
+ SCR1_HDU_DBGCSR_ADDR_DCSR,
+ SCR1_HDU_DBGCSR_ADDR_DPC,
+ SCR1_HDU_DBGCSR_ADDR_DSCRATCH0,
+ SCR1_HDU_DBGCSR_ADDR_DSCRATCH1 : begin
+ end
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+ // TDU registers
+ SCR1_CSR_ADDR_TDU_TSELECT,
+ SCR1_CSR_ADDR_TDU_TDATA1,
+ SCR1_CSR_ADDR_TDU_TDATA2,
+ SCR1_CSR_ADDR_TDU_TINFO: begin
+ end
+`endif // SCR1_TDU_EN
+
+ default : begin
+ csr_w_exc = 1'b1;
+ end
+ endcase
+ end
+end
+
+//------------------------------------------------------------------------------
+// Machine Trap Setup registers
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - MSTATUS
+ // - MIE
+ // - MTVEC
+//
+
+// MSTATUS register
+//------------------------------------------------------------------------------
+// Consists of 2 bits - current and previous (before trap) global interrupt
+// enable bits (MIE & MPIE)
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mstatus_mie_ff <= SCR1_CSR_MSTATUS_MIE_RST_VAL;
+ csr_mstatus_mpie_ff <= SCR1_CSR_MSTATUS_MPIE_RST_VAL;
+ end else begin
+ csr_mstatus_mie_ff <= csr_mstatus_mie_next;
+ csr_mstatus_mpie_ff <= csr_mstatus_mpie_next;
+ end
+end
+
+always_comb begin
+ case (1'b1)
+ e_exc, e_irq : begin
+ csr_mstatus_mie_next = 1'b0;
+ csr_mstatus_mpie_next = csr_mstatus_mie_ff;
+ end
+ e_mret : begin
+ csr_mstatus_mie_next = csr_mstatus_mpie_ff;
+ csr_mstatus_mpie_next = 1'b1;
+ end
+ csr_mstatus_upd: begin
+ csr_mstatus_mie_next = csr_w_data[SCR1_CSR_MSTATUS_MIE_OFFSET];
+ csr_mstatus_mpie_next = csr_w_data[SCR1_CSR_MSTATUS_MPIE_OFFSET];
+ end
+ default : begin
+ csr_mstatus_mie_next = csr_mstatus_mie_ff;
+ csr_mstatus_mpie_next = csr_mstatus_mpie_ff;
+ end
+ endcase
+end
+
+always_comb begin
+ csr_mstatus = '0;
+ csr_mstatus[SCR1_CSR_MSTATUS_MIE_OFFSET] = csr_mstatus_mie_ff;
+ csr_mstatus[SCR1_CSR_MSTATUS_MPIE_OFFSET] = csr_mstatus_mpie_ff;
+ csr_mstatus[SCR1_CSR_MSTATUS_MPP_OFFSET+1:SCR1_CSR_MSTATUS_MPP_OFFSET] = SCR1_CSR_MSTATUS_MPP;
+end
+
+// MIE register
+//------------------------------------------------------------------------------
+// Contains interrupt enable bits (external, software, timer IRQs)
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mie_mtie_ff <= SCR1_CSR_MIE_MTIE_RST_VAL;
+ csr_mie_meie_ff <= SCR1_CSR_MIE_MEIE_RST_VAL;
+ csr_mie_msie_ff <= SCR1_CSR_MIE_MSIE_RST_VAL;
+ end else if (csr_mie_upd) begin
+ csr_mie_mtie_ff <= csr_w_data[SCR1_CSR_MIE_MTIE_OFFSET];
+ csr_mie_meie_ff <= csr_w_data[SCR1_CSR_MIE_MEIE_OFFSET];
+ csr_mie_msie_ff <= csr_w_data[SCR1_CSR_MIE_MSIE_OFFSET];
+ end
+end
+
+always_comb begin
+ csr_mie = '0;
+ csr_mie[SCR1_CSR_MIE_MSIE_OFFSET] = csr_mie_msie_ff;
+ csr_mie[SCR1_CSR_MIE_MTIE_OFFSET] = csr_mie_mtie_ff;
+ csr_mie[SCR1_CSR_MIE_MEIE_OFFSET] = csr_mie_meie_ff;
+end
+
+// MTVEC register
+//------------------------------------------------------------------------------
+// Holds trap vector configuation. Consists of base and mode parts
+
+// MTVEC BASE part
+//------------------------------------------------------------------------------
+// Holds trap vector base address
+generate
+ // All bits of MTVEC base are Read-Only and hardwired to 0's
+ if (SCR1_MTVEC_BASE_WR_BITS == 0) begin : mtvec_base_ro
+
+ assign csr_mtvec_base = SCR1_CSR_MTVEC_BASE_RST_VAL;
+
+ // All bits of MTVEC base are RW
+ end else if (SCR1_MTVEC_BASE_WR_BITS == SCR1_CSR_MTVEC_BASE_VAL_BITS) begin : mtvec_base_rw
+
+ always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mtvec_base <= SCR1_CSR_MTVEC_BASE_RST_VAL;
+ end else if (csr_mtvec_upd) begin
+ csr_mtvec_base <= csr_w_data[`SCR1_XLEN-1:SCR1_CSR_MTVEC_BASE_ZERO_BITS];
+ end
+ end
+
+ // Lower bits of MTVEC base are RO, higher - RW
+ end else begin : mtvec_base_ro_rw
+
+ logic [(`SCR1_XLEN-1):(`SCR1_XLEN-SCR1_MTVEC_BASE_WR_BITS)] csr_mtvec_base_reg;
+
+ always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mtvec_base_reg <= SCR1_CSR_MTVEC_BASE_RST_VAL[(`SCR1_XLEN-1)-:SCR1_MTVEC_BASE_WR_BITS] ;
+ end else if (csr_mtvec_upd) begin
+ csr_mtvec_base_reg <= csr_w_data[(`SCR1_XLEN-1)-:SCR1_MTVEC_BASE_WR_BITS];
+ end
+ end
+
+ assign csr_mtvec_base = {csr_mtvec_base_reg, SCR1_CSR_MTVEC_BASE_RST_VAL[SCR1_CSR_MTVEC_BASE_ZERO_BITS+:SCR1_CSR_MTVEC_BASE_RO_BITS]};
+ end
+endgenerate
+
+// MTVEC MODE part
+//------------------------------------------------------------------------------
+// Chooses between direct (all exceptions set PC to BASE) or vectored
+// (asynchronous interrupts set PC to BASE+4xcause) interrupt modes
+
+`ifdef SCR1_MTVEC_MODE_EN
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mtvec_mode_ff <= SCR1_CSR_MTVEC_MODE_DIRECT;
+ end else if (csr_mtvec_upd) begin
+ csr_mtvec_mode_ff <= csr_w_data[0];
+ end
+end
+
+assign csr_mtvec_mode = csr_mtvec_mode_ff;
+assign csr_mtvec_mode_vect = (csr_mtvec_mode_ff == SCR1_CSR_MTVEC_MODE_VECTORED);
+`else // SCR1_MTVEC_MODE_EN
+assign csr_mtvec_mode = SCR1_CSR_MTVEC_MODE_DIRECT;
+`endif // SCR1_MTVEC_MODE_EN
+
+//------------------------------------------------------------------------------
+// Machine Trap Handling registers
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - MSCRATCH
+ // - MEPC
+ // - MCAUSE
+ // - MTVAL
+ // - MIP
+//
+
+// MSCRATCH register
+//------------------------------------------------------------------------------
+// Holds a pointer to a machine-mode hart-local context space
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mscratch_ff <= '0;
+ end else if (csr_mscratch_upd) begin
+ csr_mscratch_ff <= csr_w_data;
+ end
+end
+
+// MEPC register
+//------------------------------------------------------------------------------
+// When a trap is taken into M-mode saves the virtual address of instruction that
+// was interrupted or that encountered the exception
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mepc_ff <= '0;
+ end else begin
+ csr_mepc_ff <= csr_mepc_next;
+ end
+end
+
+always_comb begin
+ case (1'b1)
+ e_exc : csr_mepc_next = exu2csr_pc_curr_i[`SCR1_XLEN-1:PC_LSB];
+ e_irq_nmret : csr_mepc_next = exu2csr_pc_next_i[`SCR1_XLEN-1:PC_LSB];
+ csr_mepc_upd: csr_mepc_next = csr_w_data[`SCR1_XLEN-1:PC_LSB];
+ default : csr_mepc_next = csr_mepc_ff;
+ endcase
+end
+
+`ifdef SCR1_RVC_EXT
+ assign csr_mepc = {csr_mepc_ff, 1'b0};
+`else
+ assign csr_mepc = {csr_mepc_ff, 2'b00};
+`endif
+
+// MCAUSE register
+//------------------------------------------------------------------------------
+// When a trap is taken into M-mode saves a code indicating the event that caused
+// the trap
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mcause_i_ff <= 1'b0;
+ csr_mcause_ec_ff <= type_scr1_exc_code_e'(SCR1_EXC_CODE_RESET);
+ end else begin
+ csr_mcause_i_ff <= csr_mcause_i_next;
+ csr_mcause_ec_ff <= csr_mcause_ec_next;
+ end
+end
+
+always_comb begin
+ case (1'b1)
+ e_exc : begin
+ csr_mcause_i_next = 1'b0;
+ csr_mcause_ec_next = exu2csr_exc_code_i;
+ end
+ e_irq : begin
+ csr_mcause_i_next = 1'b1;
+ csr_mcause_ec_next = csr_mcause_ec_new;
+ end
+ csr_mcause_upd: begin
+ csr_mcause_i_next = csr_w_data[`SCR1_XLEN-1];
+ csr_mcause_ec_next = type_scr1_exc_code_e'(csr_w_data[SCR1_EXC_CODE_WIDTH_E-1:0]);
+ end
+ default : begin
+ csr_mcause_i_next = csr_mcause_i_ff;
+ csr_mcause_ec_next = csr_mcause_ec_ff;
+ end
+ endcase
+end
+
+// MTVAL register
+//------------------------------------------------------------------------------
+// When a trap is taken into M-mode is either set to zero or written with exception-
+// specific information
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mtval_ff <= '0;
+ end else begin
+ csr_mtval_ff <= csr_mtval_next;
+ end
+end
+
+always_comb begin
+ case (1'b1)
+ e_exc : csr_mtval_next = exu2csr_trap_val_i;
+ e_irq : csr_mtval_next = '0;
+ csr_mtval_upd: csr_mtval_next = csr_w_data;
+ default : csr_mtval_next = csr_mtval_ff;
+ endcase
+end
+
+// MIP register
+//------------------------------------------------------------------------------
+// Contains information on pending interrupts (external, software, timer IRQs)
+
+assign csr_mip_mtip = soc2csr_irq_mtimer_i;
+assign csr_mip_meip = soc2csr_irq_ext_i;
+assign csr_mip_msip = soc2csr_irq_soft_i;
+
+always_comb begin
+ csr_mip = '0;
+ csr_mip[SCR1_CSR_MIE_MSIE_OFFSET] = csr_mip_msip;
+ csr_mip[SCR1_CSR_MIE_MTIE_OFFSET] = csr_mip_mtip;
+ csr_mip[SCR1_CSR_MIE_MEIE_OFFSET] = csr_mip_meip;
+end
+
+//------------------------------------------------------------------------------
+// Machine Counters/Timers registers
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - MCYCLE
+ // - MINSTRET
+//
+
+`ifndef SCR1_CSR_REDUCED_CNT
+// MCYCLE register
+//------------------------------------------------------------------------------
+// Holds the number of clock cycles since some arbitrary point of time in the
+// past at which MCYCLE was zero
+
+assign csr_mcycle_lo_inc = 1'b1
+ `ifdef SCR1_MCOUNTEN_EN
+ & csr_mcounten_cy_ff
+ `endif // SCR1_MCOUNTEN_EN
+ ;
+assign csr_mcycle_hi_inc = csr_mcycle_lo_inc & (&csr_mcycle_lo_ff);
+
+assign csr_mcycle_lo_upd = csr_mcycle_lo_inc | csr_mcycle_upd[0];
+assign csr_mcycle_hi_upd = csr_mcycle_hi_inc | (|csr_mcycle_upd);
+
+ `ifndef SCR1_CLKCTRL_EN
+always_ff @(negedge rst_n, posedge clk) begin
+ `else // SCR1_CLKCTRL_EN
+always_ff @(negedge rst_n, posedge clk_alw_on) begin
+ `endif // SCR1_CLKCTRL_EN
+ if (~rst_n) begin
+ csr_mcycle_lo_ff <= '0;
+ csr_mcycle_hi_ff <= '0;
+ end else begin
+ if (csr_mcycle_lo_upd) csr_mcycle_lo_ff <= csr_mcycle_lo_next;
+ if (csr_mcycle_hi_upd) csr_mcycle_hi_ff <= csr_mcycle_hi_next;
+ end
+end
+
+assign csr_mcycle_hi_new = csr_mcycle_hi_ff + 1'b1;
+
+assign csr_mcycle_lo_next = csr_mcycle_upd[0] ? csr_w_data[7:0]
+ : csr_mcycle_lo_inc ? csr_mcycle_lo_ff + 1'b1
+ : csr_mcycle_lo_ff;
+assign csr_mcycle_hi_next = csr_mcycle_upd[0] ? {csr_mcycle_hi_new[63:32], csr_w_data[31:8]}
+ : csr_mcycle_upd[1] ? {csr_w_data, csr_mcycle_hi_new[31:8]}
+ : csr_mcycle_hi_inc ? csr_mcycle_hi_new
+ : csr_mcycle_hi_ff;
+
+assign csr_mcycle = {csr_mcycle_hi_ff, csr_mcycle_lo_ff};
+
+// MINSTRET register
+//------------------------------------------------------------------------------
+// Holds the number of instructions executed by the core from some arbitrary time
+// in the past at which MINSTRET was equal to zero
+
+assign csr_minstret_lo_inc = exu2csr_instret_no_exc_i
+ `ifdef SCR1_MCOUNTEN_EN
+ & csr_mcounten_ir_ff
+ `endif // SCR1_MCOUNTEN_EN
+ ;
+assign csr_minstret_hi_inc = csr_minstret_lo_inc & (&csr_minstret_lo_ff);
+
+assign csr_minstret_lo_upd = csr_minstret_lo_inc | csr_minstret_upd[0];
+assign csr_minstret_hi_upd = csr_minstret_hi_inc | (|csr_minstret_upd);
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_minstret_lo_ff <= '0;
+ csr_minstret_hi_ff <= '0;
+ end else begin
+ if (csr_minstret_lo_upd) csr_minstret_lo_ff <= csr_minstret_lo_next;
+ if (csr_minstret_hi_upd) csr_minstret_hi_ff <= csr_minstret_hi_next;
+ end
+end
+
+assign csr_minstret_hi_new = csr_minstret_hi_ff + 1'b1;
+
+assign csr_minstret_lo_next = csr_minstret_upd[0] ? csr_w_data[7:0]
+ : csr_minstret_lo_inc ? csr_minstret_lo_ff + 1'b1
+ : csr_minstret_lo_ff;
+assign csr_minstret_hi_next = csr_minstret_upd[0] ? {csr_minstret_hi_new[63:32], csr_w_data[31:8]}
+ : csr_minstret_upd[1] ? {csr_w_data, csr_minstret_hi_new[31:8]}
+ : csr_minstret_hi_inc ? csr_minstret_hi_new
+ : csr_minstret_hi_ff;
+
+assign csr_minstret = {csr_minstret_hi_ff, csr_minstret_lo_ff};
+`endif // SCR1_CSR_REDUCED_CNT
+
+//------------------------------------------------------------------------------
+// Non-standard CSR
+//------------------------------------------------------------------------------
+
+`ifdef SCR1_MCOUNTEN_EN
+// MCOUNTEN register
+//------------------------------------------------------------------------------
+// Holds Counters enable bits (CY - MCYCLE counter; IR - MINSTRET counter)
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_mcounten_cy_ff <= 1'b1;
+ csr_mcounten_ir_ff <= 1'b1;
+ end else if (csr_mcounten_upd) begin
+ csr_mcounten_cy_ff <= csr_w_data[SCR1_CSR_MCOUNTEN_CY_OFFSET];
+ csr_mcounten_ir_ff <= csr_w_data[SCR1_CSR_MCOUNTEN_IR_OFFSET];
+ end
+end
+
+always_comb begin
+ csr_mcounten = '0;
+ csr_mcounten[SCR1_CSR_MCOUNTEN_CY_OFFSET] = csr_mcounten_cy_ff;
+ csr_mcounten[SCR1_CSR_MCOUNTEN_IR_OFFSET] = csr_mcounten_ir_ff;
+end
+`endif // SCR1_MCOUNTEN_EN
+
+//------------------------------------------------------------------------------
+// CSR <-> EXU interface
+//------------------------------------------------------------------------------
+
+// CSR exception
+assign csr2exu_rw_exc_o = csr_r_exc | csr_w_exc
+`ifdef SCR1_DBG_EN
+ | (csr2hdu_req_o & (hdu2csr_resp_i != SCR1_CSR_RESP_OK))
+`endif // SCR1_DBG_EN
+`ifdef SCR1_TDU_EN
+ | (csr2tdu_req_o & (tdu2csr_resp_i != SCR1_CSR_RESP_OK))
+`endif // SCR1_TDU_EN
+ ;
+assign csr2exu_ip_ie_o = csr_eirq_pnd_en | csr_sirq_pnd_en | csr_tirq_pnd_en;
+assign csr2exu_irq_o = csr2exu_ip_ie_o & csr_mstatus_mie_ff;
+
+assign csr2exu_mstatus_mie_up_o = csr_mstatus_upd | csr_mie_upd | e_mret;
+
+// New PC multiplexer
+`ifndef SCR1_MTVEC_MODE_EN
+assign csr2exu_new_pc_o = (exu2csr_mret_instr_i & ~exu2csr_take_irq_i)
+ ? csr_mepc
+ : {csr_mtvec_base, SCR1_CSR_MTVEC_BASE_ZERO_BITS'(0)};
+`else // SCR1_MTVEC_MODE_EN
+always_comb begin
+ if (exu2csr_mret_instr_i & ~exu2csr_take_irq_i) begin
+ csr2exu_new_pc_o = csr_mepc;
+ end else begin
+ if (csr_mtvec_mode_vect) begin
+ case (1'b1)
+ exu2csr_take_exc_i: csr2exu_new_pc_o = {csr_mtvec_base, SCR1_CSR_MTVEC_BASE_ZERO_BITS'(0)};
+ csr_eirq_pnd_en : csr2exu_new_pc_o = {csr_mtvec_base, SCR1_EXC_CODE_IRQ_M_EXTERNAL, 2'd0};
+ csr_sirq_pnd_en : csr2exu_new_pc_o = {csr_mtvec_base, SCR1_EXC_CODE_IRQ_M_SOFTWARE, 2'd0};
+ csr_tirq_pnd_en : csr2exu_new_pc_o = {csr_mtvec_base, SCR1_EXC_CODE_IRQ_M_TIMER, 2'd0};
+ default : csr2exu_new_pc_o = {csr_mtvec_base, SCR1_CSR_MTVEC_BASE_ZERO_BITS'(0)};
+ endcase
+ end else begin // direct mode
+ csr2exu_new_pc_o = {csr_mtvec_base, SCR1_CSR_MTVEC_BASE_ZERO_BITS'(0)};
+ end
+ end
+end
+`endif // SCR1_MTVEC_MODE_EN
+
+`ifdef SCR1_IPIC_EN
+//------------------------------------------------------------------------------
+// CSR <-> IPIC interface
+//------------------------------------------------------------------------------
+
+assign csr_ipic_req = csr2ipic_r_req_o | csr2ipic_w_req_o;
+assign csr2ipic_addr_o = csr_ipic_req ? exu2csr_rw_addr_i[2:0] : '0;
+assign csr2ipic_wdata_o = csr2ipic_w_req_o ? exu2csr_w_data_i : '0;
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_DBG_EN
+//------------------------------------------------------------------------------
+// CSR <-> HDU interface
+//------------------------------------------------------------------------------
+
+assign csr2hdu_req_o = csr_hdu_req & exu_req_no_exc;
+assign csr2hdu_cmd_o = exu2csr_w_cmd_i;
+assign csr2hdu_addr_o = exu2csr_rw_addr_i[SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0];
+assign csr2hdu_wdata_o = exu2csr_w_data_i;
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+//------------------------------------------------------------------------------
+// CSR <-> TDU interface
+//------------------------------------------------------------------------------
+
+assign csr2tdu_req_o = csr_brkm_req & exu_req_no_exc;
+assign csr2tdu_cmd_o = exu2csr_w_cmd_i;
+assign csr2tdu_addr_o = exu2csr_rw_addr_i[SCR1_CSR_ADDR_TDU_OFFS_W-1:0];
+assign csr2tdu_wdata_o = exu2csr_w_data_i;
+`endif // SCR1_TDU_EN
+
+`ifdef SCR1_TRGT_SIMULATION
+//------------------------------------------------------------------------------
+// Assertions
+//------------------------------------------------------------------------------
+
+// X checks
+
+SCR1_SVA_CSR_XCHECK_CTRL : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({exu2csr_r_req_i, exu2csr_w_req_i, exu2csr_take_irq_i, exu2csr_take_exc_i, exu2csr_mret_update_i
+`ifndef SCR1_CSR_REDUCED_CNT
+ , exu2csr_instret_no_exc_i
+`endif // SCR1_CSR_REDUCED_CNT
+ })
+ ) else $error("CSR Error: unknown control values");
+
+SCR1_SVA_CSR_XCHECK_READ : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2csr_r_req_i |-> !$isunknown({exu2csr_rw_addr_i, csr2exu_r_data_o, csr2exu_rw_exc_o})
+ ) else $error("CSR Error: unknown control values");
+
+SCR1_SVA_CSR_XCHECK_WRITE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2csr_w_req_i |-> !$isunknown({exu2csr_rw_addr_i, exu2csr_w_cmd_i, exu2csr_w_data_i, csr2exu_rw_exc_o})
+ ) else $error("CSR Error: unknown control values");
+
+`ifdef SCR1_IPIC_EN
+SCR1_SVA_CSR_XCHECK_READ_IPIC : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ csr2ipic_r_req_o |-> !$isunknown({csr2ipic_addr_o, ipic2csr_rdata_i})
+ ) else $error("CSR Error: unknown control values");
+
+SCR1_SVA_CSR_XCHECK_WRITE_IPIC : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ csr2ipic_w_req_o |-> !$isunknown({csr2ipic_addr_o, csr2ipic_wdata_o})
+ ) else $error("CSR Error: unknown control values");
+`endif // SCR1_IPIC_EN
+
+// Behavior checks
+
+SCR1_SVA_CSR_MRET : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ e_mret |=> ($stable(csr_mepc_ff) & $stable(csr_mtval_ff))
+ ) else $error("CSR Error: MRET wrong behavior");
+
+SCR1_SVA_CSR_MRET_IRQ : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (exu2csr_mret_instr_i & e_irq)
+ |=> ($stable(csr_mepc_ff) & (exu2csr_pc_curr_i != csr_mepc))
+ ) else $error("CSR Error: MRET+IRQ wrong behavior");
+
+SCR1_SVA_CSR_EXC_IRQ : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (exu2csr_take_exc_i & exu2csr_take_irq_i
+`ifdef SCR1_DBG_EN
+ & ~hdu2csr_no_commit_i
+`endif
+ ) |=>
+ (~csr_mstatus_mie_ff & (~csr_mcause_i_ff)
+ & (exu2csr_pc_curr_i=={csr_mtvec_base, SCR1_CSR_MTVEC_BASE_ZERO_BITS'(0)}))
+ ) else $error("CSR Error: wrong EXC+IRQ");
+
+SCR1_SVA_CSR_EVENTS : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ $onehot0({e_irq, e_exc, e_mret})
+ ) else $error("CSR Error: more than one event at a time");
+
+SCR1_SVA_CSR_RW_EXC : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ csr2exu_rw_exc_o |-> (exu2csr_w_req_i | exu2csr_r_req_i)
+ ) else $error("CSR Error: impossible exception");
+
+SCR1_SVA_CSR_MSTATUS_MIE_UP : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ csr2exu_mstatus_mie_up_o |=> ~csr2exu_mstatus_mie_up_o
+ ) else $error("CSR Error: csr2exu_mstatus_mie_up_o can only be high for one mcycle");
+
+
+`ifndef SCR1_CSR_REDUCED_CNT
+
+SCR1_SVA_CSR_CYCLE_INC : assert property (
+ @(
+`ifndef SCR1_CLKCTRL_EN
+negedge clk
+`else // SCR1_CLKCTRL_EN
+negedge clk_alw_on
+`endif // SCR1_CLKCTRL_EN
+ ) disable iff (~rst_n)
+ (~|csr_mcycle_upd) |=>
+`ifdef SCR1_MCOUNTEN_EN
+ ($past(csr_mcounten_cy_ff) ? (csr_mcycle == $past(csr_mcycle + 1'b1)) : $stable(csr_mcycle))
+`else //SCR1_MCOUNTEN_EN
+ (csr_mcycle == $past(csr_mcycle + 1'b1))
+`endif // SCR1_MCOUNTEN_EN
+ ) else $error("CSR Error: CYCLE increment wrong behavior");
+
+SCR1_SVA_CSR_INSTRET_INC : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (exu2csr_instret_no_exc_i & ~|csr_minstret_upd) |=>
+`ifdef SCR1_MCOUNTEN_EN
+ ($past(csr_mcounten_ir_ff) ? (csr_minstret == $past(csr_minstret + 1'b1)) : $stable(csr_minstret))
+`else //SCR1_MCOUNTEN_EN
+ (csr_minstret == $past(csr_minstret + 1'b1))
+`endif // SCR1_MCOUNTEN_EN
+ ) else $error("CSR Error: INSTRET increment wrong behavior");
+
+SCR1_SVA_CSR_CYCLE_INSTRET_UP : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ ~(&csr_minstret_upd | &csr_mcycle_upd)
+ ) else $error("CSR Error: INSTRET/CYCLE up illegal value");
+
+`endif // SCR1_CSR_REDUCED_CNT
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_csr
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_exu.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_exu.sv
new file mode 100644
index 0000000..f518a84
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_exu.sv
@@ -0,0 +1,1061 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_exu.sv>
+/// @brief Execution Unit (EXU)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Performs instructions execution:
+ // - Prevents instructions from execution if the HART is in WFI or Debug Halted
+ // state
+ // - Fetches operands for IALU
+ // - Calculates operation results via IALU
+ // - Stores IALU results in MPRF
+ // - Performs LOAD/STORE operations via LSU
+ // - Handles exceptions:
+ // - Generates exception request
+ // - Encodes exception code
+ // - Calculates exception trap value
+ // - Controls WFI instruction execution
+ // - Calculates PC value:
+ // - Initializes PC on reset
+ // - Stores the current PC value
+ // - Calculates a New PC value and generates a New PC request to IFU
+ //
+ // Structure:
+ // - Instruction queue
+ // - Integer Arithmetic Logic Unit (IALU)
+ // - Exceptions logic
+ // - WFI logic
+ // - Program Counter logic
+ // - Load-Store Unit (LSU)
+ // - EXU status logic
+ // - EXU <-> MPRF i/f
+ // - EXU <-> CSR i/f
+ // - EXU <-> TDU i/f
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+`include "scr1_arch_types.svh"
+`include "scr1_memif.svh"
+`include "scr1_riscv_isa_decoding.svh"
+`include "scr1_csr.svh"
+
+`ifdef SCR1_DBG_EN
+ `include "scr1_hdu.svh"
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+ `include "scr1_tdu.svh"
+`endif // SCR1_TDU_EN
+
+module scr1_pipe_exu (
+ // Common
+ input logic rst_n, // EXU reset
+ input logic clk, // Gated EXU clock
+`ifdef SCR1_CLKCTRL_EN
+ input logic clk_alw_on, // Not-gated EXU clock
+ input logic clk_pipe_en, // EXU clock enabled flag
+`endif // SCR1_CLKCTRL_EN
+
+ // EXU <-> IDU interface
+ input logic idu2exu_req_i, // Request form IDU to EXU
+ output logic exu2idu_rdy_o, // EXU ready for new data from IDU
+ input type_scr1_exu_cmd_s idu2exu_cmd_i, // EXU command
+ input logic idu2exu_use_rs1_i, // Clock gating on rs1_addr field
+ input logic idu2exu_use_rs2_i, // Clock gating on rs2_addr field
+`ifndef SCR1_NO_EXE_STAGE
+ input logic idu2exu_use_rd_i, // Clock gating on rd_addr field
+ input logic idu2exu_use_imm_i, // Clock gating on imm field
+`endif // SCR1_NO_EXE_STAGE
+
+ // EXU <-> MPRF interface
+ output logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr_o, // MPRF rs1 read address
+ input logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data_i, // MPRF rs1 read data
+ output logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr_o, // MPRF rs2 read address
+ input logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data_i, // MPRF rs2 read data
+ output logic exu2mprf_w_req_o, // MPRF write request
+ output logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr_o, // MPRF rd write address
+ output logic [`SCR1_XLEN-1:0] exu2mprf_rd_data_o, // MPRF rd write data
+
+ // EXU <-> CSR read/write interface
+ output logic [SCR1_CSR_ADDR_WIDTH-1:0] exu2csr_rw_addr_o, // CSR read/write address
+ output logic exu2csr_r_req_o, // CSR read request
+ input logic [`SCR1_XLEN-1:0] csr2exu_r_data_i, // CSR read data
+ output logic exu2csr_w_req_o, // CSR write request
+ output type_scr1_csr_cmd_sel_e exu2csr_w_cmd_o, // CSR write command
+ output logic [`SCR1_XLEN-1:0] exu2csr_w_data_o, // CSR write data
+ input logic csr2exu_rw_exc_i, // CSR read/write access exception
+
+ // EXU <-> CSR events interface
+ output logic exu2csr_take_irq_o, // Take IRQ trap
+ output logic exu2csr_take_exc_o, // Take exception trap
+ output logic exu2csr_mret_update_o, // MRET update CSR
+ output logic exu2csr_mret_instr_o, // MRET instruction
+ output type_scr1_exc_code_e exu2csr_exc_code_o, // Exception code (see scr1_arch_types.svh)
+ output logic [`SCR1_XLEN-1:0] exu2csr_trap_val_o, // Trap value
+ input logic [`SCR1_XLEN-1:0] csr2exu_new_pc_i, // Exception/IRQ/MRET new PC
+ input logic csr2exu_irq_i, // IRQ request
+ input logic csr2exu_ip_ie_i, // Some IRQ pending and locally enabled
+ input logic csr2exu_mstatus_mie_up_i, // MSTATUS or MIE update in the current cycle
+
+ // EXU <-> DMEM interface
+ output logic exu2dmem_req_o, // Data memory request
+ output type_scr1_mem_cmd_e exu2dmem_cmd_o, // Data memory command
+ output type_scr1_mem_width_e exu2dmem_width_o, // Data memory width
+ output logic [`SCR1_DMEM_AWIDTH-1:0] exu2dmem_addr_o, // Data memory address
+ output logic [`SCR1_DMEM_DWIDTH-1:0] exu2dmem_wdata_o, // Data memory write data
+ input logic dmem2exu_req_ack_i, // Data memory request acknowledge
+ input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2exu_rdata_i, // Data memory read data
+ input type_scr1_mem_resp_e dmem2exu_resp_i, // Data memory response
+
+ // EXU control
+ output logic exu2pipe_exc_req_o, // Exception on last instruction
+ output logic exu2pipe_brkpt_o, // Software Breakpoint (EBREAK)
+ output logic exu2pipe_init_pc_o, // Reset exit
+ output logic exu2pipe_wfi_run2halt_o, // Transition to WFI halted state
+ output logic exu2pipe_instret_o, // Instruction retired (with or without exception)
+ output logic exu2csr_instret_no_exc_o, // Instruction retired (without exception)
+ output logic exu2pipe_exu_busy_o, // EXU busy
+
+`ifdef SCR1_DBG_EN
+ // EXU <-> HDU interface
+ input logic hdu2exu_no_commit_i, // Forbid instruction commitment
+ input logic hdu2exu_irq_dsbl_i, // Disable IRQ
+ input logic hdu2exu_pc_advmt_dsbl_i, // Forbid PC advancement
+ input logic hdu2exu_dmode_sstep_en_i, // Enable single-step
+ input logic hdu2exu_pbuf_fetch_i, // Take instructions from Program Buffer
+ input logic hdu2exu_dbg_halted_i, // Debug halted state
+ input logic hdu2exu_dbg_run2halt_i, // Transition to debug halted state
+ input logic hdu2exu_dbg_halt2run_i, // Transition to run state
+ input logic hdu2exu_dbg_run_start_i, // First cycle of run state
+ input logic [`SCR1_XLEN-1:0] hdu2exu_dbg_new_pc_i, // New PC as starting point for HART Resume
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+ // EXU <-> TDU interface
+ output type_scr1_brkm_instr_mon_s exu2tdu_imon_o, // Instruction monitor
+ input logic [SCR1_TDU_ALLTRIG_NUM-1:0] tdu2exu_ibrkpt_match_i, // Instruction breakpoint(s) match
+ input logic tdu2exu_ibrkpt_exc_req_i, // Instruction breakpoint exception
+ output type_scr1_brkm_lsu_mon_s lsu2tdu_dmon_o, // Data monitor
+ input logic tdu2lsu_ibrkpt_exc_req_i, // Instruction breakpoint exception
+ input logic [SCR1_TDU_MTRIG_NUM-1:0] tdu2lsu_dbrkpt_match_i, // Data breakpoint(s) match
+ input logic tdu2lsu_dbrkpt_exc_req_i, // Data breakpoint exception
+ output logic [SCR1_TDU_ALLTRIG_NUM-1:0] exu2tdu_ibrkpt_ret_o, // Instruction with breakpoint flag retire
+ output logic exu2hdu_ibrkpt_hw_o, // Hardware breakpoint on current instruction
+`endif // SCR1_TDU_EN
+
+ // PC interface
+`ifdef SCR1_CLKCTRL_EN
+ output logic exu2pipe_wfi_halted_o, // WFI halted state
+`endif // SCR1_CLKCTRL_EN
+ output logic [`SCR1_XLEN-1:0] exu2pipe_pc_curr_o, // Current PC
+ output logic [`SCR1_XLEN-1:0] exu2csr_pc_next_o, // Next PC
+ output logic exu2ifu_pc_new_req_o, // New PC request
+ output logic [`SCR1_XLEN-1:0] exu2ifu_pc_new_o // New PC data
+);
+
+//------------------------------------------------------------------------------
+// Local parameters declaration
+//------------------------------------------------------------------------------
+
+localparam SCR1_JUMP_MASK = `SCR1_XLEN'hFFFF_FFFE;
+
+//------------------------------------------------------------------------------
+// Local types declaration
+//------------------------------------------------------------------------------
+
+typedef enum logic {
+ SCR1_CSR_INIT,
+ SCR1_CSR_RDY
+} scr1_csr_access_e;
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// Instruction queue signals
+//------------------------------------------------------------------------------
+logic exu_queue_vd;
+type_scr1_exu_cmd_s exu_queue;
+logic exu_queue_barrier;
+
+`ifdef SCR1_DBG_EN
+logic dbg_run_start_npbuf;
+`endif // SCR1_DBG_EN
+logic exu_queue_en;
+logic [`SCR1_XLEN-1:0] exu_illegal_instr;
+
+`ifndef SCR1_NO_EXE_STAGE
+logic idu2exu_use_rs1_ff;
+logic idu2exu_use_rs2_ff;
+
+// EXU queue valid flag register signals
+logic exu_queue_vd_upd;
+logic exu_queue_vd_ff;
+logic exu_queue_vd_next;
+`endif // SCR1_NO_EXE_STAGE
+
+// IALU signals
+//------------------------------------------------------------------------------
+`ifdef SCR1_RVM_EXT
+logic ialu_rdy;
+logic ialu_vd;
+`endif // SCR1_RVM_EXT
+logic [`SCR1_XLEN-1:0] ialu_main_op1;
+logic [`SCR1_XLEN-1:0] ialu_main_op2;
+logic [`SCR1_XLEN-1:0] ialu_main_res;
+logic [`SCR1_XLEN-1:0] ialu_addr_op1;
+logic [`SCR1_XLEN-1:0] ialu_addr_op2;
+logic [`SCR1_XLEN-1:0] ialu_addr_res;
+logic ialu_cmp;
+
+// Exceptions signals
+//------------------------------------------------------------------------------
+logic exu_exc_req;
+`ifdef SCR1_DBG_EN
+logic exu_exc_req_ff;
+logic exu_exc_req_next;
+`endif // SCR1_DBG_EN
+type_scr1_exc_code_e exc_code;
+logic [`SCR1_XLEN-1:0] exc_trap_val;
+logic instr_fault_rvi_hi;
+
+// WFI signals
+//------------------------------------------------------------------------------
+// WFI control signals
+logic wfi_halt_cond;
+logic wfi_run_req;
+logic wfi_halt_req;
+
+// WFI Run Start register
+logic wfi_run_start_ff;
+logic wfi_run_start_next;
+
+// WFI halted register
+logic wfi_halted_upd;
+logic wfi_halted_ff;
+logic wfi_halted_next;
+
+// PC signals
+//------------------------------------------------------------------------------
+logic [3:0] init_pc_v;
+logic init_pc;
+logic [`SCR1_XLEN-1:0] inc_pc;
+
+logic branch_taken;
+logic jb_taken;
+logic [`SCR1_XLEN-1:0] jb_new_pc;
+`ifndef SCR1_RVC_EXT
+logic jb_misalign;
+`endif
+
+// Current PC register
+logic pc_curr_upd;
+logic [`SCR1_XLEN-1:0] pc_curr_ff;
+logic [`SCR1_XLEN-1:0] pc_curr_next;
+
+// LSU signals
+//------------------------------------------------------------------------------
+logic lsu_req;
+logic lsu_rdy;
+logic [`SCR1_XLEN-1:0] lsu_l_data;
+logic lsu_exc_req;
+type_scr1_exc_code_e lsu_exc_code;
+
+// EXU status signals
+//------------------------------------------------------------------------------
+logic exu_rdy;
+
+// MPRF signals
+//------------------------------------------------------------------------------
+logic mprf_rs1_req;
+logic mprf_rs2_req;
+
+logic [`SCR1_MPRF_AWIDTH-1:0] mprf_rs1_addr;
+logic [`SCR1_MPRF_AWIDTH-1:0] mprf_rs2_addr;
+
+// CSR signals
+//------------------------------------------------------------------------------
+// CSR access register
+scr1_csr_access_e csr_access_ff;
+scr1_csr_access_e csr_access_next;
+logic csr_access_init;
+
+//------------------------------------------------------------------------------
+// Instruction execution queue
+//------------------------------------------------------------------------------
+//
+ // Instruction execution queue consists of the following functional units:
+ // - EXU queue control logic
+ // - EXU queue valid flag register
+ // - EXU queue register
+ // - EXU queue status logic
+//
+
+`ifdef SCR1_DBG_EN
+assign dbg_run_start_npbuf = hdu2exu_dbg_run_start_i & ~hdu2exu_pbuf_fetch_i;
+`endif // SCR1_DBG_EN
+
+`ifndef SCR1_NO_EXE_STAGE
+
+// EXU queue control logic
+//------------------------------------------------------------------------------
+
+assign exu_queue_barrier = wfi_halted_ff | wfi_halt_req | wfi_run_start_ff
+`ifdef SCR1_DBG_EN
+ | hdu2exu_dbg_halted_i | hdu2exu_dbg_run2halt_i
+ | dbg_run_start_npbuf
+`endif // SCR1_DBG_EN
+;
+
+assign exu_queue_en = exu2idu_rdy_o & idu2exu_req_i;
+
+// EXU queue valid flag register
+//------------------------------------------------------------------------------
+
+assign exu_queue_vd_upd = exu_queue_barrier | exu_rdy;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ exu_queue_vd_ff <= 1'b0;
+ end else if (exu_queue_vd_upd) begin
+ exu_queue_vd_ff <= exu_queue_vd_next;
+ end
+end
+
+assign exu_queue_vd_next = ~exu_queue_barrier & idu2exu_req_i & ~exu2ifu_pc_new_req_o;
+assign exu_queue_vd = exu_queue_vd_ff;
+
+// EXU queue register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (exu_queue_en) begin
+ exu_queue.instr_rvc <= idu2exu_cmd_i.instr_rvc;
+ exu_queue.ialu_op <= idu2exu_cmd_i.ialu_op;
+ exu_queue.ialu_cmd <= idu2exu_cmd_i.ialu_cmd;
+ exu_queue.sum2_op <= idu2exu_cmd_i.sum2_op;
+ exu_queue.lsu_cmd <= idu2exu_cmd_i.lsu_cmd;
+ exu_queue.csr_op <= idu2exu_cmd_i.csr_op;
+ exu_queue.csr_cmd <= idu2exu_cmd_i.csr_cmd;
+ exu_queue.rd_wb_sel <= idu2exu_cmd_i.rd_wb_sel;
+ exu_queue.jump_req <= idu2exu_cmd_i.jump_req;
+ exu_queue.branch_req <= idu2exu_cmd_i.branch_req;
+ exu_queue.mret_req <= idu2exu_cmd_i.mret_req;
+ exu_queue.fencei_req <= idu2exu_cmd_i.fencei_req;
+ exu_queue.wfi_req <= idu2exu_cmd_i.wfi_req;
+ exu_queue.exc_req <= idu2exu_cmd_i.exc_req;
+ exu_queue.exc_code <= idu2exu_cmd_i.exc_code;
+ idu2exu_use_rs1_ff <= idu2exu_use_rs1_i;
+ idu2exu_use_rs2_ff <= idu2exu_use_rs2_i;
+ if (idu2exu_use_rs1_i) begin
+ exu_queue.rs1_addr <= idu2exu_cmd_i.rs1_addr;
+ end
+ if (idu2exu_use_rs2_i) begin
+ exu_queue.rs2_addr <= idu2exu_cmd_i.rs2_addr;
+ end
+ if (idu2exu_use_rd_i) begin
+ exu_queue.rd_addr <= idu2exu_cmd_i.rd_addr;
+ end
+ if (idu2exu_use_imm_i) begin
+ exu_queue.imm <= idu2exu_cmd_i.imm;
+ end
+ end
+end
+
+`else // ~SCR1_NO_EXE_STAGE
+
+assign exu_queue_barrier = wfi_halted_ff | wfi_run_start_ff
+`ifdef SCR1_DBG_EN
+ | hdu2exu_dbg_halted_i | dbg_run_start_npbuf
+`endif // SCR1_DBG_EN
+;
+assign exu_queue_vd = idu2exu_req_i & ~exu_queue_barrier;
+assign exu_queue = idu2exu_cmd_i;
+
+`endif // ~SCR1_NO_EXE_STAGE
+
+//------------------------------------------------------------------------------
+// Integer Arithmetic Logic Unit (IALU)
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Performs addition/subtraction and arithmetic and branch comparisons
+ // - Performs logical operations (AND(I), OR(I), XOR(I))
+ // - Performs address calculation for branch, jump, DMEM load and store and AUIPC
+ // instructions
+ // - Performs shift operations
+ // - Performs MUL/DIV operations
+ //
+//------------------------------------------------------------------------------
+
+// IALU main operands fetch
+//------------------------------------------------------------------------------
+
+`ifdef SCR1_RVM_EXT
+assign ialu_vd = exu_queue_vd & (exu_queue.ialu_cmd != SCR1_IALU_CMD_NONE)
+`ifdef SCR1_TDU_EN
+ & ~tdu2exu_ibrkpt_exc_req_i
+`endif // SCR1_TDU_EN
+ ;
+`endif // SCR1_RVM_EXT
+
+always_comb begin
+`ifdef SCR1_RVM_EXT
+ if (~ialu_vd) begin
+ ialu_main_op1 = '0;
+ ialu_main_op2 = '0;
+ end else begin
+`endif // SCR1_RVM_EXT
+ if (exu_queue.ialu_op == SCR1_IALU_OP_REG_REG) begin
+ ialu_main_op1 = mprf2exu_rs1_data_i;
+ ialu_main_op2 = mprf2exu_rs2_data_i;
+ end else begin
+ ialu_main_op1 = mprf2exu_rs1_data_i;
+ ialu_main_op2 = exu_queue.imm;
+ end
+`ifdef SCR1_RVM_EXT
+ end
+`endif // SCR1_RVM_EXT
+end
+
+// IALU address operands fetch
+//------------------------------------------------------------------------------
+
+always_comb begin
+ if (exu_queue.sum2_op == SCR1_SUM2_OP_REG_IMM) begin
+ ialu_addr_op1 = mprf2exu_rs1_data_i;
+ ialu_addr_op2 = exu_queue.imm;
+ end else begin
+ ialu_addr_op1 = pc_curr_ff;
+ ialu_addr_op2 = exu_queue.imm;
+ end
+end
+
+// IALU module instantiation
+//------------------------------------------------------------------------------
+
+scr1_pipe_ialu i_ialu(
+`ifdef SCR1_RVM_EXT
+ // Common
+ .clk (clk ),
+ .rst_n (rst_n ),
+ .exu2ialu_rvm_cmd_vd_i (ialu_vd ),
+ .ialu2exu_rvm_res_rdy_o (ialu_rdy ),
+`endif // SCR1_RVM_EXT
+
+ // IALU
+ .exu2ialu_main_op1_i (ialu_main_op1 ),
+ .exu2ialu_main_op2_i (ialu_main_op2 ),
+ .exu2ialu_cmd_i (exu_queue.ialu_cmd),
+ .ialu2exu_main_res_o (ialu_main_res ),
+ .ialu2exu_cmp_res_o (ialu_cmp ),
+
+ // Address adder signals
+ .exu2ialu_addr_op1_i (ialu_addr_op1 ),
+ .exu2ialu_addr_op2_i (ialu_addr_op2 ),
+ .ialu2exu_addr_res_o (ialu_addr_res )
+);
+
+//------------------------------------------------------------------------------
+// Exceptions logic
+//------------------------------------------------------------------------------
+//
+ // Exceptions logic consists of the following functional units:
+ // - Exception request logic
+ // - Exception code encoder
+ // - Exception trap value multiplexer
+ //
+//
+
+`ifndef SCR1_RVC_EXT
+assign jb_misalign = exu_queue_vd & jb_taken & |jb_new_pc[1:0];
+`endif // ~SCR1_RVC_EXT
+
+// Exception request
+assign exu_exc_req = exu_queue_vd & (exu_queue.exc_req | lsu_exc_req
+ | csr2exu_rw_exc_i
+`ifndef SCR1_RVC_EXT
+ | jb_misalign
+`endif // ~SCR1_RVC_EXT
+`ifdef SCR1_TDU_EN
+ | exu2hdu_ibrkpt_hw_o
+`endif // SCR1_TDU_EN
+ );
+
+// EXU exception request register
+//------------------------------------------------------------------------------
+
+`ifdef SCR1_DBG_EN
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ exu_exc_req_ff <= 1'b0;
+ end else begin
+ exu_exc_req_ff <= exu_exc_req_next;
+ end
+end
+
+assign exu_exc_req_next = hdu2exu_dbg_halt2run_i ? 1'b0 : exu_exc_req;
+`endif // SCR1_DBG_EN
+
+// Exception code encoder
+//------------------------------------------------------------------------------
+
+always_comb begin
+ case (1'b1)
+`ifdef SCR1_TDU_EN
+ exu2hdu_ibrkpt_hw_o: exc_code = SCR1_EXC_CODE_BREAKPOINT;
+`endif // SCR1_TDU_EN
+ exu_queue.exc_req : exc_code = exu_queue.exc_code;
+ lsu_exc_req : exc_code = lsu_exc_code;
+ csr2exu_rw_exc_i : exc_code = SCR1_EXC_CODE_ILLEGAL_INSTR;
+`ifndef SCR1_RVC_EXT
+ jb_misalign : exc_code = SCR1_EXC_CODE_INSTR_MISALIGN;
+`endif // ~SCR1_RVC_EXT
+ default : exc_code = SCR1_EXC_CODE_ECALL_M;
+ endcase // 1'b1
+end
+
+// Exception trap value multiplexer
+//------------------------------------------------------------------------------
+
+assign instr_fault_rvi_hi = exu_queue.instr_rvc;
+assign exu_illegal_instr = {exu2csr_rw_addr_o, // CSR address
+ 5'(exu_queue.rs1_addr), // rs1 / zimm
+ exu_queue.imm[14:12], // funct3
+ 5'(exu_queue.rd_addr), // rd
+ SCR1_OPCODE_SYSTEM,
+ SCR1_INSTR_RVI
+ };
+
+// If Instruction Access Fault occurred on high part of RVI instruction trap
+// value is set to point on the high part of the instruction (inc_pc=pc+2)
+always_comb begin
+ case (exc_code)
+`ifndef SCR1_RVC_EXT
+ SCR1_EXC_CODE_INSTR_MISALIGN : exc_trap_val = jb_new_pc;
+`endif // SCR1_RVC_EXT
+ SCR1_EXC_CODE_INSTR_ACCESS_FAULT: exc_trap_val = instr_fault_rvi_hi
+ ? inc_pc
+ : pc_curr_ff;
+`ifdef SCR1_MTVAL_ILLEGAL_INSTR_EN
+ SCR1_EXC_CODE_ILLEGAL_INSTR : exc_trap_val = exu_queue.exc_req
+ ? exu_queue.imm
+ : exu_illegal_instr;
+`else // SCR1_MTVAL_ILLEGAL_INSTR_EN
+ SCR1_EXC_CODE_ILLEGAL_INSTR : exc_trap_val = '0;
+`endif // SCR1_MTVAL_ILLEGAL_INSTR_EN
+`ifdef SCR1_TDU_EN
+ SCR1_EXC_CODE_BREAKPOINT: begin
+ case (1'b1)
+ tdu2exu_ibrkpt_exc_req_i: exc_trap_val = pc_curr_ff;
+ tdu2lsu_dbrkpt_exc_req_i: exc_trap_val = ialu_addr_res;
+ default : exc_trap_val = '0;
+ endcase
+ end
+`endif // SCR1_TDU_EN
+ SCR1_EXC_CODE_LD_ADDR_MISALIGN,
+ SCR1_EXC_CODE_LD_ACCESS_FAULT,
+ SCR1_EXC_CODE_ST_ADDR_MISALIGN,
+ SCR1_EXC_CODE_ST_ACCESS_FAULT : exc_trap_val = ialu_addr_res;
+ default : exc_trap_val = '0;
+ endcase // exc_code
+end
+
+//------------------------------------------------------------------------------
+// WFI logic
+//------------------------------------------------------------------------------
+//
+ // Wait for interrupt (WFI) logic consists of the following functional units:
+ // - WFI control logic
+ // - WFI Run Start register
+ // - WFI Halted flag register
+ // - WFI status signals
+//
+
+// WFI control logic
+//------------------------------------------------------------------------------
+
+assign wfi_halt_cond = ~csr2exu_ip_ie_i
+ & ((exu_queue_vd & exu_queue.wfi_req) | wfi_run_start_ff)
+`ifdef SCR1_DBG_EN
+ & ~hdu2exu_no_commit_i & ~hdu2exu_dmode_sstep_en_i & ~hdu2exu_dbg_run2halt_i
+`endif // SCR1_DBG_EN
+ ;
+assign wfi_halt_req = ~wfi_halted_ff & wfi_halt_cond;
+
+// HART will exit WFI halted state if the event that causes the HART to resume
+// execution occurs even if it doesn't cause an interrupt to be taken
+assign wfi_run_req = wfi_halted_ff & (csr2exu_ip_ie_i
+`ifdef SCR1_DBG_EN
+ | hdu2exu_dbg_halt2run_i
+`endif // SCR1_DBG_EN
+ );
+
+// WFI Run Start register
+//------------------------------------------------------------------------------
+
+`ifndef SCR1_CLKCTRL_EN
+always_ff @(negedge rst_n, posedge clk) begin
+`else // SCR1_CLKCTRL_EN
+always_ff @(negedge rst_n, posedge clk_alw_on) begin
+`endif // SCR1_CLKCTRL_EN
+ if (~rst_n) begin
+ wfi_run_start_ff <= 1'b0;
+ end else begin
+ wfi_run_start_ff <= wfi_run_start_next;
+ end
+end
+
+assign wfi_run_start_next = wfi_halted_ff & csr2exu_ip_ie_i & ~exu2csr_take_irq_o;
+
+// WFI halted flag register
+//------------------------------------------------------------------------------
+
+assign wfi_halted_upd = wfi_halt_req | wfi_run_req;
+
+`ifndef SCR1_CLKCTRL_EN
+always_ff @(negedge rst_n, posedge clk) begin
+`else // SCR1_CLKCTRL_EN
+always_ff @(negedge rst_n, posedge clk_alw_on) begin
+`endif // SCR1_CLKCTRL_EN
+ if (~rst_n) begin
+ wfi_halted_ff <= 1'b0;
+ end else if (wfi_halted_upd) begin
+ wfi_halted_ff <= wfi_halted_next;
+ end
+end
+
+assign wfi_halted_next = wfi_halt_req | ~wfi_run_req;
+
+// WFI status signals
+//------------------------------------------------------------------------------
+
+assign exu2pipe_wfi_run2halt_o = wfi_halt_req;
+`ifdef SCR1_CLKCTRL_EN
+assign exu2pipe_wfi_halted_o = wfi_halted_ff;
+`endif // SCR1_CLKCTRL_EN
+
+//------------------------------------------------------------------------------
+// Program Counter logic
+//------------------------------------------------------------------------------
+//
+ // PC logic consists of the following functional units:
+ // - PC initialization logic
+ // - Current PC register
+ // - New PC multiplexer
+
+// PC initialization logic
+//------------------------------------------------------------------------------
+// Generates a New PC request to set PC to reset value
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ init_pc_v <= '0;
+ end else begin
+ if (~&init_pc_v) begin
+ init_pc_v <= {init_pc_v[2:0], 1'b1};
+ end
+ end
+end
+
+assign init_pc = ~init_pc_v[3] & init_pc_v[2];
+
+// Current PC register
+//------------------------------------------------------------------------------
+
+assign pc_curr_upd = ((exu2pipe_instret_o | exu2csr_take_irq_o
+`ifdef SCR1_DBG_EN
+ | dbg_run_start_npbuf) & ( ~hdu2exu_pc_advmt_dsbl_i
+ & ~hdu2exu_no_commit_i
+`endif // SCR1_DBG_EN
+ ));
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ pc_curr_ff <= SCR1_RST_VECTOR;
+ end else if (pc_curr_upd) begin
+ pc_curr_ff <= pc_curr_next;
+ end
+end
+
+`ifdef SCR1_RVC_EXT
+assign inc_pc = pc_curr_ff + (exu_queue.instr_rvc ? `SCR1_XLEN'd2 : `SCR1_XLEN'd4);
+`else // ~SCR1_RVC_EXT
+assign inc_pc = pc_curr_ff + `SCR1_XLEN'd4;
+`endif // ~SCR1_RVC_EXT
+
+assign pc_curr_next = exu2ifu_pc_new_req_o ? exu2ifu_pc_new_o
+ : (inc_pc[6] ^ pc_curr_ff[6]) ? inc_pc
+ : {pc_curr_ff[`SCR1_XLEN-1:6], inc_pc[5:0]};
+
+// New PC multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ case (1'b1)
+ init_pc : exu2ifu_pc_new_o = SCR1_RST_VECTOR;
+ exu2csr_take_exc_o,
+ exu2csr_take_irq_o,
+ exu2csr_mret_instr_o: exu2ifu_pc_new_o = csr2exu_new_pc_i;
+`ifdef SCR1_DBG_EN
+ dbg_run_start_npbuf : exu2ifu_pc_new_o = hdu2exu_dbg_new_pc_i;
+`endif // SCR1_DBG_EN
+ wfi_run_start_ff : exu2ifu_pc_new_o = pc_curr_ff;
+ exu_queue.fencei_req: exu2ifu_pc_new_o = inc_pc;
+ default : exu2ifu_pc_new_o = ialu_addr_res & SCR1_JUMP_MASK;
+ endcase
+end
+
+assign exu2ifu_pc_new_req_o = init_pc // reset
+ | exu2csr_take_irq_o
+ | exu2csr_take_exc_o
+ | (exu2csr_mret_instr_o & ~csr2exu_mstatus_mie_up_i)
+ | (exu_queue_vd & exu_queue.fencei_req)
+ | (wfi_run_start_ff
+`ifdef SCR1_CLKCTRL_EN
+ & clk_pipe_en
+`endif // SCR1_CLKCTRL_EN
+ )
+`ifdef SCR1_DBG_EN
+ | dbg_run_start_npbuf
+`endif // SCR1_DBG_EN
+ | (exu_queue_vd & jb_taken);
+
+// Jump/branch signals
+assign branch_taken = exu_queue.branch_req & ialu_cmp;
+assign jb_taken = exu_queue.jump_req | branch_taken;
+assign jb_new_pc = ialu_addr_res & SCR1_JUMP_MASK;
+
+// PC to be loaded on MRET from interrupt trap
+assign exu2csr_pc_next_o = ~exu_queue_vd ? pc_curr_ff
+ : jb_taken ? jb_new_pc
+ : inc_pc;
+assign exu2pipe_pc_curr_o = pc_curr_ff;
+
+//------------------------------------------------------------------------------
+// Load/Store Unit (LSU)
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Performs load and store operations in Data Memory
+ // - Generates DMEM address misalign and access fault exceptions
+ // - Passes DMEM operations information to TDU and generates LSU breakpoint exception
+ //
+//------------------------------------------------------------------------------
+
+assign lsu_req = ((exu_queue.lsu_cmd != SCR1_LSU_CMD_NONE) & exu_queue_vd);
+
+scr1_pipe_lsu i_lsu(
+ .rst_n (rst_n ),
+ .clk (clk ),
+
+ // EXU <-> LSU interface
+ .exu2lsu_req_i (lsu_req ), // Request to LSU
+ .exu2lsu_cmd_i (exu_queue.lsu_cmd ), // LSU command
+ .exu2lsu_addr_i (ialu_addr_res ), // DMEM address
+ .exu2lsu_sdata_i (mprf2exu_rs2_data_i ), // Data for store to DMEM
+ .lsu2exu_rdy_o (lsu_rdy ), // LSU ready
+ .lsu2exu_ldata_o (lsu_l_data ), // Loaded data form DMEM
+ .lsu2exu_exc_o (lsu_exc_req ), // LSU exception
+ .lsu2exu_exc_code_o (lsu_exc_code ), // LSU exception code
+
+`ifdef SCR1_TDU_EN
+ // TDU <-> LSU interface
+ .lsu2tdu_dmon_o (lsu2tdu_dmon_o ),
+ .tdu2lsu_ibrkpt_exc_req_i (tdu2lsu_ibrkpt_exc_req_i),
+ .tdu2lsu_dbrkpt_exc_req_i (tdu2lsu_dbrkpt_exc_req_i),
+`endif // SCR1_TDU_EN
+
+ // Data memory interface
+ .lsu2dmem_req_o (exu2dmem_req_o ), // DMEM request
+ .lsu2dmem_cmd_o (exu2dmem_cmd_o ), // DMEM command
+ .lsu2dmem_width_o (exu2dmem_width_o ), // DMEM width
+ .lsu2dmem_addr_o (exu2dmem_addr_o ), // DMEM address
+ .lsu2dmem_wdata_o (exu2dmem_wdata_o ), // DMEM write data
+ .dmem2lsu_req_ack_i (dmem2exu_req_ack_i ), // DMEM request acknowledge
+ .dmem2lsu_rdata_i (dmem2exu_rdata_i ), // DMEM read data
+ .dmem2lsu_resp_i (dmem2exu_resp_i ) // DMEM response
+);
+
+//------------------------------------------------------------------------------
+// EXU status logic
+//------------------------------------------------------------------------------
+
+// EXU ready flag
+always_comb begin
+ case (1'b1)
+ lsu_req : exu_rdy = lsu_rdy | lsu_exc_req;
+`ifdef SCR1_RVM_EXT
+ ialu_vd : exu_rdy = ialu_rdy;
+`endif // SCR1_RVM_EXT
+ csr2exu_mstatus_mie_up_i: exu_rdy = 1'b0;
+ default : exu_rdy = 1'b1;
+ endcase
+end
+
+assign exu2pipe_init_pc_o = init_pc;
+assign exu2idu_rdy_o = exu_rdy & ~exu_queue_barrier;
+assign exu2pipe_exu_busy_o = exu_queue_vd & ~exu_rdy;
+assign exu2pipe_instret_o = exu_queue_vd & exu_rdy;
+assign exu2csr_instret_no_exc_o = exu2pipe_instret_o & ~exu_exc_req;
+
+// Exceptions
+`ifdef SCR1_DBG_EN
+assign exu2pipe_exc_req_o = exu_queue_vd ? exu_exc_req : exu_exc_req_ff;
+`else // SCR1_DBG_EN
+assign exu2pipe_exc_req_o = exu_exc_req;
+`endif // SCR1_DBG_EN
+
+// Breakpoints
+assign exu2pipe_brkpt_o = exu_queue_vd & (exu_queue.exc_code == SCR1_EXC_CODE_BREAKPOINT);
+`ifdef SCR1_TDU_EN
+assign exu2hdu_ibrkpt_hw_o = tdu2exu_ibrkpt_exc_req_i | tdu2lsu_dbrkpt_exc_req_i;
+`endif // SCR1_TDU_EN
+
+//------------------------------------------------------------------------------
+// EXU <-> MPRF interface
+//------------------------------------------------------------------------------
+
+// Operands fetching stage
+//------------------------------------------------------------------------------
+
+`ifdef SCR1_NO_EXE_STAGE
+assign mprf_rs1_req = exu_queue_vd & idu2exu_use_rs1_i;
+assign mprf_rs2_req = exu_queue_vd & idu2exu_use_rs2_i;
+`else // SCR1_NO_EXE_STAGE
+ `ifdef SCR1_MPRF_RAM
+assign mprf_rs1_req = exu_queue_en
+ ? (exu_queue_vd_next & idu2exu_use_rs1_i)
+ : (exu_queue_vd & idu2exu_use_rs1_ff);
+assign mprf_rs2_req = exu_queue_en
+ ? (exu_queue_vd_next & idu2exu_use_rs2_i)
+ : (exu_queue_vd & idu2exu_use_rs2_ff);
+ `else // SCR1_MPRF_RAM
+assign mprf_rs1_req = exu_queue_vd & idu2exu_use_rs1_ff;
+assign mprf_rs2_req = exu_queue_vd & idu2exu_use_rs2_ff;
+ `endif // SCR1_MPRF_RAM
+`endif // SCR1_NO_EXE_STAGE
+
+// If exu_queue isn't enabled we need previous addresses and usage flags because
+// RAM blocks read operation is SYNCHRONOUS
+`ifdef SCR1_MPRF_RAM
+assign mprf_rs1_addr = exu_queue_en ? idu2exu_cmd_i.rs1_addr : exu_queue.rs1_addr;
+assign mprf_rs2_addr = exu_queue_en ? idu2exu_cmd_i.rs2_addr : exu_queue.rs2_addr;
+`else // SCR1_MPRF_RAM
+assign mprf_rs1_addr = exu_queue.rs1_addr;
+assign mprf_rs2_addr = exu_queue.rs2_addr;
+`endif // SCR1_MPRF_RAM
+
+assign exu2mprf_rs1_addr_o = mprf_rs1_req ? `SCR1_MPRF_AWIDTH'(mprf_rs1_addr) : '0;
+assign exu2mprf_rs2_addr_o = mprf_rs2_req ? `SCR1_MPRF_AWIDTH'(mprf_rs2_addr) : '0;
+
+// Write back stage
+//------------------------------------------------------------------------------
+
+assign exu2mprf_w_req_o = (exu_queue.rd_wb_sel != SCR1_RD_WB_NONE) & exu_queue_vd & ~exu_exc_req
+`ifdef SCR1_DBG_EN
+ & ~hdu2exu_no_commit_i
+`endif // SCR1_DBG_EN
+ & ((exu_queue.rd_wb_sel == SCR1_RD_WB_CSR) ? csr_access_init : exu_rdy);
+
+assign exu2mprf_rd_addr_o = `SCR1_MPRF_AWIDTH'(exu_queue.rd_addr);
+
+// MRPF RD data multiplexer
+always_comb begin
+ case (exu_queue.rd_wb_sel)
+ SCR1_RD_WB_SUM2 : exu2mprf_rd_data_o = ialu_addr_res;
+ SCR1_RD_WB_IMM : exu2mprf_rd_data_o = exu_queue.imm;
+ SCR1_RD_WB_INC_PC: exu2mprf_rd_data_o = inc_pc;
+ SCR1_RD_WB_LSU : exu2mprf_rd_data_o = lsu_l_data;
+ SCR1_RD_WB_CSR : exu2mprf_rd_data_o = csr2exu_r_data_i;
+ default : exu2mprf_rd_data_o = ialu_main_res;
+ endcase
+end
+
+//------------------------------------------------------------------------------
+// EXU <-> CSR interface
+//------------------------------------------------------------------------------
+//
+ // EXU <-> CSR interface consists of the following functional units:
+ // - CSR write/read interface
+ // - CSR access FSM
+ // - CSR events interface:
+ // - Exceptions signals
+ // - Interrupts signals
+ // - MRET signals
+//
+
+// CSRs write/read interface
+//------------------------------------------------------------------------------
+
+// CSR write/read request signals calculation
+always_comb begin
+ if (~exu_queue_vd
+`ifdef SCR1_TDU_EN
+ | tdu2exu_ibrkpt_exc_req_i
+`endif // SCR1_TDU_EN
+ ) begin
+ exu2csr_r_req_o = 1'b0;
+ exu2csr_w_req_o = 1'b0;
+ end else begin
+ case (exu_queue.csr_cmd)
+ SCR1_CSR_CMD_WRITE : begin
+ exu2csr_r_req_o = |exu_queue.rd_addr;
+ exu2csr_w_req_o = csr_access_init;
+ end
+ SCR1_CSR_CMD_SET,
+ SCR1_CSR_CMD_CLEAR : begin
+ exu2csr_r_req_o = 1'b1;
+ exu2csr_w_req_o = |exu_queue.rs1_addr & csr_access_init;
+ end
+ default : begin
+ exu2csr_r_req_o = 1'b0;
+ exu2csr_w_req_o = 1'b0;
+ end
+ endcase
+ end
+end
+
+assign exu2csr_w_cmd_o = exu_queue.csr_cmd;
+assign exu2csr_rw_addr_o = exu_queue.imm[SCR1_CSR_ADDR_WIDTH-1:0];
+assign exu2csr_w_data_o = (exu_queue.csr_op == SCR1_CSR_OP_REG)
+ ? mprf2exu_rs1_data_i
+ : {'0, exu_queue.rs1_addr}; // zimm
+
+
+// CSR access FSM
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ csr_access_ff <= SCR1_CSR_INIT;
+ end else begin
+ csr_access_ff <= csr_access_next;
+ end
+end
+
+assign csr_access_next = (csr_access_init & csr2exu_mstatus_mie_up_i)
+ ? SCR1_CSR_RDY
+ : SCR1_CSR_INIT;
+
+assign csr_access_init = (csr_access_ff == SCR1_CSR_INIT);
+
+// CSR events interface
+//------------------------------------------------------------------------------
+
+// Exceptions signals
+assign exu2csr_take_exc_o = exu_exc_req
+`ifdef SCR1_DBG_EN
+ & ~hdu2exu_dbg_halted_i
+`endif // SCR1_DBG_EN
+ ;
+assign exu2csr_exc_code_o = exc_code;
+assign exu2csr_trap_val_o = exc_trap_val;
+
+// Interrupts signals
+assign exu2csr_take_irq_o = csr2exu_irq_i & ~exu2pipe_exu_busy_o
+`ifdef SCR1_DBG_EN
+ & ~hdu2exu_irq_dsbl_i
+ & ~hdu2exu_dbg_halted_i
+`endif // SCR1_DBG_EN
+`ifdef SCR1_CLKCTRL_EN
+ & clk_pipe_en
+`endif // SCR1_CLKCTRL_EN
+ ;
+
+// MRET signals
+// MRET instruction flag
+assign exu2csr_mret_instr_o = exu_queue_vd & exu_queue.mret_req
+`ifdef SCR1_TDU_EN
+ & ~tdu2exu_ibrkpt_exc_req_i
+`endif // SCR1_TDU_EN
+`ifdef SCR1_DBG_EN
+ & ~hdu2exu_dbg_halted_i
+`endif // SCR1_DBG_EN
+ ;
+assign exu2csr_mret_update_o = exu2csr_mret_instr_o & csr_access_init;
+
+`ifdef SCR1_TDU_EN
+//------------------------------------------------------------------------------
+// EXU <-> TDU interface
+//------------------------------------------------------------------------------
+
+// Instruction monitor
+assign exu2tdu_imon_o.vd = exu_queue_vd;
+assign exu2tdu_imon_o.req = exu2pipe_instret_o;
+assign exu2tdu_imon_o.addr = pc_curr_ff;
+
+always_comb begin
+ exu2tdu_ibrkpt_ret_o = '0;
+ if (exu_queue_vd) begin
+ exu2tdu_ibrkpt_ret_o = tdu2exu_ibrkpt_match_i;
+ if (lsu_req) begin
+ exu2tdu_ibrkpt_ret_o[SCR1_TDU_MTRIG_NUM-1:0] |= tdu2lsu_dbrkpt_match_i;
+ end
+ end
+end
+`endif // SCR1_TDU_EN
+
+
+`ifdef SCR1_TRGT_SIMULATION
+//------------------------------------------------------------------------------
+// Tracelog signals
+//------------------------------------------------------------------------------
+
+logic [`SCR1_XLEN-1:0] update_pc;
+logic update_pc_en;
+
+assign update_pc_en = (init_pc | exu2pipe_instret_o | exu2csr_take_irq_o)
+`ifdef SCR1_DBG_EN
+ & ~hdu2exu_pc_advmt_dsbl_i & ~hdu2exu_no_commit_i
+`endif // SCR1_DBG_EN
+ ;
+assign update_pc = exu2ifu_pc_new_req_o ? exu2ifu_pc_new_o : inc_pc;
+
+
+//------------------------------------------------------------------------------
+// Assertion
+//------------------------------------------------------------------------------
+
+// X checks
+
+SCR1_SVA_EXU_XCHECK_CTRL : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({idu2exu_req_i, csr2exu_irq_i, csr2exu_ip_ie_i, lsu_req, lsu_rdy, exu_exc_req})
+ ) else $error("EXU Error: unknown control values");
+
+SCR1_SVA_EXU_XCHECK_QUEUE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ idu2exu_req_i |-> !$isunknown(idu2exu_cmd_i)
+ ) else $error("EXU Error: unknown values in queue");
+
+SCR1_SVA_EXU_XCHECK_CSR_RDATA : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2csr_r_req_o |-> !$isunknown({csr2exu_r_data_i, csr2exu_rw_exc_i})
+ ) else $error("EXU Error: unknown values from CSR");
+
+// Behavior checks
+
+SCR1_SVA_EXU_ONEHOT : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ $onehot0({exu_queue.jump_req, exu_queue.branch_req, lsu_req})
+ ) else $error("EXU Error: illegal combination of control signals");
+
+SCR1_SVA_EXU_ONEHOT_EXC : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu_queue_vd |->
+ $onehot0({exu_queue.exc_req, lsu_exc_req, csr2exu_rw_exc_i
+`ifndef SCR1_RVC_EXT
+ , jb_misalign
+`endif
+ })
+ ) else $error("EXU Error: exceptions $onehot0 failed");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_exu
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_hdu.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_hdu.sv
new file mode 100644
index 0000000..14f421b
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_hdu.sv
@@ -0,0 +1,904 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_pipe_hdu.sv>
+/// @brief HART Debug Unit (HDU)
+///
+
+//------------------------------------------------------------------------------
+ //
+ //
+ // Functionality:
+ // - Controls HART state (RUN, Debug RUN, Debug HALTED)
+ // - Setups Debug Mode execution
+ // - Provides status information about Debug Mode execution
+ // - Provides Program Buffer functionality (a few instructions execution while
+ // in Debug Mode)
+ // - Provides access to Debug CSRs
+ //
+ // Structure:
+ // - Debug state FSM
+ // - HART Control logic
+ // - HART Status logic
+ // - Program Buffer
+ // - Debug CSRs
+ // - HDU <-> DM interface
+ // - HDU <-> EXU interface
+ // - HDU <-> IFU interface
+ // - HDU <-> CSR interface
+ // - HDU <-> TDU interface
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+`include "scr1_arch_types.svh"
+`include "scr1_riscv_isa_decoding.svh"
+`include "scr1_hdu.svh"
+
+module scr1_pipe_hdu #(parameter HART_PBUF_INSTR_REGOUT_EN = 1'b1) (
+ // Common signals
+ input logic rst_n, // HDU reset
+ input logic clk, // HDU clock
+ input logic clk_en, // HDU clock enable
+`ifdef SCR1_CLKCTRL_EN
+ input logic clk_pipe_en, // Pipeline clock enable
+`endif // SCR1_CLKCTRL_EN
+ input logic pipe2hdu_rdc_qlfy_i, // Pipeline RDC qualifier
+
+ // HDU <-> CSR i/f
+ input logic csr2hdu_req_i, // CSR i/f request
+ input type_scr1_csr_cmd_sel_e csr2hdu_cmd_i, // CSR i/f command
+ input logic [SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0] csr2hdu_addr_i, // CSR i/f address
+ input logic [`SCR1_XLEN-1:0] csr2hdu_wdata_i, // CSR i/f write data
+ output type_scr1_csr_resp_e hdu2csr_resp_o, // CSR i/f response
+ output logic [`SCR1_XLEN-1:0] hdu2csr_rdata_o, // CSR i/f read data
+
+ // HDU <-> DM i/f
+ // HART Run Control i/f
+ input logic dm2hdu_cmd_req_i, // DM-HART Command request
+ input type_scr1_hdu_dbgstates_e dm2hdu_cmd_i, // DM-HART Command
+ output logic hdu2dm_cmd_resp_o, // DM-HART Command response
+ output logic hdu2dm_cmd_rcode_o, // DM-HART Command return code: 0 - Ok; 1 - Error
+ output logic hdu2dm_hart_event_o, // DM-HART Event: 1 if HART debug state changed
+ output type_scr1_hdu_hartstatus_s hdu2dm_hart_status_o, // DM-HART Status
+
+ // Program Buffer i/f
+ output logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] hdu2dm_pbuf_addr_o, // Program Buffer address - so far request only for 1 instruction
+ input logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2hdu_pbuf_instr_i, // Program Buffer instruction
+
+ // HART Abstract Data regs i/f
+ output logic hdu2dm_dreg_req_o, // Abstract Data Register request
+ output logic hdu2dm_dreg_wr_o, // Abstract Data Register write
+ output logic [`SCR1_XLEN-1:0] hdu2dm_dreg_wdata_o, // Abstract Data Register write data
+ input logic dm2hdu_dreg_resp_i, // Abstract Data Register response
+ input logic dm2hdu_dreg_fail_i, // Abstract Data Register fail
+ input logic [`SCR1_XLEN-1:0] dm2hdu_dreg_rdata_i, // Abstract Data Register read data
+
+`ifdef SCR1_TDU_EN
+ // HDU <-> TDU interface
+ output logic hdu2tdu_hwbrk_dsbl_o, // Disables BRKM
+ input logic tdu2hdu_dmode_req_i, // Trigger Module requests transition to debug mode
+ input logic exu2hdu_ibrkpt_hw_i, // Hardware breakpoint on current instruction
+`endif // SCR1_TDU_EN
+
+ // HART Run Status
+ input logic pipe2hdu_exu_busy_i, // EXU busy
+ input logic pipe2hdu_instret_i, // Instruction retired (with or without exception)
+ input logic pipe2hdu_init_pc_i, // Reset exit
+
+ // HART Halt Status
+ input logic pipe2hdu_exu_exc_req_i, // Exception request
+ input logic pipe2hdu_brkpt_i, // Software Breakpoint (EBREAK)
+
+ // HDU <-> EXU i/f
+ // HART Run Control
+ output logic hdu2exu_pbuf_fetch_o, // Fetch instruction from Program Buffer
+ output logic hdu2exu_no_commit_o, // Forbid instruction commitment
+ output logic hdu2exu_irq_dsbl_o, // Disable IRQ
+ output logic hdu2exu_pc_advmt_dsbl_o, // Forbid PC advancement
+ output logic hdu2exu_dmode_sstep_en_o, // Enable single-step
+
+ // HART state
+ output logic hdu2exu_dbg_halted_o, // Debug halted state
+ output logic hdu2exu_dbg_run2halt_o, // Transition to debug halted state
+ output logic hdu2exu_dbg_halt2run_o, // Transition to run state
+ output logic hdu2exu_dbg_run_start_o, // First cycle of run state
+
+ // PC interface
+ input logic [`SCR1_XLEN-1:0] pipe2hdu_pc_curr_i, // Current PC
+ output logic [`SCR1_XLEN-1:0] hdu2exu_dbg_new_pc_o, // New PC for resume
+
+ // HDU <-> IFU i/f
+ // Program Buffer Instruction interface
+ input logic ifu2hdu_pbuf_instr_rdy_i, // Program Buffer Instruction i/f ready
+ output logic hdu2ifu_pbuf_instr_vd_o, // Program Buffer Instruction valid
+ output logic hdu2ifu_pbuf_instr_err_o, // Program Buffer Instruction i/f error
+ output logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr_o // Program Buffer Instruction itself
+);
+
+//------------------------------------------------------------------------------
+// Local Parameters
+//------------------------------------------------------------------------------
+
+localparam int unsigned SCR1_HDU_TIMEOUT = 64; // must be power of 2
+localparam int unsigned SCR1_HDU_TIMEOUT_WIDTH = $clog2(SCR1_HDU_TIMEOUT);
+
+//------------------------------------------------------------------------------
+// Local Signals
+//------------------------------------------------------------------------------
+
+// Debug FSM
+//------------------------------------------------------------------------------
+
+// FSM control signals
+logic dm_dhalt_req;
+logic dm_run_req;
+
+logic dm_cmd_run;
+logic dm_cmd_dhalted;
+logic dm_cmd_drun;
+
+// Debug state FSM signals
+type_scr1_hdu_dbgstates_e dbg_state;
+type_scr1_hdu_dbgstates_e dbg_state_next;
+logic dbg_state_dhalted;
+logic dbg_state_drun;
+logic dbg_state_run;
+logic dbg_state_reset;
+
+// FSM transition, update and event registers
+logic dfsm_trans;
+logic dfsm_trans_next;
+logic dfsm_update;
+logic dfsm_update_next;
+logic dfsm_event;
+logic dfsm_event_next;
+
+// HART Control signals
+//------------------------------------------------------------------------------
+
+logic hart_resume_req;
+logic hart_halt_req;
+logic hart_cmd_req;
+
+// HART Run Control register
+logic hart_runctrl_upd;
+logic hart_runctrl_clr;
+type_scr1_hdu_runctrl_s hart_runctrl;
+
+// HART halt request timeout counter signals
+logic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt;
+logic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt_next;
+logic halt_req_timeout_cnt_en;
+logic halt_req_timeout_flag;
+
+// HART Status signals
+//------------------------------------------------------------------------------
+
+type_scr1_hdu_haltstatus_s hart_haltstatus;
+type_scr1_hdu_haltcause_e hart_haltcause;
+
+logic hart_halt_pnd;
+logic hart_halt_ack;
+
+// Debug mode cause decoder signals
+logic dmode_cause_sstep;
+logic dmode_cause_except;
+logic dmode_cause_ebreak;
+logic dmode_cause_any;
+`ifdef SCR1_TDU_EN
+logic dmode_cause_tmreq;
+`endif // SCR1_TDU_EN
+
+// Program Buffer FSM
+//------------------------------------------------------------------------------
+
+// PBUF FSM control signals
+logic ifu_handshake_done;
+logic pbuf_exc_inj_req;
+logic pbuf_exc_inj_end;
+logic pbuf_start_fetch;
+
+// PBUF FSM signals
+type_scr1_hdu_pbufstates_e pbuf_fsm_curr;
+type_scr1_hdu_pbufstates_e pbuf_fsm_next;
+logic pbuf_fsm_idle;
+logic pbuf_fsm_fetch;
+logic pbuf_fsm_excinj;
+
+// PBUF address signals
+logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_ff;
+logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_next;
+logic pbuf_addr_end;
+logic pbuf_addr_next_vd;
+
+logic pbuf_instr_wait_latching;
+
+// Debugs CSRs
+//------------------------------------------------------------------------------
+
+// CSRs write/read interface signals
+logic csr_upd_on_halt;
+logic csr_wr;
+logic [`SCR1_XLEN-1:0] csr_wr_data;
+logic [`SCR1_XLEN-1:0] csr_rd_data;
+
+// Debug Control and Status register (DCSR)
+logic csr_dcsr_sel;
+logic csr_dcsr_wr;
+type_scr1_hdu_dcsr_s csr_dcsr_in;
+type_scr1_hdu_dcsr_s csr_dcsr_out;
+logic csr_dcsr_ebreakm;
+logic csr_dcsr_stepie;
+logic csr_dcsr_step;
+logic [SCR1_HDU_DCSR_CAUSE_BIT_L-
+ SCR1_HDU_DCSR_CAUSE_BIT_R:0] csr_dcsr_cause;
+
+// Debug Program Counter register (DPC)
+logic csr_dpc_sel;
+logic csr_dpc_wr;
+logic [`SCR1_XLEN-1:0] csr_dpc_ff;
+logic [`SCR1_XLEN-1:0] csr_dpc_next;
+logic [`SCR1_XLEN-1:0] csr_dpc_out;
+
+// Debug Scratch register 0 (DSCRATCH0)
+logic csr_addr_dscratch0;
+logic csr_dscratch0_sel;
+logic csr_dscratch0_wr;
+logic [`SCR1_XLEN-1:0] csr_dscratch0_out;
+type_scr1_csr_resp_e csr_dscratch0_resp;
+
+//------------------------------------------------------------------------------
+// Debug state FSM logic
+//------------------------------------------------------------------------------
+//
+ // Debug state FSM logic consists of the following functional units:
+ // - FSM control logic
+ // - Debug state FSM
+ // - FSM transition, update and event registers
+//
+
+// FSM control logic
+//------------------------------------------------------------------------------
+
+assign dm_cmd_dhalted = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DHALTED);
+assign dm_cmd_run = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_RUN);
+assign dm_cmd_drun = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DRUN);
+
+assign dm_dhalt_req = dm2hdu_cmd_req_i & dm_cmd_dhalted;
+assign dm_run_req = dm2hdu_cmd_req_i & (dm_cmd_run | dm_cmd_drun);
+
+// Debug state FSM
+//------------------------------------------------------------------------------
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ dbg_state <= SCR1_HDU_DBGSTATE_RESET;
+ end else begin
+ dbg_state <= dbg_state_next;
+ end
+end
+
+always_comb begin
+ if (~pipe2hdu_rdc_qlfy_i) begin
+ dbg_state_next = SCR1_HDU_DBGSTATE_RESET;
+ end else begin
+ case (dbg_state)
+ SCR1_HDU_DBGSTATE_RESET: begin
+ dbg_state_next = ~pipe2hdu_init_pc_i ? SCR1_HDU_DBGSTATE_RESET
+ : dm_dhalt_req ? SCR1_HDU_DBGSTATE_DHALTED
+ : SCR1_HDU_DBGSTATE_RUN;
+ end
+ SCR1_HDU_DBGSTATE_RUN: begin
+ dbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
+ : SCR1_HDU_DBGSTATE_RUN;
+ end
+ SCR1_HDU_DBGSTATE_DHALTED: begin
+ dbg_state_next = ~dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
+ : dm_cmd_drun ? SCR1_HDU_DBGSTATE_DRUN
+ : SCR1_HDU_DBGSTATE_RUN;
+ end
+ SCR1_HDU_DBGSTATE_DRUN: begin
+ dbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
+ : SCR1_HDU_DBGSTATE_DRUN;
+ end
+ default: begin
+`ifdef SCR1_XPROP_EN
+ dbg_state_next = SCR1_HDU_DBGSTATE_XXX;
+`else // SCR1_XPROP_EN
+ dbg_state_next = dbg_state;
+`endif // SCR1_XPROP_EN
+ end
+ endcase
+ end
+end
+
+assign dbg_state_dhalted = (dbg_state == SCR1_HDU_DBGSTATE_DHALTED);
+assign dbg_state_drun = (dbg_state == SCR1_HDU_DBGSTATE_DRUN);
+assign dbg_state_run = (dbg_state == SCR1_HDU_DBGSTATE_RUN);
+assign dbg_state_reset = (dbg_state == SCR1_HDU_DBGSTATE_RESET);
+
+// FSM transition, update and event registers
+//------------------------------------------------------------------------------
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ dfsm_trans <= 1'b0;
+ dfsm_update <= 1'b0;
+ dfsm_event <= 1'b0;
+ end else begin
+ dfsm_trans <= dfsm_trans_next;
+ dfsm_update <= dfsm_update_next;
+ dfsm_event <= dfsm_event_next;
+ end
+end
+
+always_comb begin
+ dfsm_trans_next = 1'b0;
+ dfsm_update_next = 1'b0;
+ dfsm_event_next = 1'b0;
+
+ if (~pipe2hdu_rdc_qlfy_i) begin
+ dfsm_trans_next = 1'b0;
+ dfsm_update_next = 1'b0;
+ dfsm_event_next = 1'b1;
+ end else begin
+ case (dbg_state)
+ SCR1_HDU_DBGSTATE_RESET: begin
+ dfsm_trans_next = 1'b0;
+ dfsm_update_next = 1'b0;
+ dfsm_event_next = pipe2hdu_init_pc_i & ~dm2hdu_cmd_req_i;
+ end
+
+ SCR1_HDU_DBGSTATE_RUN,
+ SCR1_HDU_DBGSTATE_DRUN: begin
+ dfsm_trans_next = ~dfsm_update ? hart_halt_pnd : dfsm_trans;
+ dfsm_update_next = ~dfsm_update & hart_halt_ack;
+ dfsm_event_next = dfsm_update;
+ end
+
+ SCR1_HDU_DBGSTATE_DHALTED: begin
+ dfsm_trans_next = ~dfsm_update ? ~dfsm_trans & dm_run_req
+ : dfsm_trans;
+ dfsm_update_next = ~dfsm_update & dfsm_trans;
+ dfsm_event_next = dfsm_update;
+ end
+
+ default : begin
+ dfsm_trans_next = 'X;
+ dfsm_update_next = 'X;
+ dfsm_event_next = 'X;
+ end
+ endcase
+ end
+end
+
+//------------------------------------------------------------------------------
+// HART Control logic
+//------------------------------------------------------------------------------
+//
+ // HART Control logic consists of the following functional units:
+ // - Control signals
+ // - HART Run Control register
+ // - HART Halt Request Time-Out counter
+//
+
+// Control logic
+always_comb begin
+ hart_cmd_req = 1'b0;
+
+ if (~pipe2hdu_rdc_qlfy_i) begin
+ hart_cmd_req = 1'b0;
+ end else begin
+ case (dbg_state)
+ SCR1_HDU_DBGSTATE_RESET : hart_cmd_req = dm2hdu_cmd_req_i;
+ SCR1_HDU_DBGSTATE_DHALTED: hart_cmd_req = (dfsm_update | dfsm_trans);
+ SCR1_HDU_DBGSTATE_RUN,
+ SCR1_HDU_DBGSTATE_DRUN : hart_cmd_req = ~dfsm_update & dfsm_trans;
+ default : hart_cmd_req = 'X;
+ endcase
+ end
+end
+
+assign hart_halt_req = dm_cmd_dhalted & hart_cmd_req;
+assign hart_resume_req = (dm_cmd_run | dm_cmd_drun) & hart_cmd_req;
+
+// HART Run Control register
+//------------------------------------------------------------------------------
+
+assign hart_runctrl_clr = (dbg_state_run | dbg_state_drun)
+ & (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);
+assign hart_runctrl_upd = dbg_state_dhalted & dfsm_trans_next;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ hart_runctrl.irq_dsbl <= 1'b0;
+ hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;
+ hart_runctrl.pc_advmt_dsbl <= 1'b0;
+ hart_runctrl.hwbrkpt_dsbl <= 1'b0;
+ hart_runctrl.redirect <= '0;
+ end else if(clk_en) begin
+ if (hart_runctrl_clr) begin
+ hart_runctrl <= '0;
+ end else begin
+ if (hart_runctrl_upd) begin
+ if (~dm_cmd_drun) begin
+ // Case : resume to RUN state
+ hart_runctrl.irq_dsbl <= csr_dcsr_step ? ~csr_dcsr_stepie : 1'b0;
+ hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;
+ hart_runctrl.pc_advmt_dsbl <= 1'b0;
+ hart_runctrl.hwbrkpt_dsbl <= 1'b0;
+ hart_runctrl.redirect.sstep <= csr_dcsr_step;
+ hart_runctrl.redirect.ebreak <= csr_dcsr_ebreakm;
+ end else begin
+ // Case : resume to DRUN state
+ hart_runctrl.irq_dsbl <= 1'b1;
+ hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_PBUF;
+ hart_runctrl.pc_advmt_dsbl <= 1'b1;
+ hart_runctrl.hwbrkpt_dsbl <= 1'b1;
+ hart_runctrl.redirect.sstep <= 1'b0;
+ hart_runctrl.redirect.ebreak <= 1'b1;
+ end
+ end
+ end
+ end
+end
+
+// HART Halt Request Time-Out counter
+//------------------------------------------------------------------------------
+// HART goes into halt state only if the halt request is present for timeout period
+// of time
+
+assign halt_req_timeout_cnt_en = hdu2exu_dbg_halt2run_o
+ | (hart_halt_req & ~hdu2exu_dbg_run2halt_o);
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ halt_req_timeout_cnt <= '1;
+ end else if (halt_req_timeout_cnt_en) begin
+ halt_req_timeout_cnt <= halt_req_timeout_cnt_next;
+ end
+end
+
+assign halt_req_timeout_cnt_next = hdu2exu_dbg_halt2run_o ? '1
+ : (hart_halt_req & ~hdu2exu_dbg_run2halt_o) ? halt_req_timeout_cnt - 1'b1
+ : halt_req_timeout_cnt;
+
+assign halt_req_timeout_flag = ~|halt_req_timeout_cnt;
+
+//------------------------------------------------------------------------------
+// HART Status logic
+//------------------------------------------------------------------------------
+//
+ // HART Status logic consists of the following functional units:
+ // - Debug mode cause decoder
+ // - Hart halt status cause encoder
+ // - Hart halt status register
+//
+
+// Debug mode cause decoder
+//------------------------------------------------------------------------------
+
+assign dmode_cause_sstep = hart_runctrl.redirect.sstep & pipe2hdu_instret_i;
+assign dmode_cause_except = dbg_state_drun & pipe2hdu_exu_exc_req_i
+ & ~pipe2hdu_brkpt_i
+`ifdef SCR1_TDU_EN
+ & ~exu2hdu_ibrkpt_hw_i
+`endif // SCR1_TDU_EN
+ ;
+assign dmode_cause_ebreak = hart_runctrl.redirect.ebreak & pipe2hdu_brkpt_i;
+`ifdef SCR1_TDU_EN
+assign dmode_cause_tmreq = tdu2hdu_dmode_req_i & exu2hdu_ibrkpt_hw_i;
+`endif // SCR1_TDU_EN
+
+assign dmode_cause_any = dmode_cause_sstep | dmode_cause_ebreak | dmode_cause_except
+ | hart_halt_req
+`ifdef SCR1_TDU_EN
+ | dmode_cause_tmreq
+`endif // SCR1_TDU_EN
+ ;
+
+// HART halt cause encoder
+//------------------------------------------------------------------------------
+
+always_comb begin
+ case (1'b1)
+`ifdef SCR1_TDU_EN
+ dmode_cause_tmreq : hart_haltcause = SCR1_HDU_HALTCAUSE_TMREQ;
+`endif // SCR1_TDU_EN
+ dmode_cause_ebreak : hart_haltcause = SCR1_HDU_HALTCAUSE_EBREAK;
+ hart_halt_req : hart_haltcause = SCR1_HDU_HALTCAUSE_DMREQ;
+ dmode_cause_sstep : hart_haltcause = SCR1_HDU_HALTCAUSE_SSTEP;
+ default : hart_haltcause = SCR1_HDU_HALTCAUSE_NONE;
+ endcase
+end
+
+// HART halt status register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ hart_haltstatus <= '0;
+ end else if (hart_halt_ack) begin
+ hart_haltstatus.except <= dmode_cause_except;
+ hart_haltstatus.cause <= hart_haltcause;
+ end
+end
+
+assign hart_halt_pnd = (dfsm_trans | dm_dhalt_req) & ~hart_halt_ack;
+assign hart_halt_ack = ~hdu2exu_dbg_halted_o
+ & (halt_req_timeout_flag | (~pipe2hdu_exu_busy_i & dmode_cause_any));
+
+//------------------------------------------------------------------------------
+// Program Buffer (PBUF) logic
+//------------------------------------------------------------------------------
+//
+ // Program Buffer allows to execute small programs in debug mode
+//
+
+// To terminate Program Buffer execution exception should be raised. There are 2
+// cases:
+// - One of PBUF instructions raise an exception
+// - No PBUF instruction raise an exception before the last PBUF instruction has
+// been issued. In this case FSM goes into EXCINJECT state and an "Instruction
+// fetch access fault" exception is injected
+
+// PBUF FSM
+//------------------------------------------------------------------------------
+
+assign ifu_handshake_done = hdu2ifu_pbuf_instr_vd_o & ifu2hdu_pbuf_instr_rdy_i;
+assign pbuf_addr_end = (pbuf_addr_ff == (SCR1_HDU_PBUF_ADDR_SPAN-1));
+
+assign pbuf_start_fetch = dbg_state_dhalted & (dbg_state_next == SCR1_HDU_DBGSTATE_DRUN);
+assign pbuf_exc_inj_req = ifu_handshake_done & pbuf_addr_end;
+assign pbuf_exc_inj_end = pipe2hdu_exu_exc_req_i | ifu_handshake_done;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ pbuf_fsm_curr <= SCR1_HDU_PBUFSTATE_IDLE;
+ end else if(clk_en) begin
+ pbuf_fsm_curr <= pbuf_fsm_next;
+ end
+end
+
+always_comb begin
+ case (pbuf_fsm_curr)
+ SCR1_HDU_PBUFSTATE_IDLE: begin
+ pbuf_fsm_next = pbuf_start_fetch ? SCR1_HDU_PBUFSTATE_FETCH
+ : SCR1_HDU_PBUFSTATE_IDLE;
+ end
+ SCR1_HDU_PBUFSTATE_FETCH: begin
+ pbuf_fsm_next = pipe2hdu_exu_exc_req_i ? SCR1_HDU_PBUFSTATE_WAIT4END
+ : pbuf_exc_inj_req ? SCR1_HDU_PBUFSTATE_EXCINJECT
+ : SCR1_HDU_PBUFSTATE_FETCH;
+ end
+ SCR1_HDU_PBUFSTATE_EXCINJECT: begin
+ pbuf_fsm_next = pbuf_exc_inj_end ? SCR1_HDU_PBUFSTATE_WAIT4END
+ : SCR1_HDU_PBUFSTATE_EXCINJECT;
+ end
+ SCR1_HDU_PBUFSTATE_WAIT4END: begin
+ pbuf_fsm_next = hdu2exu_dbg_halted_o ? SCR1_HDU_PBUFSTATE_IDLE
+ : SCR1_HDU_PBUFSTATE_WAIT4END;
+ end
+ endcase
+end
+
+assign pbuf_fsm_idle = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_IDLE);
+assign pbuf_fsm_fetch = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_FETCH);
+assign pbuf_fsm_excinj = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_EXCINJECT);
+
+// Program Buffer address register
+//------------------------------------------------------------------------------
+
+assign pbuf_addr_next_vd = pbuf_fsm_fetch & ifu_handshake_done
+ & ~pipe2hdu_exu_exc_req_i & ~pbuf_addr_end;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ pbuf_addr_ff <= '0;
+ end else if(clk_en) begin
+ pbuf_addr_ff <= pbuf_addr_next;
+ end
+end
+
+assign pbuf_addr_next = pbuf_fsm_idle ? '0
+ : pbuf_addr_next_vd ? pbuf_addr_ff + 1'b1
+ : pbuf_addr_ff;
+
+// Pass instruction from debug program buffer to cpu pipeline with two options:
+// - through register, better for frequency
+// - through wires, better for area
+generate if (HART_PBUF_INSTR_REGOUT_EN) begin
+ always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ pbuf_instr_wait_latching <= 1'b0;
+ end else begin
+ pbuf_instr_wait_latching <= ifu_handshake_done;
+ end
+ end
+end else begin
+ assign pbuf_instr_wait_latching = 1'b0;
+end endgenerate
+
+//------------------------------------------------------------------------------
+// Debug CSRs
+//------------------------------------------------------------------------------
+
+assign csr_upd_on_halt = (dbg_state_reset | dbg_state_run)
+ & (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);
+
+// CSRs select logic
+//------------------------------------------------------------------------------
+
+always_comb begin : csr_if_regsel
+ csr_dcsr_sel = 1'b0;
+ csr_dpc_sel = 1'b0;
+ csr_dscratch0_sel = 1'b0;
+ //csr_dscratch1_sel = 1'b0;
+
+ if (csr2hdu_req_i) begin
+ case (csr2hdu_addr_i)
+ SCR1_HDU_DBGCSR_OFFS_DCSR : csr_dcsr_sel = 1'b1;
+ SCR1_HDU_DBGCSR_OFFS_DPC : csr_dpc_sel = 1'b1;
+ SCR1_HDU_DBGCSR_OFFS_DSCRATCH0: csr_dscratch0_sel = 1'b1;
+ default : begin
+ csr_dcsr_sel = 1'bX;
+ csr_dpc_sel = 1'bX;
+ csr_dscratch0_sel = 1'bX;
+ end
+ endcase
+ end
+end : csr_if_regsel
+
+// CSRs read interface
+//------------------------------------------------------------------------------
+
+assign csr_rd_data = csr_dcsr_out | csr_dpc_out | csr_dscratch0_out;
+
+// CSRs write interface
+//------------------------------------------------------------------------------
+
+assign csr_wr = csr2hdu_req_i;
+
+always_comb begin : csr_if_write
+ csr_wr_data = '0;
+
+ if (csr2hdu_req_i) begin
+ case (csr2hdu_cmd_i)
+ SCR1_CSR_CMD_WRITE : csr_wr_data = csr2hdu_wdata_i;
+ SCR1_CSR_CMD_SET : csr_wr_data = csr_rd_data | csr2hdu_wdata_i;
+ SCR1_CSR_CMD_CLEAR : csr_wr_data = csr_rd_data & (~csr2hdu_wdata_i);
+ default : csr_wr_data = 'X;
+ endcase
+ end
+end : csr_if_write
+
+// Debug Control and Status register
+//------------------------------------------------------------------------------
+// Setups the HART behaviour in Debug Mode and holds Debug status information
+
+always_comb begin
+ csr_dcsr_in = csr_wr_data;
+ csr_dcsr_wr = csr_wr & csr_dcsr_sel;
+
+ csr_dcsr_out = '0;
+ if (csr_dcsr_sel) begin
+ csr_dcsr_out.xdebugver = SCR1_HDU_DEBUGCSR_DCSR_XDEBUGVER;
+ csr_dcsr_out.ebreakm = csr_dcsr_ebreakm;
+ csr_dcsr_out.stepie = csr_dcsr_stepie;
+ csr_dcsr_out.step = csr_dcsr_step;
+ csr_dcsr_out.prv = 2'b11;
+ csr_dcsr_out.cause = csr_dcsr_cause;
+ end
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_dcsr_ebreakm <= 1'b0;
+ csr_dcsr_stepie <= 1'b0;
+ csr_dcsr_step <= 1'b0;
+ end else if(clk_en) begin
+ if (csr_dcsr_wr) begin
+ csr_dcsr_ebreakm <= csr_dcsr_in.ebreakm;
+ csr_dcsr_stepie <= csr_dcsr_in.stepie;
+ csr_dcsr_step <= csr_dcsr_in.step;
+ end
+ end
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ csr_dcsr_cause <= 1'b0;
+ end else if(clk_en) begin
+ if(csr_upd_on_halt) begin
+ csr_dcsr_cause <= hart_haltstatus.cause;
+ end
+ end
+end
+
+// Debug PC register
+//------------------------------------------------------------------------------
+// Saves the virtual address of the next instruction to be executed when Debug
+// Mode is entered. Could be changed by debugger
+
+assign csr_dpc_wr = csr_wr & csr_dpc_sel;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ csr_dpc_ff <= '0;
+ end else if(clk_en) begin
+ csr_dpc_ff <= csr_dpc_next;
+ end
+end
+
+assign csr_dpc_next = csr_upd_on_halt ? pipe2hdu_pc_curr_i
+ : csr_dpc_wr ? csr_wr_data
+ : csr_dpc_ff;
+assign csr_dpc_out = csr_dpc_sel ? csr_dpc_ff : '0;
+
+// Debug Scratch 0 register
+//------------------------------------------------------------------------------
+
+assign csr_dscratch0_resp = (~dm2hdu_dreg_resp_i | dm2hdu_dreg_fail_i)
+ ? SCR1_CSR_RESP_ER
+ : SCR1_CSR_RESP_OK;
+assign csr_dscratch0_out = csr_dscratch0_sel ? dm2hdu_dreg_rdata_i : '0;
+
+//------------------------------------------------------------------------------
+// HDU <-> DM interface
+//------------------------------------------------------------------------------
+
+assign hdu2dm_hart_event_o = dfsm_event;
+
+// HART status
+always_comb begin
+ hdu2dm_hart_status_o = '0;
+ hdu2dm_hart_status_o.dbg_state = dbg_state;
+ hdu2dm_hart_status_o.except = dbg_state_dhalted & hart_haltstatus.except;
+ hdu2dm_hart_status_o.ebreak = dbg_state_dhalted & (hart_haltstatus.cause == SCR1_HDU_HALTCAUSE_EBREAK);
+end
+
+assign hdu2dm_cmd_rcode_o = dbg_state_reset
+ ? ~pipe2hdu_rdc_qlfy_i | ~pipe2hdu_init_pc_i | ~dm2hdu_cmd_req_i
+ : ~pipe2hdu_rdc_qlfy_i | ~dfsm_update;
+
+always_comb begin
+ hdu2dm_cmd_resp_o = 1'b0;
+
+ case (dbg_state)
+ SCR1_HDU_DBGSTATE_RESET: begin
+ hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & pipe2hdu_init_pc_i & dm2hdu_cmd_req_i;
+ end
+
+ SCR1_HDU_DBGSTATE_RUN: begin
+ hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & dfsm_update & dm2hdu_cmd_req_i;
+ end
+
+ SCR1_HDU_DBGSTATE_DHALTED: begin
+ hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i ? dfsm_update : dm2hdu_cmd_req_i;
+ end
+
+ SCR1_HDU_DBGSTATE_DRUN: begin
+ hdu2dm_cmd_resp_o = (~pipe2hdu_rdc_qlfy_i | dfsm_update) & dm2hdu_cmd_req_i;
+ end
+
+ default: begin
+ hdu2dm_cmd_resp_o = 'X;
+ end
+ endcase
+end
+
+assign hdu2dm_pbuf_addr_o = pbuf_addr_ff;
+assign hdu2dm_dreg_req_o = csr_dscratch0_sel;
+assign hdu2dm_dreg_wr_o = csr_wr & csr_dscratch0_sel;
+assign hdu2dm_dreg_wdata_o = csr_wr_data;
+
+//------------------------------------------------------------------------------
+// HDU <-> EXU interface
+//------------------------------------------------------------------------------
+
+assign hdu2exu_dbg_halted_o = (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED)
+ | (~pipe2hdu_rdc_qlfy_i & ~dbg_state_run);
+assign hdu2exu_dbg_run_start_o = dbg_state_dhalted & pipe2hdu_rdc_qlfy_i & dfsm_update;
+assign hdu2exu_dbg_halt2run_o = hdu2exu_dbg_halted_o & hart_resume_req
+`ifdef SCR1_CLKCTRL_EN
+ & clk_pipe_en
+`endif // SCR1_CLKCTRL_EN
+ ;
+assign hdu2exu_dbg_run2halt_o = hart_halt_ack;
+
+assign hdu2exu_pbuf_fetch_o = hart_runctrl.fetch_src;
+assign hdu2exu_irq_dsbl_o = hart_runctrl.irq_dsbl;
+assign hdu2exu_pc_advmt_dsbl_o = hart_runctrl.pc_advmt_dsbl;
+// No change in arch. state if dmode caused by breakpoint
+assign hdu2exu_no_commit_o = dmode_cause_ebreak
+`ifdef SCR1_TDU_EN
+ | dmode_cause_tmreq
+`endif // SCR1_TDU_EN
+ ;
+assign hdu2exu_dmode_sstep_en_o = hart_runctrl.redirect.sstep;
+assign hdu2exu_dbg_new_pc_o = csr_dpc_ff;
+
+//------------------------------------------------------------------------------
+// HDU <-> IFU interface
+//------------------------------------------------------------------------------
+
+assign hdu2ifu_pbuf_instr_vd_o = (pbuf_fsm_fetch | pbuf_fsm_excinj)
+ & ~pbuf_instr_wait_latching;
+assign hdu2ifu_pbuf_instr_err_o = pbuf_fsm_excinj;
+
+generate if (HART_PBUF_INSTR_REGOUT_EN) begin
+ always_ff @(posedge clk) begin
+ hdu2ifu_pbuf_instr_o <= dm2hdu_pbuf_instr_i;
+ end
+end else begin
+ assign hdu2ifu_pbuf_instr_o = dm2hdu_pbuf_instr_i;
+end endgenerate
+
+//------------------------------------------------------------------------------
+// HDU <-> CSR interface
+//------------------------------------------------------------------------------
+
+assign csr_addr_dscratch0 = (csr2hdu_addr_i == SCR1_HDU_DBGCSR_OFFS_DSCRATCH0);
+
+assign hdu2csr_resp_o = ~dbg_state_drun ? SCR1_CSR_RESP_ER
+ : csr_addr_dscratch0 ? csr_dscratch0_resp
+ : csr2hdu_req_i ? SCR1_CSR_RESP_OK
+ : SCR1_CSR_RESP_ER;
+assign hdu2csr_rdata_o = csr_rd_data;
+
+`ifdef SCR1_TDU_EN
+//------------------------------------------------------------------------------
+// HDU <-> TDU interface
+//------------------------------------------------------------------------------
+
+assign hdu2tdu_hwbrk_dsbl_o = hart_runctrl.hwbrkpt_dsbl;
+`endif // SCR1_TDU_EN
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+SVA_HDU_XCHECK_COMMON :
+ assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown( {rst_n,clk,clk_en,csr2hdu_req_i,pipe2hdu_rdc_qlfy_i} )
+ )
+ else $error("HDU Error: common signals are in X state");
+
+SVA_HDU_XCHECK_CSR_INTF :
+ assert property (
+ @(negedge clk) disable iff (~rst_n)
+ csr2hdu_req_i |-> !$isunknown( {csr2hdu_cmd_i,csr2hdu_addr_i,csr2hdu_wdata_i} )
+ )
+ else $error("HDU Error: CSR i/f is in X state");
+
+SVA_HDU_XCHECK_DM_INTF :
+ assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown( {dm2hdu_cmd_req_i,dm2hdu_cmd_i,dm2hdu_dreg_resp_i,
+ dm2hdu_dreg_fail_i} )
+ )
+ else $error("HDU Error: DM i/f is in X state");
+
+SVA_HDU_XCHECK_TDU_INTF :
+ assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown( {tdu2hdu_dmode_req_i,exu2hdu_ibrkpt_hw_i} )
+ )
+ else $error("HDU Error: TDU i/f is in X state");
+
+SVA_HDU_XCHECK_HART_INTF :
+ assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown( {pipe2hdu_exu_busy_i,pipe2hdu_instret_i,pipe2hdu_init_pc_i,pipe2hdu_exu_exc_req_i,pipe2hdu_brkpt_i,
+ pipe2hdu_pc_curr_i,ifu2hdu_pbuf_instr_rdy_i} )
+ )
+ else $error("HDU Error: HART i/f is in X state");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_hdu
+
+`endif // SCR1_DBG_EN
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ialu.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ialu.sv
new file mode 100644
index 0000000..eec1c20
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ialu.sv
@@ -0,0 +1,720 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_ialu.sv>
+/// @brief Integer Arithmetic Logic Unit (IALU)
+///
+
+//-------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Performs addition/subtraction and arithmetic and branch comparisons
+ // - Performs logical operations (AND(I), OR(I), XOR(I))
+ // - Performs address calculation for branch, jump, DMEM load and store and AUIPC
+ // instructions
+ // - Performs shift operations
+ // - Performs MUL/DIV operations
+ //
+ // Structure:
+ // - Main adder
+ // - Address adder
+ // - Shift logic
+ // - MUL/DIV logic
+ // - Output result multiplexer
+ //
+//-------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+`include "scr1_riscv_isa_decoding.svh"
+`include "scr1_search_ms1.svh"
+
+
+module scr1_pipe_ialu (
+`ifdef SCR1_RVM_EXT
+ // Common
+ input logic clk, // IALU clock
+ input logic rst_n, // IALU reset
+ input logic exu2ialu_rvm_cmd_vd_i, // MUL/DIV command valid
+ output logic ialu2exu_rvm_res_rdy_o, // MUL/DIV result ready
+`endif // SCR1_RVM_EXT
+
+ // Main adder
+ input logic [`SCR1_XLEN-1:0] exu2ialu_main_op1_i, // main ALU 1st operand
+ input logic [`SCR1_XLEN-1:0] exu2ialu_main_op2_i, // main ALU 2nd operand
+ input type_scr1_ialu_cmd_sel_e exu2ialu_cmd_i, // IALU command
+ output logic [`SCR1_XLEN-1:0] ialu2exu_main_res_o, // main ALU result
+ output logic ialu2exu_cmp_res_o, // IALU comparison result
+
+ // Address adder
+ input logic [`SCR1_XLEN-1:0] exu2ialu_addr_op1_i, // Address adder 1st operand
+ input logic [`SCR1_XLEN-1:0] exu2ialu_addr_op2_i, // Address adder 2nd operand
+ output logic [`SCR1_XLEN-1:0] ialu2exu_addr_res_o // Address adder result
+);
+
+//-------------------------------------------------------------------------------
+// Local parameters declaration
+//-------------------------------------------------------------------------------
+
+`ifdef SCR1_RVM_EXT
+ `ifdef SCR1_FAST_MUL
+localparam SCR1_MUL_WIDTH = `SCR1_XLEN;
+localparam SCR1_MUL_RES_WIDTH = 2 * `SCR1_XLEN;
+localparam SCR1_MDU_SUM_WIDTH = `SCR1_XLEN + 1;
+ `else
+localparam SCR1_MUL_STG_NUM = 32;
+localparam SCR1_MUL_WIDTH = 32 / SCR1_MUL_STG_NUM;
+localparam SCR1_MUL_CNT_INIT = 32'b1 << (`SCR1_XLEN/SCR1_MUL_WIDTH - 2);
+localparam SCR1_MDU_SUM_WIDTH = `SCR1_XLEN + SCR1_MUL_WIDTH;
+ `endif // ~SCR1_FAST_MUL
+localparam SCR1_DIV_WIDTH = 1;
+localparam SCR1_DIV_CNT_INIT = 32'b1 << (`SCR1_XLEN/SCR1_DIV_WIDTH - 2);
+`endif // SCR1_RVM_EXT
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+
+typedef struct packed {
+ logic z; // Zero
+ logic s; // Sign
+ logic o; // Overflow
+ logic c; // Carry
+} type_scr1_ialu_flags_s;
+
+ `ifdef SCR1_RVM_EXT
+typedef enum logic [1:0] {
+ SCR1_IALU_MDU_FSM_IDLE,
+ SCR1_IALU_MDU_FSM_ITER,
+ SCR1_IALU_MDU_FSM_CORR
+} type_scr1_ialu_fsm_state;
+
+typedef enum logic [1:0] {
+ SCR1_IALU_MDU_NONE,
+ SCR1_IALU_MDU_MUL,
+ SCR1_IALU_MDU_DIV
+} type_scr1_ialu_mdu_cmd;
+ `endif // SCR1_RVM_EXT
+
+//-------------------------------------------------------------------------------
+// Local signals declaration
+//-------------------------------------------------------------------------------
+
+// Main adder signals
+logic [`SCR1_XLEN:0] main_sum_res; // Main adder result
+type_scr1_ialu_flags_s main_sum_flags; // Main adder flags
+logic main_sum_pos_ovflw; // Main adder positive overflow
+logic main_sum_neg_ovflw; // Main adder negative overflow
+logic main_ops_diff_sgn; // Main adder operands have different signs
+logic main_ops_non_zero; // Both main adder operands are NOT 0
+
+// Shifter signals
+logic ialu_cmd_shft; // IALU command is shift
+logic signed [`SCR1_XLEN-1:0] shft_op1; // SHIFT operand 1
+logic [4:0] shft_op2; // SHIFT operand 2
+logic [1:0] shft_cmd; // SHIFT command: 00 - logical left, 10 - logical right, 11 - arithmetical right
+logic [`SCR1_XLEN-1:0] shft_res; // SHIFT result
+
+// MUL/DIV signals
+`ifdef SCR1_RVM_EXT
+// MUL/DIV FSM control signals
+logic mdu_cmd_is_iter; // MDU Command is iterative
+logic mdu_iter_req; // Request iterative stage
+logic mdu_iter_rdy; // Iteration is ready
+logic mdu_corr_req; // DIV/REM(U) correction request
+logic div_corr_req; // Correction request for DIV operation
+logic rem_corr_req; // Correction request for REM(U) operations
+
+// MUL/DIV FSM signals
+type_scr1_ialu_fsm_state mdu_fsm_ff; // Current FSM state
+type_scr1_ialu_fsm_state mdu_fsm_next; // Next FSM state
+logic mdu_fsm_idle; // MDU FSM is in IDLE state
+`ifdef SCR1_TRGT_SIMULATION
+logic mdu_fsm_iter; // MDU FSM is in ITER state
+`endif // SCR1_TRGT_SIMULATION
+logic mdu_fsm_corr; // MDU FSM is in CORR state
+
+// MDU command signals
+type_scr1_ialu_mdu_cmd mdu_cmd; // MDU command: 00 - NONE, 01 - MUL, 10 - DIV
+logic mdu_cmd_mul; // MDU command is MUL(HSU)
+logic mdu_cmd_div; // MDU command is DIV(U)/REM(U)
+logic [1:0] mul_cmd; // MUL command: 00 - MUL, 01 - MULH, 10 - MULHSU, 11 - MULHU
+logic mul_cmd_hi; // High part of MUL result is requested
+logic [1:0] div_cmd; // DIV command: 00 - DIV, 01 - DIVU, 10 - REM, 11 - REMU
+logic div_cmd_div; // DIV command is DIV
+logic div_cmd_rem; // DIV command is REM(U)
+
+// Multiplier signals
+logic mul_op1_is_sgn; // First MUL operand is signed
+logic mul_op2_is_sgn; // Second MUL operand is signed
+logic mul_op1_sgn; // First MUL operand is negative
+logic mul_op2_sgn; // Second MUL operand is negative
+logic signed [`SCR1_XLEN:0] mul_op1; // MUL operand 1
+logic signed [SCR1_MUL_WIDTH:0] mul_op2; // MUL operand 1
+ `ifdef SCR1_FAST_MUL
+logic signed [SCR1_MUL_RES_WIDTH-1:0] mul_res; // MUL result
+ `else // ~SCR1_FAST_MUL
+logic signed [SCR1_MDU_SUM_WIDTH:0] mul_part_prod;
+logic [`SCR1_XLEN-1:0] mul_res_hi;
+logic [`SCR1_XLEN-1:0] mul_res_lo;
+ `endif // ~SCR1_FAST_MUL
+
+// Divisor signals
+logic div_ops_are_sgn;
+logic div_op1_is_neg;
+logic div_op2_is_neg;
+logic div_res_rem_c;
+logic [`SCR1_XLEN-1:0] div_res_rem;
+logic [`SCR1_XLEN-1:0] div_res_quo;
+logic div_quo_bit;
+logic div_dvdnd_lo_upd;
+logic [`SCR1_XLEN-1:0] div_dvdnd_lo_ff;
+logic [`SCR1_XLEN-1:0] div_dvdnd_lo_next;
+
+// MDU adder signals
+logic mdu_sum_sub; // MDU adder operation: 0 - add, 1 - sub
+logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_op1; // MDU adder operand 1
+logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_op2; // MDU adder operand 2
+logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_res; // MDU adder result
+
+// MDU iteration counter signals
+logic mdu_iter_cnt_en;
+logic [`SCR1_XLEN-1:0] mdu_iter_cnt;
+logic [`SCR1_XLEN-1:0] mdu_iter_cnt_next;
+
+// Intermediate results registers
+logic mdu_res_upd;
+logic mdu_res_c_ff;
+logic mdu_res_c_next;
+logic [`SCR1_XLEN-1:0] mdu_res_hi_ff;
+logic [`SCR1_XLEN-1:0] mdu_res_hi_next;
+logic [`SCR1_XLEN-1:0] mdu_res_lo_ff;
+logic [`SCR1_XLEN-1:0] mdu_res_lo_next;
+`endif // SCR1_RVM_EXT
+
+//-------------------------------------------------------------------------------
+// Main adder
+//-------------------------------------------------------------------------------
+//
+ // Main adder is used for the following types of operations:
+ // - Addition/subtraction (ADD/ADDI/SUB)
+ // - Branch comparisons (BEQ/BNE/BLT(U)/BGE(U))
+ // - Arithmetic comparisons (SLT(U)/SLTI(U))
+//
+
+// Carry out (MSB of main_sum_res) is evaluated correctly because the result
+// width equals to the maximum width of both the right-hand and left-hand side variables
+always_comb begin
+ main_sum_res = (exu2ialu_cmd_i != SCR1_IALU_CMD_ADD)
+ ? (exu2ialu_main_op1_i - exu2ialu_main_op2_i) // Subtraction and comparison
+ : (exu2ialu_main_op1_i + exu2ialu_main_op2_i); // Addition
+
+ main_sum_pos_ovflw = ~exu2ialu_main_op1_i[`SCR1_XLEN-1]
+ & exu2ialu_main_op2_i[`SCR1_XLEN-1]
+ & main_sum_res[`SCR1_XLEN-1];
+ main_sum_neg_ovflw = exu2ialu_main_op1_i[`SCR1_XLEN-1]
+ & ~exu2ialu_main_op2_i[`SCR1_XLEN-1]
+ & ~main_sum_res[`SCR1_XLEN-1];
+
+ // FLAGS1 - flags for comparison (result of subtraction)
+ main_sum_flags.c = main_sum_res[`SCR1_XLEN];
+ main_sum_flags.z = ~|main_sum_res[`SCR1_XLEN-1:0];
+ main_sum_flags.s = main_sum_res[`SCR1_XLEN-1];
+ main_sum_flags.o = main_sum_pos_ovflw | main_sum_neg_ovflw;
+end
+
+//-------------------------------------------------------------------------------
+// Address adder
+//-------------------------------------------------------------------------------
+//
+ // Additional adder is used for the following types of operations:
+ // - PC-based address calculation (AUIPC)
+ // - IMEM branch address calculation (BEQ/BNE/BLT(U)/BGE(U))
+ // - IMEM jump address calculation (JAL/JALR)
+ // - DMEM load address calculation (LB(U)/LH(U)/LW)
+ // - DMEM store address calculation (SB/SH/SW)
+//
+
+assign ialu2exu_addr_res_o = exu2ialu_addr_op1_i + exu2ialu_addr_op2_i;
+
+//-------------------------------------------------------------------------------
+// Shift logic
+//-------------------------------------------------------------------------------
+ //
+ // Shift logic supports the following types of shift operations:
+ // - Logical left shift (SLLI/SLL)
+ // - Logical right shift (SRLI/SRL)
+ // - Arithmetic right shift (SRAI/SRA)
+//
+
+assign ialu_cmd_shft = (exu2ialu_cmd_i == SCR1_IALU_CMD_SLL)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_SRL)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_SRA);
+assign shft_cmd = ialu_cmd_shft
+ ? {(exu2ialu_cmd_i != SCR1_IALU_CMD_SLL),
+ (exu2ialu_cmd_i == SCR1_IALU_CMD_SRA)}
+ : 2'b00;
+
+always_comb begin
+ shft_op1 = exu2ialu_main_op1_i;
+ shft_op2 = exu2ialu_main_op2_i[4:0];
+ case (shft_cmd)
+ 2'b10 : shft_res = shft_op1 >> shft_op2;
+ 2'b11 : shft_res = shft_op1 >>> shft_op2;
+ default : shft_res = shft_op1 << shft_op2;
+ endcase
+end
+
+`ifdef SCR1_RVM_EXT
+//-------------------------------------------------------------------------------
+// MUL/DIV logic
+//-------------------------------------------------------------------------------
+//
+ // MUL/DIV instructions use the following functional units:
+ // - MUL/DIV FSM control logic, including iteration number counter
+ // - MUL/DIV FSM
+ // - MUL logic
+ // - DIV logic
+ // - MDU adder to produce an intermediate result
+ // - 2 registers to save the intermediate result (shared between MUL and DIV
+ // operations)
+//
+
+//-------------------------------------------------------------------------------
+// MUL/DIV FSM Control logic
+//-------------------------------------------------------------------------------
+
+assign mdu_cmd_div = (exu2ialu_cmd_i == SCR1_IALU_CMD_DIV)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_DIVU)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_REM)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_REMU);
+assign mdu_cmd_mul = (exu2ialu_cmd_i == SCR1_IALU_CMD_MUL)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULH)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU)
+ | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHSU);
+
+assign mdu_cmd = mdu_cmd_div ? SCR1_IALU_MDU_DIV
+ : mdu_cmd_mul ? SCR1_IALU_MDU_MUL
+ : SCR1_IALU_MDU_NONE;
+
+assign main_ops_non_zero = |exu2ialu_main_op1_i & |exu2ialu_main_op2_i;
+assign main_ops_diff_sgn = exu2ialu_main_op1_i[`SCR1_XLEN-1]
+ ^ exu2ialu_main_op2_i[`SCR1_XLEN-1];
+
+ `ifdef SCR1_FAST_MUL
+ assign mdu_cmd_is_iter = mdu_cmd_div;
+ `else // ~SCR1_FAST_MUL
+ assign mdu_cmd_is_iter = mdu_cmd_mul | mdu_cmd_div;
+ `endif // ~SCR1_FAST_MUL
+
+assign mdu_iter_req = mdu_cmd_is_iter ? (main_ops_non_zero & mdu_fsm_idle) : 1'b0;
+assign mdu_iter_rdy = mdu_iter_cnt[0];
+
+assign div_cmd_div = (div_cmd == 2'b00);
+assign div_cmd_rem = div_cmd[1];
+
+// Correction request signals
+assign div_corr_req = div_cmd_div & main_ops_diff_sgn;
+assign rem_corr_req = div_cmd_rem & |div_res_rem & (div_op1_is_neg ^ div_res_rem_c);
+assign mdu_corr_req = mdu_cmd_div & (div_corr_req | rem_corr_req);
+
+// MDU iteration counter
+//------------------------------------------------------------------------------
+
+assign mdu_iter_cnt_en = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
+
+always_ff @(posedge clk) begin
+ if (mdu_iter_cnt_en) begin
+ mdu_iter_cnt <= mdu_iter_cnt_next;
+ end
+end
+
+assign mdu_iter_cnt_next = ~mdu_fsm_idle ? mdu_iter_cnt >> 1
+ : mdu_cmd_div ? SCR1_DIV_CNT_INIT
+ `ifndef SCR1_FAST_MUL
+ : mdu_cmd_mul ? SCR1_MUL_CNT_INIT
+ `endif // ~SCR1_FAST_MUL
+ : mdu_iter_cnt;
+
+//-------------------------------------------------------------------------------
+// MUL/DIV FSM
+//-------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ mdu_fsm_ff <= SCR1_IALU_MDU_FSM_IDLE;
+ end else begin
+ mdu_fsm_ff <= mdu_fsm_next;
+ end
+end
+
+always_comb begin
+ mdu_fsm_next = SCR1_IALU_MDU_FSM_IDLE;
+
+ if (exu2ialu_rvm_cmd_vd_i) begin
+ case (mdu_fsm_ff)
+ SCR1_IALU_MDU_FSM_IDLE : begin
+ mdu_fsm_next = mdu_iter_req ? SCR1_IALU_MDU_FSM_ITER
+ : SCR1_IALU_MDU_FSM_IDLE;
+ end
+ SCR1_IALU_MDU_FSM_ITER : begin
+ mdu_fsm_next = ~mdu_iter_rdy ? SCR1_IALU_MDU_FSM_ITER
+ : mdu_corr_req ? SCR1_IALU_MDU_FSM_CORR
+ : SCR1_IALU_MDU_FSM_IDLE;
+ end
+ SCR1_IALU_MDU_FSM_CORR : begin
+ mdu_fsm_next = SCR1_IALU_MDU_FSM_IDLE;
+ end
+ endcase
+ end
+end
+
+assign mdu_fsm_idle = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_IDLE);
+`ifdef SCR1_TRGT_SIMULATION
+assign mdu_fsm_iter = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_ITER);
+`endif // SCR1_TRGT_SIMULATION
+assign mdu_fsm_corr = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_CORR);
+
+//-------------------------------------------------------------------------------
+// Multiplier logic
+//-------------------------------------------------------------------------------
+//
+ // Multiplication has 2 options: fast (1 cycle) and Radix-2 (32 cycles) multiplication.
+ //
+ // 1. Fast multiplication uses the straightforward approach when 2 operands are
+ // multiplied in one cycle
+ //
+ // 2. Radix-2 multiplication uses 2 registers (high and low part of multiplication)
+ //
+ // Radix-2 algorithm:
+ // 1. Initialize registers
+ // 2. Create a partial product by multiplying multiplicand by the LSB of multiplier
+ // 3. Add the partial product to the previous (intermediate) value of multiplication
+ // result (stored into high and low parts of multiplication result register)
+ // 4. Shift the low part of multiplication result register right
+ // 4. Store the addition result into the high part of multiplication result register
+ // 6. If iteration is not ready, go to step 2. Otherwise multiplication is done
+ //
+//
+
+assign mul_cmd = {((exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHSU)),
+ ((exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULH))};
+
+assign mul_cmd_hi = |mul_cmd;
+assign mul_op1_is_sgn = ~&mul_cmd;
+assign mul_op2_is_sgn = ~mul_cmd[1];
+assign mul_op1_sgn = mul_op1_is_sgn & exu2ialu_main_op1_i[`SCR1_XLEN-1];
+assign mul_op2_sgn = mul_op2_is_sgn & exu2ialu_main_op2_i[`SCR1_XLEN-1];
+
+`ifdef SCR1_FAST_MUL
+assign mul_op1 = mdu_cmd_mul ? $signed({mul_op1_sgn, exu2ialu_main_op1_i}) : '0;
+assign mul_op2 = mdu_cmd_mul ? $signed({mul_op2_sgn, exu2ialu_main_op2_i}) : '0;
+assign mul_res = mdu_cmd_mul ? mul_op1 * mul_op2 : 'sb0;
+`else // ~SCR1_FAST_MUL
+assign mul_op1 = mdu_cmd_mul ? $signed({mul_op1_sgn, exu2ialu_main_op1_i}) : '0;
+assign mul_op2 = ~mdu_cmd_mul ? '0
+ : mdu_fsm_idle ? $signed({1'b0, exu2ialu_main_op2_i[SCR1_MUL_WIDTH-1:0]})
+ : $signed({(mdu_iter_cnt[0] & mul_op2_is_sgn & mdu_res_lo_ff[SCR1_MUL_WIDTH-1]),
+ mdu_res_lo_ff[SCR1_MUL_WIDTH-1:0]});
+
+assign mul_part_prod = mdu_cmd_mul ? mul_op1 * mul_op2 : 'sb0;
+assign {mul_res_hi, mul_res_lo} = ~mdu_cmd_mul ? '0
+ : mdu_fsm_idle ? ({mdu_sum_res, exu2ialu_main_op2_i[`SCR1_XLEN-1:SCR1_MUL_WIDTH]})
+ : ({mdu_sum_res, mdu_res_lo_ff[`SCR1_XLEN-1:SCR1_MUL_WIDTH]});
+`endif // ~SCR1_FAST_MUL
+
+//-------------------------------------------------------------------------------
+// Divider logic
+//-------------------------------------------------------------------------------
+//
+ // Division uses a non-restoring algorithm. 3 registers are used:
+ // - Remainder register
+ // - Quotient register
+ // - Dividend low part register (for corner case quotient bit calculation)
+ //
+ // Algorithm:
+ // 1. Initialize registers
+ // 2. Shift remainder and dividend low part registers left
+ // 3. Compare remainder register with the divisor (taking previous quotient bit
+ // and operands signs into account) and calculate quotient bit based on the
+ // comparison results
+ // 4. Shift quotient register left, append quotient bit to the quotient register
+ // 5. If iteration is not ready, go to step 2. Otherwise go to step 6
+ // 6. Do correction if necessary, otherwise division is done
+ //
+ // Quotient bit calculation has a corner case:
+ // When dividend is negative result carry bit check takes into account only
+ // the case of remainder register been greater than divisor. To handle
+ // equality case we should check if both the comparison result and the
+ // lower part of dividend are zero
+//
+
+assign div_cmd = {((exu2ialu_cmd_i == SCR1_IALU_CMD_REM) | (exu2ialu_cmd_i == SCR1_IALU_CMD_REMU)),
+ ((exu2ialu_cmd_i == SCR1_IALU_CMD_REMU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_DIVU))};
+
+assign div_ops_are_sgn = ~div_cmd[0];
+assign div_op1_is_neg = div_ops_are_sgn & exu2ialu_main_op1_i[`SCR1_XLEN-1];
+assign div_op2_is_neg = div_ops_are_sgn & exu2ialu_main_op2_i[`SCR1_XLEN-1];
+
+always_comb begin
+ div_res_rem_c = '0;
+ div_res_rem = '0;
+ div_res_quo = '0;
+ div_quo_bit = 1'b0;
+ if (mdu_cmd_div & ~mdu_fsm_corr) begin
+ div_res_rem_c = mdu_sum_res[SCR1_MDU_SUM_WIDTH-1];
+ div_res_rem = mdu_sum_res[SCR1_MDU_SUM_WIDTH-2:0];
+ div_quo_bit = ~(div_op1_is_neg ^ div_res_rem_c)
+ | (div_op1_is_neg & ({mdu_sum_res, div_dvdnd_lo_next} == '0));
+ div_res_quo = mdu_fsm_idle
+ ? {'0, div_quo_bit}
+ : {mdu_res_lo_ff[`SCR1_XLEN-2:0], div_quo_bit};
+ end
+end
+
+// Dividend low part register
+//------------------------------------------------------------------------------
+
+assign div_dvdnd_lo_upd = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
+
+always_ff @(posedge clk) begin
+ if (div_dvdnd_lo_upd) begin
+ div_dvdnd_lo_ff <= div_dvdnd_lo_next;
+ end
+end
+
+assign div_dvdnd_lo_next = (~mdu_cmd_div | mdu_fsm_corr) ? '0
+ : mdu_fsm_idle ? exu2ialu_main_op1_i << 1
+ : div_dvdnd_lo_ff << 1;
+
+//-------------------------------------------------------------------------------
+// MDU adder
+//-------------------------------------------------------------------------------
+
+always_comb begin
+ mdu_sum_sub = 1'b0;
+ mdu_sum_op1 = '0;
+ mdu_sum_op2 = '0;
+ case (mdu_cmd)
+ SCR1_IALU_MDU_DIV : begin
+ logic sgn;
+ logic inv;
+
+ sgn = mdu_fsm_corr ? div_op1_is_neg ^ mdu_res_c_ff
+ : mdu_fsm_idle ? 1'b0
+ : ~mdu_res_lo_ff[0];
+ inv = div_ops_are_sgn & main_ops_diff_sgn;
+ mdu_sum_sub = ~inv ^ sgn;
+ mdu_sum_op1 = mdu_fsm_corr ? $signed({1'b0, mdu_res_hi_ff})
+ : mdu_fsm_idle ? $signed({div_op1_is_neg, exu2ialu_main_op1_i[`SCR1_XLEN-1]})
+ : $signed({mdu_res_hi_ff, div_dvdnd_lo_ff[`SCR1_XLEN-1]});
+ mdu_sum_op2 = $signed({div_op2_is_neg, exu2ialu_main_op2_i});
+ end
+`ifndef SCR1_FAST_MUL
+ SCR1_IALU_MDU_MUL : begin
+ mdu_sum_op1 = mdu_fsm_idle
+ ? '0
+ : $signed({(mul_op1_is_sgn & mdu_res_hi_ff[`SCR1_XLEN-1]), mdu_res_hi_ff});
+ mdu_sum_op2 = mul_part_prod;
+ end
+`endif // SCR1_FAST_MUL
+ default : begin end
+ endcase
+ mdu_sum_res = mdu_sum_sub
+ ? (mdu_sum_op1 - mdu_sum_op2)
+ : (mdu_sum_op1 + mdu_sum_op2);
+end
+
+//-------------------------------------------------------------------------------
+// MUL/DIV intermediate results registers
+//-------------------------------------------------------------------------------
+
+assign mdu_res_upd = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
+
+always_ff @(posedge clk) begin
+ if (mdu_res_upd) begin
+ mdu_res_c_ff <= mdu_res_c_next;
+ mdu_res_hi_ff <= mdu_res_hi_next;
+ mdu_res_lo_ff <= mdu_res_lo_next;
+ end
+end
+
+assign mdu_res_c_next = mdu_cmd_div ? div_res_rem_c : mdu_res_c_ff;
+assign mdu_res_hi_next = mdu_cmd_div ? div_res_rem
+ `ifndef SCR1_FAST_MUL
+ : mdu_cmd_mul ? mul_res_hi
+ `endif // SCR1_FAST_MUL
+ : mdu_res_hi_ff;
+assign mdu_res_lo_next = mdu_cmd_div ? div_res_quo
+ `ifndef SCR1_FAST_MUL
+ : mdu_cmd_mul ? mul_res_lo
+ `endif // SCR1_FAST_MUL
+ : mdu_res_lo_ff;
+`endif // SCR1_RVM_EXT
+
+//-------------------------------------------------------------------------------
+// Operation result forming
+//-------------------------------------------------------------------------------
+
+always_comb begin
+ ialu2exu_main_res_o = '0;
+ ialu2exu_cmp_res_o = 1'b0;
+`ifdef SCR1_RVM_EXT
+ ialu2exu_rvm_res_rdy_o = 1'b1;
+`endif // SCR1_RVM_EXT
+
+ case (exu2ialu_cmd_i)
+ SCR1_IALU_CMD_AND : begin
+ ialu2exu_main_res_o = exu2ialu_main_op1_i & exu2ialu_main_op2_i;
+ end
+ SCR1_IALU_CMD_OR : begin
+ ialu2exu_main_res_o = exu2ialu_main_op1_i | exu2ialu_main_op2_i;
+ end
+ SCR1_IALU_CMD_XOR : begin
+ ialu2exu_main_res_o = exu2ialu_main_op1_i ^ exu2ialu_main_op2_i;
+ end
+ SCR1_IALU_CMD_ADD : begin
+ ialu2exu_main_res_o = main_sum_res[`SCR1_XLEN-1:0];
+ end
+ SCR1_IALU_CMD_SUB : begin
+ ialu2exu_main_res_o = main_sum_res[`SCR1_XLEN-1:0];
+ end
+ SCR1_IALU_CMD_SUB_LT : begin
+ ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.s ^ main_sum_flags.o);
+ ialu2exu_cmp_res_o = main_sum_flags.s ^ main_sum_flags.o;
+ end
+ SCR1_IALU_CMD_SUB_LTU : begin
+ ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.c);
+ ialu2exu_cmp_res_o = main_sum_flags.c;
+ end
+ SCR1_IALU_CMD_SUB_EQ : begin
+ ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.z);
+ ialu2exu_cmp_res_o = main_sum_flags.z;
+ end
+ SCR1_IALU_CMD_SUB_NE : begin
+ ialu2exu_main_res_o = `SCR1_XLEN'(~main_sum_flags.z);
+ ialu2exu_cmp_res_o = ~main_sum_flags.z;
+ end
+ SCR1_IALU_CMD_SUB_GE : begin
+ ialu2exu_main_res_o = `SCR1_XLEN'(~(main_sum_flags.s ^ main_sum_flags.o));
+ ialu2exu_cmp_res_o = ~(main_sum_flags.s ^ main_sum_flags.o);
+ end
+ SCR1_IALU_CMD_SUB_GEU : begin
+ ialu2exu_main_res_o = `SCR1_XLEN'(~main_sum_flags.c);
+ ialu2exu_cmp_res_o = ~main_sum_flags.c;
+ end
+ SCR1_IALU_CMD_SLL,
+ SCR1_IALU_CMD_SRL,
+ SCR1_IALU_CMD_SRA: begin
+ ialu2exu_main_res_o = shft_res;
+ end
+`ifdef SCR1_RVM_EXT
+ SCR1_IALU_CMD_MUL,
+ SCR1_IALU_CMD_MULHU,
+ SCR1_IALU_CMD_MULHSU,
+ SCR1_IALU_CMD_MULH : begin
+ `ifdef SCR1_FAST_MUL
+ ialu2exu_main_res_o = mul_cmd_hi
+ ? mul_res[SCR1_MUL_RES_WIDTH-1:`SCR1_XLEN]
+ : mul_res[`SCR1_XLEN-1:0];
+ `else // ~SCR1_FAST_MUL
+ case (mdu_fsm_ff)
+ SCR1_IALU_MDU_FSM_IDLE : begin
+ ialu2exu_main_res_o = '0;
+ ialu2exu_rvm_res_rdy_o = ~mdu_iter_req;
+ end
+ SCR1_IALU_MDU_FSM_ITER : begin
+ ialu2exu_main_res_o = mul_cmd_hi ? mul_res_hi : mul_res_lo;
+ ialu2exu_rvm_res_rdy_o = mdu_iter_rdy;
+ end
+ endcase
+ `endif // ~SCR1_FAST_MUL
+ end
+ SCR1_IALU_CMD_DIV,
+ SCR1_IALU_CMD_DIVU,
+ SCR1_IALU_CMD_REM,
+ SCR1_IALU_CMD_REMU : begin
+ case (mdu_fsm_ff)
+ SCR1_IALU_MDU_FSM_IDLE : begin
+ ialu2exu_main_res_o = (|exu2ialu_main_op2_i | div_cmd_rem)
+ ? exu2ialu_main_op1_i
+ : '1;
+ ialu2exu_rvm_res_rdy_o = ~mdu_iter_req;
+ end
+ SCR1_IALU_MDU_FSM_ITER : begin
+ ialu2exu_main_res_o = div_cmd_rem ? div_res_rem : div_res_quo;
+ ialu2exu_rvm_res_rdy_o = mdu_iter_rdy & ~mdu_corr_req;
+ end
+ SCR1_IALU_MDU_FSM_CORR : begin
+ ialu2exu_main_res_o = div_cmd_rem
+ ? mdu_sum_res[`SCR1_XLEN-1:0]
+ : -mdu_res_lo_ff[`SCR1_XLEN-1:0];
+ ialu2exu_rvm_res_rdy_o = 1'b1;
+ end
+ endcase
+ end
+`endif // SCR1_RVM_EXT
+ default : begin end
+ endcase
+end
+
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+`ifdef SCR1_RVM_EXT
+
+// X checks
+
+SCR1_SVA_IALU_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({exu2ialu_rvm_cmd_vd_i, mdu_fsm_ff})
+ ) else $error("IALU Error: unknown values");
+
+SCR1_SVA_IALU_XCHECK_QUEUE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2ialu_rvm_cmd_vd_i |->
+ !$isunknown({exu2ialu_main_op1_i, exu2ialu_main_op2_i, exu2ialu_cmd_i})
+ ) else $error("IALU Error: unknown values in queue");
+
+// Behavior checks
+
+SCR1_SVA_IALU_ILL_STATE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ $onehot0({~exu2ialu_rvm_cmd_vd_i, mdu_fsm_iter, mdu_fsm_corr})
+ ) else $error("IALU Error: illegal state");
+
+SCR1_SVA_IALU_JUMP_FROM_IDLE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (mdu_fsm_idle & (~exu2ialu_rvm_cmd_vd_i | ~mdu_iter_req)) |=> mdu_fsm_idle
+ ) else $error("EXU Error: illegal jump from IDLE state");
+
+SCR1_SVA_IALU_IDLE_TO_ITER : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (mdu_fsm_idle & exu2ialu_rvm_cmd_vd_i & mdu_iter_req) |=> mdu_fsm_iter
+ ) else $error("EXU Error: illegal change state form IDLE to ITER");
+
+SCR1_SVA_IALU_JUMP_FROM_ITER : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (mdu_fsm_iter & ~mdu_iter_rdy) |=> mdu_fsm_iter
+ ) else $error("EXU Error: illegal jump from ITER state");
+
+SCR1_SVA_IALU_ITER_TO_IDLE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (mdu_fsm_iter & mdu_iter_rdy & ~mdu_corr_req) |=> mdu_fsm_idle
+ ) else $error("EXU Error: illegal state change ITER to IDLE");
+
+SCR1_SVA_IALU_ITER_TO_CORR : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (mdu_fsm_iter & mdu_iter_rdy & mdu_corr_req) |=> mdu_fsm_corr
+ ) else $error("EXU Error: illegal state change ITER to CORR");
+
+SCR1_SVA_IALU_CORR_TO_IDLE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ mdu_fsm_corr |=> mdu_fsm_idle
+ ) else $error("EXU Error: illegal state stay in CORR");
+
+`endif // SCR1_RVM_EXT
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_ialu
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_idu.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_idu.sv
new file mode 100644
index 0000000..f51dacf
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_idu.sv
@@ -0,0 +1,876 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_idu.sv>
+/// @brief Instruction Decoder Unit (IDU)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Decodes the instruction and creates the appropriate control signals for EXU
+ //
+ // Structure:
+ // - Instruction decoder
+ // - IDU <-> IFU i/f
+ // - IDU <-> EXU i/f
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_memif.svh"
+`include "scr1_arch_types.svh"
+`include "scr1_riscv_isa_decoding.svh"
+`include "scr1_arch_description.svh"
+
+module scr1_pipe_idu
+(
+`ifdef SCR1_TRGT_SIMULATION
+ input logic rst_n, // IDU reset
+ input logic clk, // IDU clock
+`endif // SCR1_TRGT_SIMULATION
+
+ // IFU <-> IDU interface
+ output logic idu2ifu_rdy_o, // IDU ready for new data
+ input logic [`SCR1_IMEM_DWIDTH-1:0] ifu2idu_instr_i, // IFU instruction
+ input logic ifu2idu_imem_err_i, // Instruction access fault exception
+ input logic ifu2idu_err_rvi_hi_i, // 1 - imem fault when trying to fetch second half of an unaligned RVI instruction
+ input logic ifu2idu_vd_i, // IFU request
+
+ // IDU <-> EXU interface
+ output logic idu2exu_req_o, // IDU request
+ output type_scr1_exu_cmd_s idu2exu_cmd_o, // IDU command
+ output logic idu2exu_use_rs1_o, // Instruction uses rs1
+ output logic idu2exu_use_rs2_o, // Instruction uses rs2
+ output logic idu2exu_use_rd_o, // Instruction uses rd
+ output logic idu2exu_use_imm_o, // Instruction uses immediate
+ input logic exu2idu_rdy_i // EXU ready for new data
+);
+
+//-------------------------------------------------------------------------------
+// Local parameters declaration
+//-------------------------------------------------------------------------------
+
+localparam [SCR1_GPR_FIELD_WIDTH-1:0] SCR1_MPRF_ZERO_ADDR = 5'd0;
+localparam [SCR1_GPR_FIELD_WIDTH-1:0] SCR1_MPRF_RA_ADDR = 5'd1;
+localparam [SCR1_GPR_FIELD_WIDTH-1:0] SCR1_MPRF_SP_ADDR = 5'd2;
+
+//-------------------------------------------------------------------------------
+// Local signals declaration
+//-------------------------------------------------------------------------------
+
+logic [`SCR1_IMEM_DWIDTH-1:0] instr;
+type_scr1_instr_type_e instr_type;
+type_scr1_rvi_opcode_e rvi_opcode;
+logic rvi_illegal;
+logic [2:0] funct3;
+logic [6:0] funct7;
+logic [11:0] funct12;
+logic [4:0] shamt;
+`ifdef SCR1_RVC_EXT
+logic rvc_illegal;
+`endif // SCR1_RVC_EXT
+`ifdef SCR1_RVE_EXT
+logic rve_illegal;
+`endif // SCR1_RVE_EXT
+
+//-------------------------------------------------------------------------------
+// Instruction decoding
+//-------------------------------------------------------------------------------
+
+assign idu2ifu_rdy_o = exu2idu_rdy_i;
+assign idu2exu_req_o = ifu2idu_vd_i;
+assign instr = ifu2idu_instr_i;
+
+// RVI / RVC
+assign instr_type = type_scr1_instr_type_e'(instr[1:0]);
+
+// RVI / RVC fields
+assign rvi_opcode = type_scr1_rvi_opcode_e'(instr[6:2]); // RVI
+assign funct3 = (instr_type == SCR1_INSTR_RVI) ? instr[14:12] : instr[15:13]; // RVI / RVC
+assign funct7 = instr[31:25]; // RVI
+assign funct12 = instr[31:20]; // RVI (SYSTEM)
+assign shamt = instr[24:20]; // RVI
+
+// RV32I(MC) decode
+always_comb begin
+ // Defaults
+ idu2exu_cmd_o.instr_rvc = 1'b0;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_NONE;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_NONE;
+ idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_NONE;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_NONE;
+ idu2exu_cmd_o.jump_req = 1'b0;
+ idu2exu_cmd_o.branch_req = 1'b0;
+ idu2exu_cmd_o.mret_req = 1'b0;
+ idu2exu_cmd_o.fencei_req = 1'b0;
+ idu2exu_cmd_o.wfi_req = 1'b0;
+ idu2exu_cmd_o.rs1_addr = '0;
+ idu2exu_cmd_o.rs2_addr = '0;
+ idu2exu_cmd_o.rd_addr = '0;
+ idu2exu_cmd_o.imm = '0;
+ idu2exu_cmd_o.exc_req = 1'b0;
+ idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_INSTR_MISALIGN;
+
+ // Clock gating
+ idu2exu_use_rs1_o = 1'b0;
+ idu2exu_use_rs2_o = 1'b0;
+ idu2exu_use_rd_o = 1'b0;
+ idu2exu_use_imm_o = 1'b0;
+
+ rvi_illegal = 1'b0;
+`ifdef SCR1_RVE_EXT
+ rve_illegal = 1'b0;
+`endif // SCR1_RVE_EXT
+`ifdef SCR1_RVC_EXT
+ rvc_illegal = 1'b0;
+`endif // SCR1_RVC_EXT
+
+ // Check for IMEM access fault
+ if (ifu2idu_imem_err_i) begin
+ idu2exu_cmd_o.exc_req = 1'b1;
+ idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_INSTR_ACCESS_FAULT;
+ idu2exu_cmd_o.instr_rvc = ifu2idu_err_rvi_hi_i;
+ end else begin // no imem fault
+ case (instr_type)
+ SCR1_INSTR_RVI : begin
+ idu2exu_cmd_o.rs1_addr = instr[19:15];
+ idu2exu_cmd_o.rs2_addr = instr[24:20];
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+ case (rvi_opcode)
+ SCR1_OPCODE_AUIPC : begin
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_SUM2;
+ idu2exu_cmd_o.imm = {instr[31:12], 12'b0};
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_AUIPC
+
+ SCR1_OPCODE_LUI : begin
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IMM;
+ idu2exu_cmd_o.imm = {instr[31:12], 12'b0};
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_LUI
+
+ SCR1_OPCODE_JAL : begin
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
+ idu2exu_cmd_o.jump_req = 1'b1;
+ idu2exu_cmd_o.imm = {{12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0};
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_JAL
+
+ SCR1_OPCODE_LOAD : begin
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_LSU;
+ idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:20]};
+ case (funct3)
+ 3'b000 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LB;
+ 3'b001 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LH;
+ 3'b010 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LW;
+ 3'b100 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LBU;
+ 3'b101 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LHU;
+ default : rvi_illegal = 1'b1;
+ endcase // funct3
+`ifdef SCR1_RVE_EXT
+ if (instr[11] | instr[19]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_LOAD
+
+ SCR1_OPCODE_STORE : begin
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:25], instr[11:7]};
+ case (funct3)
+ 3'b000 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SB;
+ 3'b001 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SH;
+ 3'b010 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SW;
+ default : rvi_illegal = 1'b1;
+ endcase // funct3
+`ifdef SCR1_RVE_EXT
+ if (instr[19] | instr[24]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_STORE
+
+ SCR1_OPCODE_OP : begin
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ case (funct7)
+ 7'b0000000 : begin
+ case (funct3)
+ 3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
+ 3'b001 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SLL;
+ 3'b010 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LT;
+ 3'b011 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LTU;
+ 3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_XOR;
+ 3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRL;
+ 3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_OR;
+ 3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND;
+ endcase // funct3
+ end // 7'b0000000
+
+ 7'b0100000 : begin
+ case (funct3)
+ 3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB;
+ 3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRA;
+ default : rvi_illegal = 1'b1;
+ endcase // funct3
+ end // 7'b0100000
+`ifdef SCR1_RVM_EXT
+ 7'b0000001 : begin
+ case (funct3)
+ 3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MUL;
+ 3'b001 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MULH;
+ 3'b010 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MULHSU;
+ 3'b011 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MULHU;
+ 3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_DIV;
+ 3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_DIVU;
+ 3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_REM;
+ 3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_REMU;
+ endcase // funct3
+ end // 7'b0000001
+`endif // SCR1_RVM_EXT
+ default : rvi_illegal = 1'b1;
+ endcase // funct7
+`ifdef SCR1_RVE_EXT
+ if (instr[11] | instr[19] | instr[24]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_OP
+
+ SCR1_OPCODE_OP_IMM : begin
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:20]};
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ case (funct3)
+ 3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD; // ADDI
+ 3'b010 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LT; // SLTI
+ 3'b011 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LTU; // SLTIU
+ 3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_XOR; // XORI
+ 3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_OR; // ORI
+ 3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND; // ANDI
+ 3'b001 : begin
+ case (funct7)
+ 7'b0000000 : begin
+ // SLLI
+ idu2exu_cmd_o.imm = `SCR1_XLEN'(shamt); // zero-extend
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SLL;
+ end
+ default : rvi_illegal = 1'b1;
+ endcase // funct7
+ end
+ 3'b101 : begin
+ case (funct7)
+ 7'b0000000 : begin
+ // SRLI
+ idu2exu_cmd_o.imm = `SCR1_XLEN'(shamt); // zero-extend
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRL;
+ end
+ 7'b0100000 : begin
+ // SRAI
+ idu2exu_cmd_o.imm = `SCR1_XLEN'(shamt); // zero-extend
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRA;
+ end
+ default : rvi_illegal = 1'b1;
+ endcase // funct7
+ end
+ endcase // funct3
+`ifdef SCR1_RVE_EXT
+ if (instr[11] | instr[19]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_OP_IMM
+
+ SCR1_OPCODE_MISC_MEM : begin
+ case (funct3)
+ 3'b000 : begin
+ if (~|{instr[31:28], instr[19:15], instr[11:7]}) begin
+ // FENCE = NOP
+ end
+ else rvi_illegal = 1'b1;
+ end
+ 3'b001 : begin
+ if (~|{instr[31:15], instr[11:7]}) begin
+ // FENCE.I
+ idu2exu_cmd_o.fencei_req = 1'b1;
+ end
+ else rvi_illegal = 1'b1;
+ end
+ default : rvi_illegal = 1'b1;
+ endcase // funct3
+ end // SCR1_OPCODE_MISC_MEM
+
+ SCR1_OPCODE_BRANCH : begin
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.imm = {{20{instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0};
+ idu2exu_cmd_o.branch_req = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ case (funct3)
+ 3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_EQ;
+ 3'b001 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_NE;
+ 3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LT;
+ 3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_GE;
+ 3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LTU;
+ 3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_GEU;
+ default : rvi_illegal = 1'b1;
+ endcase // funct3
+`ifdef SCR1_RVE_EXT
+ if (instr[19] | instr[24]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_BRANCH
+
+ SCR1_OPCODE_JALR : begin
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ case (funct3)
+ 3'b000 : begin
+ // JALR
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
+ idu2exu_cmd_o.jump_req = 1'b1;
+ idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:20]};
+ end
+ default : rvi_illegal = 1'b1;
+ endcase
+`ifdef SCR1_RVE_EXT
+ if (instr[11] | instr[19]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end // SCR1_OPCODE_JALR
+
+ SCR1_OPCODE_SYSTEM : begin
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.imm = `SCR1_XLEN'({funct3, instr[31:20]}); // {funct3, CSR address}
+ case (funct3)
+ 3'b000 : begin
+ idu2exu_use_rd_o = 1'b0;
+ idu2exu_use_imm_o = 1'b0;
+ case ({instr[19:15], instr[11:7]})
+ 10'd0 : begin
+ case (funct12)
+ 12'h000 : begin
+ // ECALL
+ idu2exu_cmd_o.exc_req = 1'b1;
+ idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_ECALL_M;
+ end
+ 12'h001 : begin
+ // EBREAK
+ idu2exu_cmd_o.exc_req = 1'b1;
+ idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_BREAKPOINT;
+ end
+ 12'h302 : begin
+ // MRET
+ idu2exu_cmd_o.mret_req = 1'b1;
+ end
+ 12'h105 : begin
+ // WFI
+ idu2exu_cmd_o.wfi_req = 1'b1;
+ end
+ default : rvi_illegal = 1'b1;
+ endcase // funct12
+ end
+ default : rvi_illegal = 1'b1;
+ endcase // {instr[19:15], instr[11:7]}
+ end
+ 3'b001 : begin
+ // CSRRW
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_WRITE;
+ idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
+`ifdef SCR1_RVE_EXT
+ if (instr[11] | instr[19]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b010 : begin
+ // CSRRS
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_SET;
+ idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
+`ifdef SCR1_RVE_EXT
+ if (instr[11] | instr[19]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b011 : begin
+ // CSRRC
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_CLEAR;
+ idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
+`ifdef SCR1_RVE_EXT
+ if (instr[11] | instr[19]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b101 : begin
+ // CSRRWI
+ idu2exu_use_rs1_o = 1'b1; // zimm
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_WRITE;
+ idu2exu_cmd_o.csr_op = SCR1_CSR_OP_IMM;
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b110 : begin
+ // CSRRSI
+ idu2exu_use_rs1_o = 1'b1; // zimm
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_SET;
+ idu2exu_cmd_o.csr_op = SCR1_CSR_OP_IMM;
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b111 : begin
+ // CSRRCI
+ idu2exu_use_rs1_o = 1'b1; // zimm
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_CLEAR;
+ idu2exu_cmd_o.csr_op = SCR1_CSR_OP_IMM;
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ default : rvi_illegal = 1'b1;
+ endcase // funct3
+ end // SCR1_OPCODE_SYSTEM
+
+ default : begin
+ rvi_illegal = 1'b1;
+ end
+ endcase // rvi_opcode
+ end // SCR1_INSTR_RVI
+
+`ifdef SCR1_RVC_EXT
+
+ // Quadrant 0
+ SCR1_INSTR_RVC0 : begin
+ idu2exu_cmd_o.instr_rvc = 1'b1;
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ case (funct3)
+ 3'b000 : begin
+ if (~|instr[12:5]) rvc_illegal = 1'b1;
+ // C.ADDI4SPN
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
+ idu2exu_cmd_o.rd_addr = {2'b01, instr[4:2]};
+ idu2exu_cmd_o.imm = {22'd0, instr[10:7], instr[12:11], instr[5], instr[6], 2'b00};
+ end
+ 3'b010 : begin
+ // C.LW
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LW;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_LSU;
+ idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
+ idu2exu_cmd_o.rd_addr = {2'b01, instr[4:2]};
+ idu2exu_cmd_o.imm = {25'd0, instr[5], instr[12:10], instr[6], 2'b00};
+ end
+ 3'b110 : begin
+ // C.SW
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SW;
+ idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
+ idu2exu_cmd_o.rs2_addr = {2'b01, instr[4:2]};
+ idu2exu_cmd_o.imm = {25'd0, instr[5], instr[12:10], instr[6], 2'b00};
+ end
+ default : begin
+ rvc_illegal = 1'b1;
+ end
+ endcase // funct3
+ end // Quadrant 0
+
+ // Quadrant 1
+ SCR1_INSTR_RVC1 : begin
+ idu2exu_cmd_o.instr_rvc = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ case (funct3)
+ 3'b000 : begin
+ // C.ADDI / C.NOP
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ idu2exu_cmd_o.rs1_addr = instr[11:7];
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+ idu2exu_cmd_o.imm = {{27{instr[12]}}, instr[6:2]};
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b001 : begin
+ // C.JAL
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
+ idu2exu_cmd_o.jump_req = 1'b1;
+ idu2exu_cmd_o.rd_addr = SCR1_MPRF_RA_ADDR;
+ idu2exu_cmd_o.imm = {{21{instr[12]}}, instr[8], instr[10:9], instr[6], instr[7], instr[2], instr[11], instr[5:3], 1'b0};
+ end
+ 3'b010 : begin
+ // C.LI
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IMM;
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+ idu2exu_cmd_o.imm = {{27{instr[12]}}, instr[6:2]};
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b011 : begin
+ if (~|{instr[12], instr[6:2]}) rvc_illegal = 1'b1;
+ if (instr[11:7] == SCR1_MPRF_SP_ADDR) begin
+ // C.ADDI16SP
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
+ idu2exu_cmd_o.rd_addr = SCR1_MPRF_SP_ADDR;
+ idu2exu_cmd_o.imm = {{23{instr[12]}}, instr[4:3], instr[5], instr[2], instr[6], 4'd0};
+ end else begin
+ // C.LUI
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IMM;
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+ idu2exu_cmd_o.imm = {{15{instr[12]}}, instr[6:2], 12'd0};
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ end
+ 3'b100 : begin
+ idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
+ idu2exu_cmd_o.rd_addr = {2'b01, instr[9:7]};
+ idu2exu_cmd_o.rs2_addr = {2'b01, instr[4:2]};
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ case (instr[11:10])
+ 2'b00 : begin
+ if (instr[12]) rvc_illegal = 1'b1;
+ // C.SRLI
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.imm = {27'd0, instr[6:2]};
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRL;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ end
+ 2'b01 : begin
+ if (instr[12]) rvc_illegal = 1'b1;
+ // C.SRAI
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.imm = {27'd0, instr[6:2]};
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRA;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ end
+ 2'b10 : begin
+ // C.ANDI
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ idu2exu_cmd_o.imm = {{27{instr[12]}}, instr[6:2]};
+ end
+ 2'b11 : begin
+ idu2exu_use_rs2_o = 1'b1;
+ case ({instr[12], instr[6:5]})
+ 3'b000 : begin
+ // C.SUB
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ end
+ 3'b001 : begin
+ // C.XOR
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_XOR;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ end
+ 3'b010 : begin
+ // C.OR
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_OR;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ end
+ 3'b011 : begin
+ // C.AND
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ end
+ default : begin
+ rvc_illegal = 1'b1;
+ end
+ endcase // {instr[12], instr[6:5]}
+ end
+ endcase // instr[11:10]
+ end // funct3 == 3'b100
+ 3'b101 : begin
+ // C.J
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.jump_req = 1'b1;
+ idu2exu_cmd_o.imm = {{21{instr[12]}}, instr[8], instr[10:9], instr[6], instr[7], instr[2], instr[11], instr[5:3], 1'b0};
+ end
+ 3'b110 : begin
+ // C.BEQZ
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_EQ;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.branch_req = 1'b1;
+ idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
+ idu2exu_cmd_o.rs2_addr = SCR1_MPRF_ZERO_ADDR;
+ idu2exu_cmd_o.imm = {{24{instr[12]}}, instr[6:5], instr[2], instr[11:10], instr[4:3], 1'b0};
+ end
+ 3'b111 : begin
+ // C.BNEZ
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_NE;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
+ idu2exu_cmd_o.branch_req = 1'b1;
+ idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
+ idu2exu_cmd_o.rs2_addr = SCR1_MPRF_ZERO_ADDR;
+ idu2exu_cmd_o.imm = {{24{instr[12]}}, instr[6:5], instr[2], instr[11:10], instr[4:3], 1'b0};
+ end
+ endcase // funct3
+ end // Quadrant 1
+
+ // Quadrant 2
+ SCR1_INSTR_RVC2 : begin
+ idu2exu_cmd_o.instr_rvc = 1'b1;
+ idu2exu_use_rs1_o = 1'b1;
+ case (funct3)
+ 3'b000 : begin
+ if (instr[12]) rvc_illegal = 1'b1;
+ // C.SLLI
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.rs1_addr = instr[11:7];
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+ idu2exu_cmd_o.imm = {27'd0, instr[6:2]};
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SLL;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b010 : begin
+ if (~|instr[11:7]) rvc_illegal = 1'b1;
+ // C.LWSP
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LW;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_LSU;
+ idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+ idu2exu_cmd_o.imm = {24'd0, instr[3:2], instr[12], instr[6:4], 2'b00};
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ 3'b100 : begin
+ if (~instr[12]) begin
+ if (|instr[6:2]) begin
+ // C.MV
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ idu2exu_cmd_o.rs1_addr = SCR1_MPRF_ZERO_ADDR;
+ idu2exu_cmd_o.rs2_addr = instr[6:2];
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+`ifdef SCR1_RVE_EXT
+ if (instr[11]|instr[6]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end else begin
+ if (~|instr[11:7]) rvc_illegal = 1'b1;
+ // C.JR
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.jump_req = 1'b1;
+ idu2exu_cmd_o.rs1_addr = instr[11:7];
+ idu2exu_cmd_o.imm = 0;
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ end else begin // instr[12] == 1
+ if (~|instr[11:2]) begin
+ // C.EBREAK
+ idu2exu_cmd_o.exc_req = 1'b1;
+ idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_BREAKPOINT;
+ end else if (~|instr[6:2]) begin
+ // C.JALR
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
+ idu2exu_cmd_o.jump_req = 1'b1;
+ idu2exu_cmd_o.rs1_addr = instr[11:7];
+ idu2exu_cmd_o.rd_addr = SCR1_MPRF_RA_ADDR;
+ idu2exu_cmd_o.imm = 0;
+`ifdef SCR1_RVE_EXT
+ if (instr[11]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end else begin
+ // C.ADD
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_rd_o = 1'b1;
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
+ idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
+ idu2exu_cmd_o.rs1_addr = instr[11:7];
+ idu2exu_cmd_o.rs2_addr = instr[6:2];
+ idu2exu_cmd_o.rd_addr = instr[11:7];
+`ifdef SCR1_RVE_EXT
+ if (instr[11]|instr[6]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ end // instr[12] == 1
+ end
+ 3'b110 : begin
+ // C.SWSP
+ idu2exu_use_rs1_o = 1'b1;
+ idu2exu_use_rs2_o = 1'b1;
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
+ idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SW;
+ idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
+ idu2exu_cmd_o.rs2_addr = instr[6:2];
+ idu2exu_cmd_o.imm = {24'd0, instr[8:7], instr[12:9], 2'b00};
+`ifdef SCR1_RVE_EXT
+ if (instr[6]) rve_illegal = 1'b1;
+`endif // SCR1_RVE_EXT
+ end
+ default : begin
+ rvc_illegal = 1'b1;
+ end
+ endcase // funct3
+ end // Quadrant 2
+
+ default : begin
+ end
+`else // SCR1_RVC_EXT
+ default : begin
+ idu2exu_cmd_o.instr_rvc = 1'b1;
+ rvi_illegal = 1'b1;
+ end
+`endif // SCR1_RVC_EXT
+ endcase // instr_type
+ end // no imem fault
+
+ // At this point the instruction is fully decoded
+ // given that no imem fault has happened
+
+ // Check illegal instruction
+ if (
+ rvi_illegal
+`ifdef SCR1_RVC_EXT
+ | rvc_illegal
+`endif
+`ifdef SCR1_RVE_EXT
+ | rve_illegal
+`endif
+ ) begin
+ idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_NONE;
+ idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_NONE;
+ idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_NONE;
+ idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_NONE;
+ idu2exu_cmd_o.jump_req = 1'b0;
+ idu2exu_cmd_o.branch_req = 1'b0;
+ idu2exu_cmd_o.mret_req = 1'b0;
+ idu2exu_cmd_o.fencei_req = 1'b0;
+ idu2exu_cmd_o.wfi_req = 1'b0;
+
+ idu2exu_use_rs1_o = 1'b0;
+ idu2exu_use_rs2_o = 1'b0;
+ idu2exu_use_rd_o = 1'b0;
+
+`ifndef SCR1_MTVAL_ILLEGAL_INSTR_EN
+ idu2exu_use_imm_o = 1'b0;
+`else // SCR1_MTVAL_ILLEGAL_INSTR_EN
+ idu2exu_use_imm_o = 1'b1;
+ idu2exu_cmd_o.imm = instr;
+`endif // SCR1_MTVAL_ILLEGAL_INSTR_EN
+
+ idu2exu_cmd_o.exc_req = 1'b1;
+ idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_ILLEGAL_INSTR;
+ end
+
+end // RV32I(MC) decode
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+// X checks
+
+SCR1_SVA_IDU_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({ifu2idu_vd_i, exu2idu_rdy_i})
+ ) else $error("IDU Error: unknown values");
+
+SCR1_SVA_IDU_XCHECK2 : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ ifu2idu_vd_i |-> !$isunknown({ifu2idu_imem_err_i, (ifu2idu_imem_err_i ? 0 : ifu2idu_instr_i)})
+ ) else $error("IDU Error: unknown values");
+
+// Behavior checks
+
+SCR1_SVA_IDU_IALU_CMD_RANGE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (ifu2idu_vd_i & ~ifu2idu_imem_err_i) |->
+ ((idu2exu_cmd_o.ialu_cmd >= SCR1_IALU_CMD_NONE) &
+ (idu2exu_cmd_o.ialu_cmd <=
+`ifdef SCR1_RVM_EXT
+ SCR1_IALU_CMD_REMU
+`else
+ SCR1_IALU_CMD_SRA
+`endif // SCR1_RVM_EXT
+ ))
+ ) else $error("IDU Error: IALU_CMD out of range");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_idu
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ifu.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ifu.sv
new file mode 100644
index 0000000..740c4f6
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_ifu.sv
@@ -0,0 +1,826 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_ifu.sv>
+/// @brief Instruction Fetch Unit (IFU)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Controls instruction fetching process:
+ // - Fetches instructions either from IMEM or from Program Buffer, supporting
+ // pending IMEM instructions handling
+ // - Handles new PC misalignment and constructs the correct instruction (supports
+ // RVI and RVC instructions)
+ // - Either stores instructions in the instruction queue or bypasses to the
+ // IDU if the corresponding option is used
+ // - Flushes instruction queue if requested
+ //
+ // Structure:
+ // - Instruction queue
+ // - IFU FSM
+ // - IFU <-> IMEM i/f
+ // - IFU <-> IDU i/f
+ // - IFU <-> HDU i/f
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_memif.svh"
+`include "scr1_arch_description.svh"
+`ifdef SCR1_DBG_EN
+`include "scr1_hdu.svh"
+`endif // SCR1_DBG_EN
+
+module scr1_pipe_ifu
+(
+ // Control signals
+ input logic rst_n, // IFU reset
+ input logic clk, // IFU clock
+ input logic pipe2ifu_stop_fetch_i, // Stop instruction fetch
+
+ // IFU <-> IMEM interface
+ input logic imem2ifu_req_ack_i, // Instruction memory request acknowledgement
+ output logic ifu2imem_req_o, // Instruction memory request
+ output type_scr1_mem_cmd_e ifu2imem_cmd_o, // Instruction memory command (READ/WRITE)
+ output logic [`SCR1_IMEM_AWIDTH-1:0] ifu2imem_addr_o, // Instruction memory address
+ input logic [`SCR1_IMEM_DWIDTH-1:0] imem2ifu_rdata_i, // Instruction memory read data
+ input type_scr1_mem_resp_e imem2ifu_resp_i, // Instruction memory response
+
+ // IFU <-> EXU New PC interface
+ input logic exu2ifu_pc_new_req_i, // New PC request (jumps, branches, traps etc)
+ input logic [`SCR1_XLEN-1:0] exu2ifu_pc_new_i, // New PC
+
+`ifdef SCR1_DBG_EN
+ // IFU <-> HDU Program Buffer interface
+ input logic hdu2ifu_pbuf_fetch_i, // Fetch instructions provided by Program Buffer
+ output logic ifu2hdu_pbuf_rdy_o, // Program Buffer Instruction i/f ready
+ input logic hdu2ifu_pbuf_vd_i, // Program Buffer Instruction valid
+ input logic hdu2ifu_pbuf_err_i, // Program Buffer Instruction i/f error
+ input logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr_i, // Program Buffer Instruction itself
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_CLKCTRL_EN
+ output logic ifu2pipe_imem_txns_pnd_o, // There are pending imem transactions
+`endif // SCR1_CLKCTRL_EN
+
+ // IFU <-> IDU interface
+ input logic idu2ifu_rdy_i, // IDU ready for new data
+ output logic [`SCR1_IMEM_DWIDTH-1:0] ifu2idu_instr_o, // IFU instruction
+ output logic ifu2idu_imem_err_o, // Instruction access fault exception
+ output logic ifu2idu_err_rvi_hi_o, // 1 - imem fault when trying to fetch second half of an unaligned RVI instruction
+ output logic ifu2idu_vd_o // IFU request
+);
+
+//------------------------------------------------------------------------------
+// Local parameters declaration
+//------------------------------------------------------------------------------
+
+localparam SCR1_IFU_Q_SIZE_WORD = 2;
+localparam SCR1_IFU_Q_SIZE_HALF = SCR1_IFU_Q_SIZE_WORD * 2;
+localparam SCR1_TXN_CNT_W = 3;
+
+localparam SCR1_IFU_QUEUE_ADR_W = $clog2(SCR1_IFU_Q_SIZE_HALF);
+localparam SCR1_IFU_QUEUE_PTR_W = SCR1_IFU_QUEUE_ADR_W + 1;
+
+localparam SCR1_IFU_Q_FREE_H_W = $clog2(SCR1_IFU_Q_SIZE_HALF + 1);
+localparam SCR1_IFU_Q_FREE_W_W = $clog2(SCR1_IFU_Q_SIZE_WORD + 1);
+
+//------------------------------------------------------------------------------
+// Local types declaration
+//------------------------------------------------------------------------------
+
+typedef enum logic {
+ SCR1_IFU_FSM_IDLE,
+ SCR1_IFU_FSM_FETCH
+} type_scr1_ifu_fsm_e;
+
+typedef enum logic[1:0] {
+ SCR1_IFU_QUEUE_WR_NONE, // No write to queue
+ SCR1_IFU_QUEUE_WR_FULL, // Write 32 rdata bits to queue
+ SCR1_IFU_QUEUE_WR_HI // Write 16 upper rdata bits to queue
+} type_scr1_ifu_queue_wr_e;
+
+typedef enum logic[1:0] {
+ SCR1_IFU_QUEUE_RD_NONE, // No queue read
+ SCR1_IFU_QUEUE_RD_HWORD, // Read halfword
+ SCR1_IFU_QUEUE_RD_WORD // Read word
+} type_scr1_ifu_queue_rd_e;
+
+`ifdef SCR1_NO_DEC_STAGE
+typedef enum logic[1:0] {
+ SCR1_BYPASS_NONE, // No bypass
+ SCR1_BYPASS_RVC, // Bypass RVC
+ SCR1_BYPASS_RVI_RDATA_QUEUE, // Bypass RVI, rdata+queue
+ SCR1_BYPASS_RVI_RDATA // Bypass RVI, rdata only
+} type_scr1_bypass_e;
+`endif // SCR1_NO_DEC_STAGE
+
+typedef enum logic [2:0] {
+ // SCR1_IFU_INSTR_<UPPER_16_BITS>_<LOWER_16_BITS>
+ SCR1_IFU_INSTR_NONE, // No valid instruction
+ SCR1_IFU_INSTR_RVI_HI_RVI_LO, // Full RV32I instruction
+ SCR1_IFU_INSTR_RVC_RVC,
+ SCR1_IFU_INSTR_RVI_LO_RVC,
+ SCR1_IFU_INSTR_RVC_RVI_HI,
+ SCR1_IFU_INSTR_RVI_LO_RVI_HI,
+ SCR1_IFU_INSTR_RVC_NV, // Instruction after unaligned new_pc
+ SCR1_IFU_INSTR_RVI_LO_NV // Instruction after unaligned new_pc
+} type_scr1_ifu_instr_e;
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// Instruction queue signals
+//------------------------------------------------------------------------------
+
+// New PC unaligned flag register
+logic new_pc_unaligned_ff;
+logic new_pc_unaligned_next;
+logic new_pc_unaligned_upd;
+
+// IMEM instruction type decoder
+logic instr_hi_is_rvi;
+logic instr_lo_is_rvi;
+type_scr1_ifu_instr_e instr_type;
+
+// Register to store if the previous IMEM instruction had low part of RVI instruction
+// in its high part
+logic instr_hi_rvi_lo_ff;
+logic instr_hi_rvi_lo_next;
+
+// Queue read/write size decoders
+type_scr1_ifu_queue_rd_e q_rd_size;
+logic q_rd_vd;
+logic q_rd_none;
+logic q_rd_hword;
+type_scr1_ifu_queue_wr_e q_wr_size;
+logic q_wr_none;
+logic q_wr_full;
+
+// Write/read pointer registers
+logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_rptr;
+logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_rptr_next;
+logic q_rptr_upd;
+logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_wptr;
+logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_wptr_next;
+logic q_wptr_upd;
+
+// Instruction queue control signals
+logic q_wr_en;
+logic q_flush_req;
+
+// Queue data registers
+logic [`SCR1_IMEM_DWIDTH/2-1:0] q_data [SCR1_IFU_Q_SIZE_HALF];
+logic [`SCR1_IMEM_DWIDTH/2-1:0] q_data_head;
+logic [`SCR1_IMEM_DWIDTH/2-1:0] q_data_next;
+
+// Queue error flags registers
+logic q_err [SCR1_IFU_Q_SIZE_HALF];
+logic q_err_head;
+logic q_err_next;
+
+// Instruction queue status signals
+logic q_is_empty;
+logic q_has_free_slots;
+logic q_has_1_ocpd_hw;
+logic q_head_is_rvc;
+logic q_head_is_rvi;
+logic [SCR1_IFU_Q_FREE_H_W-1:0] q_ocpd_h;
+logic [SCR1_IFU_Q_FREE_H_W-1:0] q_free_h_next;
+logic [SCR1_IFU_Q_FREE_W_W-1:0] q_free_w_next;
+
+// IFU FSM signals
+//------------------------------------------------------------------------------
+
+// IFU FSM control signals
+logic ifu_fetch_req;
+logic ifu_stop_req;
+
+type_scr1_ifu_fsm_e ifu_fsm_curr;
+type_scr1_ifu_fsm_e ifu_fsm_next;
+logic ifu_fsm_fetch;
+
+// IMEM signals
+//------------------------------------------------------------------------------
+
+// IMEM response signals
+logic imem_resp_ok;
+logic imem_resp_er;
+logic imem_resp_er_discard_pnd;
+logic imem_resp_discard_req;
+logic imem_resp_received;
+logic imem_resp_vd;
+logic imem_handshake_done;
+
+logic [15:0] imem_rdata_lo;
+logic [31:16] imem_rdata_hi;
+
+// IMEM address signals
+logic imem_addr_upd;
+logic [`SCR1_XLEN-1:2] imem_addr_ff;
+logic [`SCR1_XLEN-1:2] imem_addr_next;
+
+// IMEM pending transactions counter
+logic imem_pnd_txns_cnt_upd;
+logic [SCR1_TXN_CNT_W-1:0] imem_pnd_txns_cnt;
+logic [SCR1_TXN_CNT_W-1:0] imem_pnd_txns_cnt_next;
+logic [SCR1_TXN_CNT_W-1:0] imem_vd_pnd_txns_cnt;
+logic imem_pnd_txns_q_full;
+
+// IMEM responses discard counter
+logic imem_resp_discard_cnt_upd;
+logic [SCR1_TXN_CNT_W-1:0] imem_resp_discard_cnt;
+logic [SCR1_TXN_CNT_W-1:0] imem_resp_discard_cnt_next;
+
+`ifdef SCR1_NEW_PC_REG
+logic new_pc_req_ff;
+`endif // SCR1_NEW_PC_REG
+
+// Instruction bypass signals
+`ifdef SCR1_NO_DEC_STAGE
+type_scr1_bypass_e instr_bypass_type;
+logic instr_bypass_vd;
+`endif // SCR1_NO_DEC_STAGE
+
+//------------------------------------------------------------------------------
+// Instruction queue
+//------------------------------------------------------------------------------
+//
+ // Instruction queue consists of the following functional units:
+ // - New PC unaligned flag register
+ // - Instruction type decoder, including register to store if the previous
+ // IMEM instruction had low part of RVI instruction in its high part
+ // - Read/write size decoders
+ // - Read/write pointer registers
+ // - Data and error flag registers
+ // - Status logic
+//
+
+// New PC unaligned flag register
+//------------------------------------------------------------------------------
+
+assign new_pc_unaligned_upd = exu2ifu_pc_new_req_i | imem_resp_vd;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ new_pc_unaligned_ff <= 1'b0;
+ end else if (new_pc_unaligned_upd) begin
+ new_pc_unaligned_ff <= new_pc_unaligned_next;
+ end
+end
+
+assign new_pc_unaligned_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[1]
+ : ~imem_resp_vd ? new_pc_unaligned_ff
+ : 1'b0;
+
+// Instruction type decoder
+//------------------------------------------------------------------------------
+
+assign instr_hi_is_rvi = &imem2ifu_rdata_i[17:16];
+assign instr_lo_is_rvi = &imem2ifu_rdata_i[1:0];
+
+always_comb begin
+ instr_type = SCR1_IFU_INSTR_NONE;
+
+ if (imem_resp_ok & ~imem_resp_discard_req) begin
+ if (new_pc_unaligned_ff) begin
+ instr_type = instr_hi_is_rvi ? SCR1_IFU_INSTR_RVI_LO_NV
+ : SCR1_IFU_INSTR_RVC_NV;
+ end else begin // ~new_pc_unaligned_ff
+ if (instr_hi_rvi_lo_ff) begin
+ instr_type = instr_hi_is_rvi ? SCR1_IFU_INSTR_RVI_LO_RVI_HI
+ : SCR1_IFU_INSTR_RVC_RVI_HI;
+ end else begin // SCR1_OTHER
+ casez ({instr_hi_is_rvi, instr_lo_is_rvi})
+ 2'b?1 : instr_type = SCR1_IFU_INSTR_RVI_HI_RVI_LO;
+ 2'b00 : instr_type = SCR1_IFU_INSTR_RVC_RVC;
+ 2'b10 : instr_type = SCR1_IFU_INSTR_RVI_LO_RVC;
+ endcase
+ end
+ end
+ end
+end
+
+// Register to store if the previous IMEM instruction had low part of RVI
+// instruction in its high part
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ instr_hi_rvi_lo_ff <= 1'b0;
+ end else begin
+ if (exu2ifu_pc_new_req_i) begin
+ instr_hi_rvi_lo_ff <= 1'b0;
+ end else if (imem_resp_vd) begin
+ instr_hi_rvi_lo_ff <= instr_hi_rvi_lo_next;
+ end
+ end
+end
+
+assign instr_hi_rvi_lo_next = (instr_type == SCR1_IFU_INSTR_RVI_LO_NV)
+ | (instr_type == SCR1_IFU_INSTR_RVI_LO_RVI_HI)
+ | (instr_type == SCR1_IFU_INSTR_RVI_LO_RVC);
+
+// Queue write/read size decoders
+//------------------------------------------------------------------------------
+
+// Queue read size decoder
+assign q_rd_vd = ~q_is_empty & ifu2idu_vd_o & idu2ifu_rdy_i;
+assign q_rd_hword = q_head_is_rvc | q_err_head
+`ifdef SCR1_NO_DEC_STAGE
+ | (q_head_is_rvi & instr_bypass_vd)
+`endif // SCR1_NO_DEC_STAGE
+ ;
+assign q_rd_size = ~q_rd_vd ? SCR1_IFU_QUEUE_RD_NONE
+ : q_rd_hword ? SCR1_IFU_QUEUE_RD_HWORD
+ : SCR1_IFU_QUEUE_RD_WORD;
+assign q_rd_none = (q_rd_size == SCR1_IFU_QUEUE_RD_NONE);
+
+// Queue write size decoder
+always_comb begin
+ q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
+ if (~imem_resp_discard_req) begin
+ if (imem_resp_ok) begin
+`ifdef SCR1_NO_DEC_STAGE
+ case (instr_type)
+ SCR1_IFU_INSTR_NONE : q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
+ SCR1_IFU_INSTR_RVI_LO_NV : q_wr_size = SCR1_IFU_QUEUE_WR_HI;
+ SCR1_IFU_INSTR_RVC_NV : q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
+ ? SCR1_IFU_QUEUE_WR_NONE
+ : SCR1_IFU_QUEUE_WR_HI;
+ SCR1_IFU_INSTR_RVI_HI_RVI_LO: q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
+ ? SCR1_IFU_QUEUE_WR_NONE
+ : SCR1_IFU_QUEUE_WR_FULL;
+ SCR1_IFU_INSTR_RVC_RVC,
+ SCR1_IFU_INSTR_RVI_LO_RVC,
+ SCR1_IFU_INSTR_RVC_RVI_HI,
+ SCR1_IFU_INSTR_RVI_LO_RVI_HI: q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
+ ? SCR1_IFU_QUEUE_WR_HI
+ : SCR1_IFU_QUEUE_WR_FULL;
+ endcase // instr_type
+`else // SCR1_NO_DEC_STAGE
+ case (instr_type)
+ SCR1_IFU_INSTR_NONE : q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
+ SCR1_IFU_INSTR_RVC_NV,
+ SCR1_IFU_INSTR_RVI_LO_NV : q_wr_size = SCR1_IFU_QUEUE_WR_HI;
+ default : q_wr_size = SCR1_IFU_QUEUE_WR_FULL;
+ endcase // instr_type
+`endif // SCR1_NO_DEC_STAGE
+ end else if (imem_resp_er) begin
+ q_wr_size = SCR1_IFU_QUEUE_WR_FULL;
+ end // imem_resp_er
+ end // ~imem_resp_discard_req
+end
+
+assign q_wr_none = (q_wr_size == SCR1_IFU_QUEUE_WR_NONE);
+assign q_wr_full = (q_wr_size == SCR1_IFU_QUEUE_WR_FULL);
+
+// Write/read pointer registers
+//------------------------------------------------------------------------------
+
+assign q_flush_req = exu2ifu_pc_new_req_i | pipe2ifu_stop_fetch_i;
+
+// Queue write pointer register
+assign q_wptr_upd = q_flush_req | ~q_wr_none;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ q_wptr <= '0;
+ end else if (q_wptr_upd) begin
+ q_wptr <= q_wptr_next;
+ end
+end
+
+assign q_wptr_next = q_flush_req ? '0
+ : ~q_wr_none ? q_wptr + (q_wr_full ? 2'd2 : 1'b1)
+ : q_wptr;
+
+// Queue read pointer register
+assign q_rptr_upd = q_flush_req | ~q_rd_none;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ q_rptr <= '0;
+ end else if (q_rptr_upd) begin
+ q_rptr <= q_rptr_next;
+ end
+end
+
+assign q_rptr_next = q_flush_req ? '0
+ : ~q_rd_none ? q_rptr + (q_rd_hword ? 1'b1 : 2'd2)
+ : q_rptr;
+
+// Queue data and error flag registers
+//------------------------------------------------------------------------------
+
+assign imem_rdata_hi = imem2ifu_rdata_i[31:16];
+assign imem_rdata_lo = imem2ifu_rdata_i[15:0];
+
+assign q_wr_en = imem_resp_vd & ~q_flush_req;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ q_data <= '{SCR1_IFU_Q_SIZE_HALF{'0}};
+ q_err <= '{SCR1_IFU_Q_SIZE_HALF{1'b0}};
+ end else if (q_wr_en) begin
+ case (q_wr_size)
+ SCR1_IFU_QUEUE_WR_HI : begin
+ q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_rdata_hi;
+ q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_resp_er;
+ end
+ SCR1_IFU_QUEUE_WR_FULL : begin
+ q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_rdata_lo;
+ q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_resp_er;
+ q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr + 1'b1)] <= imem_rdata_hi;
+ q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr + 1'b1)] <= imem_resp_er;
+ end
+ endcase
+ end
+end
+
+assign q_data_head = q_data [SCR1_IFU_QUEUE_ADR_W'(q_rptr)];
+assign q_data_next = q_data [SCR1_IFU_QUEUE_ADR_W'(q_rptr + 1'b1)];
+assign q_err_head = q_err [SCR1_IFU_QUEUE_ADR_W'(q_rptr)];
+assign q_err_next = q_err [SCR1_IFU_QUEUE_ADR_W'(q_rptr + 1'b1)];
+
+// Queue status logic
+//------------------------------------------------------------------------------
+
+assign q_ocpd_h = SCR1_IFU_Q_FREE_H_W'(q_wptr - q_rptr);
+assign q_free_h_next = SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF - (q_wptr - q_rptr_next));
+assign q_free_w_next = SCR1_IFU_Q_FREE_W_W'(q_free_h_next >> 1'b1);
+
+assign q_is_empty = (q_rptr == q_wptr);
+assign q_has_free_slots = (SCR1_TXN_CNT_W'(q_free_w_next) > imem_vd_pnd_txns_cnt);
+assign q_has_1_ocpd_hw = (q_ocpd_h == SCR1_IFU_Q_FREE_H_W'(1));
+
+assign q_head_is_rvi = &(q_data_head[1:0]);
+assign q_head_is_rvc = ~q_head_is_rvi;
+
+//------------------------------------------------------------------------------
+// IFU FSM
+//------------------------------------------------------------------------------
+
+// IFU FSM control signals
+assign ifu_fetch_req = exu2ifu_pc_new_req_i & ~pipe2ifu_stop_fetch_i;
+assign ifu_stop_req = pipe2ifu_stop_fetch_i
+ | (imem_resp_er_discard_pnd & ~exu2ifu_pc_new_req_i);
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ ifu_fsm_curr <= SCR1_IFU_FSM_IDLE;
+ end else begin
+ ifu_fsm_curr <= ifu_fsm_next;
+ end
+end
+
+always_comb begin
+ case (ifu_fsm_curr)
+ SCR1_IFU_FSM_IDLE : begin
+ ifu_fsm_next = ifu_fetch_req ? SCR1_IFU_FSM_FETCH
+ : SCR1_IFU_FSM_IDLE;
+ end
+ SCR1_IFU_FSM_FETCH : begin
+ ifu_fsm_next = ifu_stop_req ? SCR1_IFU_FSM_IDLE
+ : SCR1_IFU_FSM_FETCH;
+ end
+ endcase
+end
+
+assign ifu_fsm_fetch = (ifu_fsm_curr == SCR1_IFU_FSM_FETCH);
+
+//------------------------------------------------------------------------------
+// IFU <-> IMEM interface
+//------------------------------------------------------------------------------
+//
+ // IFU <-> IMEM interface consists of the following functional units:
+ // - IMEM response logic
+ // - IMEM address register
+ // - Pending IMEM transactions counter
+ // - IMEM discard responses counter
+ // - IFU <-> IMEM interface output signals
+//
+
+// IMEM response logic
+//------------------------------------------------------------------------------
+
+assign imem_resp_er = (imem2ifu_resp_i == SCR1_MEM_RESP_RDY_ER);
+assign imem_resp_ok = (imem2ifu_resp_i == SCR1_MEM_RESP_RDY_OK);
+assign imem_resp_received = imem_resp_ok | imem_resp_er;
+assign imem_resp_vd = imem_resp_received & ~imem_resp_discard_req;
+assign imem_resp_er_discard_pnd = imem_resp_er & ~imem_resp_discard_req;
+
+assign imem_handshake_done = ifu2imem_req_o & imem2ifu_req_ack_i;
+
+// IMEM address register
+//------------------------------------------------------------------------------
+
+assign imem_addr_upd = imem_handshake_done | exu2ifu_pc_new_req_i;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ imem_addr_ff <= '0;
+ end else if (imem_addr_upd) begin
+ imem_addr_ff <= imem_addr_next;
+ end
+end
+
+`ifndef SCR1_NEW_PC_REG
+assign imem_addr_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[`SCR1_XLEN-1:2] + imem_handshake_done
+ : &imem_addr_ff[5:2] ? imem_addr_ff + imem_handshake_done
+ : {imem_addr_ff[`SCR1_XLEN-1:6], imem_addr_ff[5:2] + imem_handshake_done};
+`else // SCR1_NEW_PC_REG
+assign imem_addr_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[`SCR1_XLEN-1:2]
+ : &imem_addr_ff[5:2] ? imem_addr_ff + imem_handshake_done
+ : {imem_addr_ff[`SCR1_XLEN-1:6], imem_addr_ff[5:2] + imem_handshake_done};
+`endif // SCR1_NEW_PC_REG
+
+// Pending IMEM transactions counter
+//------------------------------------------------------------------------------
+// Pending IMEM transactions occur if IFU request has been acknowledged, but
+// response comes in the next cycle or later
+
+assign imem_pnd_txns_cnt_upd = imem_handshake_done ^ imem_resp_received;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ imem_pnd_txns_cnt <= '0;
+ end else if (imem_pnd_txns_cnt_upd) begin
+ imem_pnd_txns_cnt <= imem_pnd_txns_cnt_next;
+ end
+end
+
+assign imem_pnd_txns_cnt_next = imem_pnd_txns_cnt + (imem_handshake_done - imem_resp_received);
+assign imem_pnd_txns_q_full = &imem_pnd_txns_cnt;
+
+// IMEM discard responses counter
+//------------------------------------------------------------------------------
+// IMEM instructions should be discarded in the following 2 cases:
+// 1. New PC is requested by jump, branch, mret or other instruction
+// 2. IMEM response was erroneous and not discarded
+//
+// In both cases the number of instructions to be discarded equals to the number
+// of pending instructions.
+// In the 1st case we don't need all the instructions that haven't been fetched
+// yet, since the PC has changed.
+// In the 2nd case, since the IMEM responce was erroneous there is no guarantee
+// that subsequent IMEM instructions would be valid.
+
+assign imem_resp_discard_cnt_upd = exu2ifu_pc_new_req_i | imem_resp_er
+ | (imem_resp_ok & imem_resp_discard_req);
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ imem_resp_discard_cnt <= '0;
+ end else if (imem_resp_discard_cnt_upd) begin
+ imem_resp_discard_cnt <= imem_resp_discard_cnt_next;
+ end
+end
+
+`ifndef SCR1_NEW_PC_REG
+assign imem_resp_discard_cnt_next = exu2ifu_pc_new_req_i ? imem_pnd_txns_cnt_next - imem_handshake_done
+ : imem_resp_er_discard_pnd ? imem_pnd_txns_cnt_next
+ : imem_resp_discard_cnt - 1'b1;
+`else // SCR1_NEW_PC_REG
+assign imem_resp_discard_cnt_next = exu2ifu_pc_new_req_i | imem_resp_er_discard_pnd
+ ? imem_pnd_txns_cnt_next
+ : imem_resp_discard_cnt - 1'b1;
+`endif // SCR1_NEW_PC_REG
+
+assign imem_vd_pnd_txns_cnt = imem_pnd_txns_cnt - imem_resp_discard_cnt;
+assign imem_resp_discard_req = |imem_resp_discard_cnt;
+
+// IFU <-> IMEM interface output signals
+//------------------------------------------------------------------------------
+
+`ifndef SCR1_NEW_PC_REG
+assign ifu2imem_req_o = (exu2ifu_pc_new_req_i & ~imem_pnd_txns_q_full & ~pipe2ifu_stop_fetch_i)
+ | (ifu_fsm_fetch & ~imem_pnd_txns_q_full & q_has_free_slots);
+assign ifu2imem_addr_o = exu2ifu_pc_new_req_i
+ ? {exu2ifu_pc_new_i[`SCR1_XLEN-1:2], 2'b00}
+ : {imem_addr_ff, 2'b00};
+`else // SCR1_NEW_PC_REG
+assign ifu2imem_req_o = ifu_fsm_fetch & ~imem_pnd_txns_q_full & q_has_free_slots;
+assign ifu2imem_addr_o = {imem_addr_ff, 2'b00};
+`endif // SCR1_NEW_PC_REG
+
+assign ifu2imem_cmd_o = SCR1_MEM_CMD_RD;
+
+`ifdef SCR1_CLKCTRL_EN
+assign ifu2pipe_imem_txns_pnd_o = |imem_pnd_txns_cnt;
+`endif // SCR1_CLKCTRL_EN
+
+//------------------------------------------------------------------------------
+// IFU <-> IDU interface
+//------------------------------------------------------------------------------
+//
+ // IFU <-> IDU interface consists of the following functional units:
+ // - Instruction bypass type decoder
+ // - IFU <-> IDU status signals
+ // - Output instruction multiplexer
+//
+
+`ifdef SCR1_NO_DEC_STAGE
+
+// Instruction bypass type decoder
+//------------------------------------------------------------------------------
+
+assign instr_bypass_vd = (instr_bypass_type != SCR1_BYPASS_NONE);
+
+always_comb begin
+ instr_bypass_type = SCR1_BYPASS_NONE;
+
+ if (imem_resp_vd) begin
+ if (q_is_empty) begin
+ case (instr_type)
+ SCR1_IFU_INSTR_RVC_NV,
+ SCR1_IFU_INSTR_RVC_RVC,
+ SCR1_IFU_INSTR_RVI_LO_RVC : begin
+ instr_bypass_type = SCR1_BYPASS_RVC;
+ end
+ SCR1_IFU_INSTR_RVI_HI_RVI_LO : begin
+ instr_bypass_type = SCR1_BYPASS_RVI_RDATA;
+ end
+ default : begin end
+ endcase // instr_type
+ end else if (q_has_1_ocpd_hw & q_head_is_rvi) begin
+ if (instr_hi_rvi_lo_ff) begin
+ instr_bypass_type = SCR1_BYPASS_RVI_RDATA_QUEUE;
+ end
+ end
+ end // imem_resp_vd
+end
+
+// IFU <-> IDU interface status signals
+//------------------------------------------------------------------------------
+
+always_comb begin
+ ifu2idu_vd_o = 1'b0;
+ ifu2idu_imem_err_o = 1'b0;
+ ifu2idu_err_rvi_hi_o = 1'b0;
+
+ if (ifu_fsm_fetch | ~q_is_empty) begin
+ if (instr_bypass_vd) begin
+ ifu2idu_vd_o = 1'b1;
+ ifu2idu_imem_err_o = (instr_bypass_type == SCR1_BYPASS_RVI_RDATA_QUEUE)
+ ? (imem_resp_er | q_err_head)
+ : imem_resp_er;
+ ifu2idu_err_rvi_hi_o = (instr_bypass_type == SCR1_BYPASS_RVI_RDATA_QUEUE) & imem_resp_er;
+ end else if (~q_is_empty) begin
+ if (q_has_1_ocpd_hw) begin
+ ifu2idu_vd_o = q_head_is_rvc | q_err_head;
+ ifu2idu_imem_err_o = q_err_head;
+ ifu2idu_err_rvi_hi_o = ~q_err_head & q_head_is_rvi & q_err_next;
+ end else begin
+ ifu2idu_vd_o = 1'b1;
+ ifu2idu_imem_err_o = q_err_head ? 1'b1 : (q_head_is_rvi & q_err_next);
+ end
+ end // ~q_is_empty
+ end
+`ifdef SCR1_DBG_EN
+ if (hdu2ifu_pbuf_fetch_i) begin
+ ifu2idu_vd_o = hdu2ifu_pbuf_vd_i;
+ ifu2idu_imem_err_o = hdu2ifu_pbuf_err_i;
+ end
+`endif // SCR1_DBG_EN
+end
+
+// Output instruction multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ case (instr_bypass_type)
+ SCR1_BYPASS_RVC : begin
+ ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'(new_pc_unaligned_ff ? imem_rdata_hi
+ : imem_rdata_lo);
+ end
+ SCR1_BYPASS_RVI_RDATA : begin
+ ifu2idu_instr_o = imem2ifu_rdata_i;
+ end
+ SCR1_BYPASS_RVI_RDATA_QUEUE: begin
+ ifu2idu_instr_o = {imem_rdata_lo, q_data_head};
+ end
+ default : begin
+ ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'(q_head_is_rvc ? q_data_head
+ : {q_data_next, q_data_head});
+ end
+ endcase // instr_bypass_type
+`ifdef SCR1_DBG_EN
+ if (hdu2ifu_pbuf_fetch_i) begin
+ ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'({'0, hdu2ifu_pbuf_instr_i});
+ end
+`endif // SCR1_DBG_EN
+end
+
+`else // SCR1_NO_DEC_STAGE
+
+// IFU <-> IDU interface status signals
+//------------------------------------------------------------------------------
+
+always_comb begin
+ ifu2idu_vd_o = 1'b0;
+ ifu2idu_imem_err_o = 1'b0;
+ ifu2idu_err_rvi_hi_o = 1'b0;
+ if (~q_is_empty) begin
+ if (q_has_1_ocpd_hw) begin
+ ifu2idu_vd_o = q_head_is_rvc | q_err_head;
+ ifu2idu_imem_err_o = q_err_head;
+ end else begin
+ ifu2idu_vd_o = 1'b1;
+ ifu2idu_imem_err_o = q_err_head ? 1'b1 : (q_head_is_rvi & q_err_next);
+ ifu2idu_err_rvi_hi_o = ~q_err_head & q_head_is_rvi & q_err_next;
+ end
+ end // ~q_is_empty
+`ifdef SCR1_DBG_EN
+ if (hdu2ifu_pbuf_fetch_i) begin
+ ifu2idu_vd_o = hdu2ifu_pbuf_vd_i;
+ ifu2idu_imem_err_o = hdu2ifu_pbuf_err_i;
+ end
+`endif // SCR1_DBG_EN
+end
+
+// Output instruction multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ ifu2idu_instr_o = q_head_is_rvc ? `SCR1_IMEM_DWIDTH'(q_data_head)
+ : {q_data_next, q_data_head};
+`ifdef SCR1_DBG_EN
+ if (hdu2ifu_pbuf_fetch_i) begin
+ ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'({'0, hdu2ifu_pbuf_instr_i});
+ end
+`endif // SCR1_DBG_EN
+end
+
+`endif // SCR1_NO_DEC_STAGE
+
+`ifdef SCR1_DBG_EN
+assign ifu2hdu_pbuf_rdy_o = idu2ifu_rdy_i;
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TRGT_SIMULATION
+
+//------------------------------------------------------------------------------
+// Assertions
+//------------------------------------------------------------------------------
+
+// X checks
+
+SCR1_SVA_IFU_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({imem2ifu_req_ack_i, idu2ifu_rdy_i, exu2ifu_pc_new_req_i})
+ ) else $error("IFU Error: unknown values");
+
+SCR1_SVA_IFU_XCHECK_REQ : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ ifu2imem_req_o |-> !$isunknown({ifu2imem_addr_o, ifu2imem_cmd_o})
+ ) else $error("IFU Error: unknown {ifu2imem_addr_o, ifu2imem_cmd_o}");
+
+// Behavior checks
+
+SCR1_SVA_IFU_DRC_UNDERFLOW : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ ~imem_resp_discard_req |=> ~(imem_resp_discard_cnt == SCR1_TXN_CNT_W'('1))
+ ) else $error("IFU Error: imem_resp_discard_cnt underflow");
+
+SCR1_SVA_IFU_DRC_RANGE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (imem_resp_discard_cnt >= 0) & (imem_resp_discard_cnt <= imem_pnd_txns_cnt)
+ ) else $error("IFU Error: imem_resp_discard_cnt out of range");
+
+SCR1_SVA_IFU_QUEUE_OVF : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (q_ocpd_h >= SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF-1)) |->
+ ((q_ocpd_h == SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF-1)) ? (q_wr_size != SCR1_IFU_QUEUE_WR_FULL)
+ : (q_wr_size == SCR1_IFU_QUEUE_WR_NONE))
+ ) else $error("IFU Error: queue overflow");
+
+SCR1_SVA_IFU_IMEM_ERR_BEH : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (imem_resp_er & ~imem_resp_discard_req & ~exu2ifu_pc_new_req_i) |=>
+ (ifu_fsm_curr == SCR1_IFU_FSM_IDLE) & (imem_resp_discard_cnt == imem_pnd_txns_cnt)
+ ) else $error("IFU Error: incorrect behavior after memory error");
+
+SCR1_SVA_IFU_NEW_PC_REQ_BEH : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2ifu_pc_new_req_i |=> q_is_empty
+ ) else $error("IFU Error: incorrect behavior after exu2ifu_pc_new_req_i");
+
+SCR1_SVA_IFU_IMEM_ADDR_ALIGNED : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ ifu2imem_req_o |-> ~|ifu2imem_addr_o[1:0]
+ ) else $error("IFU Error: unaligned IMEM access");
+
+SCR1_SVA_IFU_STOP_FETCH : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ pipe2ifu_stop_fetch_i |=> (ifu_fsm_curr == SCR1_IFU_FSM_IDLE)
+ ) else $error("IFU Error: fetch not stopped");
+
+SCR1_SVA_IFU_IMEM_FAULT_RVI_HI : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ ifu2idu_err_rvi_hi_o |-> ifu2idu_imem_err_o
+ ) else $error("IFU Error: ifu2idu_imem_err_o == 0");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_ifu
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_lsu.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_lsu.sv
new file mode 100644
index 0000000..cb87993
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_lsu.sv
@@ -0,0 +1,351 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_lsu.sv>
+/// @brief Load/Store Unit (LSU)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Performs load and store operations in Data Memory
+ // - Generates DMEM address misalign and access fault exceptions
+ // - Passes DMEM operations information to TDU and generates LSU breakpoint exception
+ //
+ // Structure:
+ // - FSM
+ // - Exceptions logic
+ // - LSU <-> EXU interface
+ // - LSU <-> DMEM interface
+ // - LSU <-> TDU interface
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+`include "scr1_arch_types.svh"
+`include "scr1_memif.svh"
+`include "scr1_riscv_isa_decoding.svh"
+`ifdef SCR1_TDU_EN
+`include "scr1_tdu.svh"
+`endif // SCR1_TDU_EN
+
+module scr1_pipe_lsu (
+ // Common
+ input logic rst_n, // LSU reset
+ input logic clk, // LSU clock
+
+ // LSU <-> EXU interface
+ input logic exu2lsu_req_i, // Request to LSU
+ input type_scr1_lsu_cmd_sel_e exu2lsu_cmd_i, // LSU command
+ input logic [`SCR1_XLEN-1:0] exu2lsu_addr_i, // Address of DMEM
+ input logic [`SCR1_XLEN-1:0] exu2lsu_sdata_i, // Data for store
+ output logic lsu2exu_rdy_o, // LSU received DMEM response
+ output logic [`SCR1_XLEN-1:0] lsu2exu_ldata_o, // Load data
+ output logic lsu2exu_exc_o, // Exception from LSU
+ output type_scr1_exc_code_e lsu2exu_exc_code_o, // Exception code
+
+`ifdef SCR1_TDU_EN
+ // LSU <-> TDU interface
+ output type_scr1_brkm_lsu_mon_s lsu2tdu_dmon_o, // Data address stream monitoring
+ input logic tdu2lsu_ibrkpt_exc_req_i, // Instruction BP exception request
+ input logic tdu2lsu_dbrkpt_exc_req_i, // Data BP exception request
+`endif // SCR1_TDU_EN
+
+ // LSU <-> DMEM interface
+ output logic lsu2dmem_req_o, // Data memory request
+ output type_scr1_mem_cmd_e lsu2dmem_cmd_o, // Data memory command (READ/WRITE)
+ output type_scr1_mem_width_e lsu2dmem_width_o, // Data memory data width
+ output logic [`SCR1_DMEM_AWIDTH-1:0] lsu2dmem_addr_o, // Data memory address
+ output logic [`SCR1_DMEM_DWIDTH-1:0] lsu2dmem_wdata_o, // Data memory write data
+ input logic dmem2lsu_req_ack_i, // Data memory request acknowledge
+ input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2lsu_rdata_i, // Data memory read data
+ input type_scr1_mem_resp_e dmem2lsu_resp_i // Data memory response
+);
+
+//------------------------------------------------------------------------------
+// Local types declaration
+//------------------------------------------------------------------------------
+
+typedef enum logic {
+ SCR1_LSU_FSM_IDLE,
+ SCR1_LSU_FSM_BUSY
+} type_scr1_lsu_fsm_e;
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// LSU FSM signals
+type_scr1_lsu_fsm_e lsu_fsm_curr; // LSU FSM current state
+type_scr1_lsu_fsm_e lsu_fsm_next; // LSU FSM next state
+logic lsu_fsm_idle; // LSU FSM is in IDLE state
+
+// LSU Command register signals
+logic lsu_cmd_upd; // LSU Command register update
+type_scr1_lsu_cmd_sel_e lsu_cmd_ff; // LSU Command register value
+logic lsu_cmd_ff_load; // Registered LSU Command is load
+logic lsu_cmd_ff_store; // Registered LSU Command is store
+
+// DMEM command and width flags
+logic dmem_cmd_load; // DMEM command is load
+logic dmem_cmd_store; // DMEM Command is store
+logic dmem_wdth_word; // DMEM data width is WORD
+logic dmem_wdth_hword; // DMEM data width is HALFWORD
+logic dmem_wdth_byte; // DMEM data width is BYTE
+
+// DMEM response and request control signals
+logic dmem_resp_ok; // DMEM response is OK
+logic dmem_resp_er; // DMEM response is erroneous
+logic dmem_resp_received; // DMEM response is received
+logic dmem_req_vd; // DMEM request is valid (req_ack received)
+
+// Exceptions signals
+logic lsu_exc_req; // LSU exception request
+logic dmem_addr_mslgn; // DMEM address is misaligned
+logic dmem_addr_mslgn_l; // DMEM load address is misaligned
+logic dmem_addr_mslgn_s; // DMEM store address is misaligned
+`ifdef SCR1_TDU_EN
+logic lsu_exc_hwbrk; // LSU hardware breakpoint exception
+`endif // SCR1_TDU_EN
+
+//------------------------------------------------------------------------------
+// Control logic
+//------------------------------------------------------------------------------
+
+// DMEM response and request control signals
+assign dmem_resp_ok = (dmem2lsu_resp_i == SCR1_MEM_RESP_RDY_OK);
+assign dmem_resp_er = (dmem2lsu_resp_i == SCR1_MEM_RESP_RDY_ER);
+assign dmem_resp_received = dmem_resp_ok | dmem_resp_er;
+assign dmem_req_vd = exu2lsu_req_i & dmem2lsu_req_ack_i & ~lsu_exc_req;
+
+// LSU load and store command flags
+assign dmem_cmd_load = (exu2lsu_cmd_i == SCR1_LSU_CMD_LB )
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_LBU)
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_LH )
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_LHU)
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_LW );
+assign dmem_cmd_store = (exu2lsu_cmd_i == SCR1_LSU_CMD_SB )
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_SH )
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_SW );
+
+// LSU data width flags
+assign dmem_wdth_word = (exu2lsu_cmd_i == SCR1_LSU_CMD_LW )
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_SW );
+assign dmem_wdth_hword = (exu2lsu_cmd_i == SCR1_LSU_CMD_LH )
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_LHU)
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_SH );
+assign dmem_wdth_byte = (exu2lsu_cmd_i == SCR1_LSU_CMD_LB )
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_LBU)
+ | (exu2lsu_cmd_i == SCR1_LSU_CMD_SB );
+
+// LSU command register
+assign lsu_cmd_upd = lsu_fsm_idle & dmem_req_vd;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ lsu_cmd_ff <= SCR1_LSU_CMD_NONE;
+ end else if (lsu_cmd_upd) begin
+ lsu_cmd_ff <= exu2lsu_cmd_i;
+ end
+end
+
+// LSU registered load and store command flags
+assign lsu_cmd_ff_load = (lsu_cmd_ff == SCR1_LSU_CMD_LB )
+ | (lsu_cmd_ff == SCR1_LSU_CMD_LBU)
+ | (lsu_cmd_ff == SCR1_LSU_CMD_LH )
+ | (lsu_cmd_ff == SCR1_LSU_CMD_LHU)
+ | (lsu_cmd_ff == SCR1_LSU_CMD_LW );
+assign lsu_cmd_ff_store = (lsu_cmd_ff == SCR1_LSU_CMD_SB )
+ | (lsu_cmd_ff == SCR1_LSU_CMD_SH )
+ | (lsu_cmd_ff == SCR1_LSU_CMD_SW );
+
+//------------------------------------------------------------------------------
+// LSU FSM
+//------------------------------------------------------------------------------
+ //
+ // LSU FSM is used to control the LSU <-> DMEM interface
+ //
+//
+
+// Updating LSU FSM state
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ lsu_fsm_curr <= SCR1_LSU_FSM_IDLE;
+ end else begin
+ lsu_fsm_curr <= lsu_fsm_next;
+ end
+end
+
+// LSU FSM next state logic
+always_comb begin
+ case (lsu_fsm_curr)
+ SCR1_LSU_FSM_IDLE: begin
+ lsu_fsm_next = dmem_req_vd ? SCR1_LSU_FSM_BUSY
+ : SCR1_LSU_FSM_IDLE;
+ end
+ SCR1_LSU_FSM_BUSY: begin
+ lsu_fsm_next = dmem_resp_received ? SCR1_LSU_FSM_IDLE
+ : SCR1_LSU_FSM_BUSY;
+ end
+ endcase
+end
+
+assign lsu_fsm_idle = (lsu_fsm_curr == SCR1_LSU_FSM_IDLE);
+
+//------------------------------------------------------------------------------
+// Exceptions logic
+//------------------------------------------------------------------------------
+ //
+ // The following types of exceptions are supported:
+ // - Load address misalign
+ // - Load access fault
+ // - Store address misalign
+ // - Store access fault
+ // - LSU breakpoint exception
+//
+
+// DMEM addr misalign logic
+assign dmem_addr_mslgn = exu2lsu_req_i & ( (dmem_wdth_hword & exu2lsu_addr_i[0])
+ | (dmem_wdth_word & |exu2lsu_addr_i[1:0]));
+assign dmem_addr_mslgn_l = dmem_addr_mslgn & dmem_cmd_load;
+assign dmem_addr_mslgn_s = dmem_addr_mslgn & dmem_cmd_store;
+
+// Exception code logic
+always_comb begin
+ case (1'b1)
+ dmem_resp_er : lsu2exu_exc_code_o = lsu_cmd_ff_load ? SCR1_EXC_CODE_LD_ACCESS_FAULT
+ : lsu_cmd_ff_store ? SCR1_EXC_CODE_ST_ACCESS_FAULT
+ : SCR1_EXC_CODE_INSTR_MISALIGN;
+`ifdef SCR1_TDU_EN
+ lsu_exc_hwbrk : lsu2exu_exc_code_o = SCR1_EXC_CODE_BREAKPOINT;
+`endif // SCR1_TDU_EN
+ dmem_addr_mslgn_l: lsu2exu_exc_code_o = SCR1_EXC_CODE_LD_ADDR_MISALIGN;
+ dmem_addr_mslgn_s: lsu2exu_exc_code_o = SCR1_EXC_CODE_ST_ADDR_MISALIGN;
+ default : lsu2exu_exc_code_o = SCR1_EXC_CODE_INSTR_MISALIGN;
+ endcase // 1'b1
+end
+
+assign lsu_exc_req = dmem_addr_mslgn_l | dmem_addr_mslgn_s
+`ifdef SCR1_TDU_EN
+ | lsu_exc_hwbrk
+`endif // SCR1_TDU_EN
+;
+
+//------------------------------------------------------------------------------
+// LSU <-> EXU interface
+//------------------------------------------------------------------------------
+
+assign lsu2exu_rdy_o = dmem_resp_received;
+assign lsu2exu_exc_o = dmem_resp_er | lsu_exc_req;
+
+// Sign- or zero-extending data received from DMEM
+always_comb begin
+ case (lsu_cmd_ff)
+ SCR1_LSU_CMD_LH : lsu2exu_ldata_o = {{16{dmem2lsu_rdata_i[15]}}, dmem2lsu_rdata_i[15:0]};
+ SCR1_LSU_CMD_LHU: lsu2exu_ldata_o = { 16'b0, dmem2lsu_rdata_i[15:0]};
+ SCR1_LSU_CMD_LB : lsu2exu_ldata_o = {{24{dmem2lsu_rdata_i[7]}}, dmem2lsu_rdata_i[7:0]};
+ SCR1_LSU_CMD_LBU: lsu2exu_ldata_o = { 24'b0, dmem2lsu_rdata_i[7:0]};
+ default : lsu2exu_ldata_o = dmem2lsu_rdata_i;
+ endcase // lsu_cmd_ff
+end
+
+//------------------------------------------------------------------------------
+// LSU <-> DMEM interface
+//------------------------------------------------------------------------------
+
+assign lsu2dmem_req_o = exu2lsu_req_i & ~lsu_exc_req & lsu_fsm_idle;
+assign lsu2dmem_addr_o = exu2lsu_addr_i;
+assign lsu2dmem_wdata_o = exu2lsu_sdata_i;
+assign lsu2dmem_cmd_o = dmem_cmd_store ? SCR1_MEM_CMD_WR : SCR1_MEM_CMD_RD;
+assign lsu2dmem_width_o = dmem_wdth_byte ? SCR1_MEM_WIDTH_BYTE
+ : dmem_wdth_hword ? SCR1_MEM_WIDTH_HWORD
+ : SCR1_MEM_WIDTH_WORD;
+
+`ifdef SCR1_TDU_EN
+//------------------------------------------------------------------------------
+// LSU <-> TDU interface
+//------------------------------------------------------------------------------
+
+assign lsu2tdu_dmon_o.vd = exu2lsu_req_i & lsu_fsm_idle & ~tdu2lsu_ibrkpt_exc_req_i;
+assign lsu2tdu_dmon_o.addr = exu2lsu_addr_i;
+assign lsu2tdu_dmon_o.load = dmem_cmd_load;
+assign lsu2tdu_dmon_o.store = dmem_cmd_store;
+
+assign lsu_exc_hwbrk = (exu2lsu_req_i & tdu2lsu_ibrkpt_exc_req_i)
+ | tdu2lsu_dbrkpt_exc_req_i;
+
+`endif // SCR1_TDU_EN
+
+`ifdef SCR1_TRGT_SIMULATION
+//------------------------------------------------------------------------------
+// Assertions
+//------------------------------------------------------------------------------
+
+// X checks
+
+SCR1_SVA_LSU_XCHECK_CTRL : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({exu2lsu_req_i, lsu_fsm_curr
+`ifdef SCR1_TDU_EN
+ , tdu2lsu_ibrkpt_exc_req_i, tdu2lsu_dbrkpt_exc_req_i
+`endif // SCR1_TDU_EN
+ })
+ ) else $error("LSU Error: unknown control value");
+
+SCR1_SVA_LSU_XCHECK_CMD : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2lsu_req_i |-> !$isunknown({exu2lsu_cmd_i, exu2lsu_addr_i})
+ ) else $error("LSU Error: undefined CMD or address");
+
+SCR1_SVA_LSU_XCHECK_SDATA : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (exu2lsu_req_i & (lsu2dmem_cmd_o == SCR1_MEM_CMD_WR)) |-> !$isunknown({exu2lsu_sdata_i})
+ ) else $error("LSU Error: undefined store data");
+
+SCR1_SVA_LSU_XCHECK_EXC : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ lsu2exu_exc_o |-> !$isunknown(lsu2exu_exc_code_o)
+ ) else $error("LSU Error: exception code undefined");
+
+SCR1_SVA_LSU_IMEM_CTRL : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ lsu2dmem_req_o |-> !$isunknown({lsu2dmem_cmd_o, lsu2dmem_width_o, lsu2dmem_addr_o})
+ ) else $error("LSU Error: undefined dmem control");
+
+SCR1_SVA_LSU_IMEM_ACK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ lsu2dmem_req_o |-> !$isunknown(dmem2lsu_req_ack_i)
+ ) else $error("LSU Error: undefined dmem ack");
+
+SCR1_SVA_LSU_IMEM_WDATA : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ lsu2dmem_req_o & (lsu2dmem_cmd_o == SCR1_MEM_CMD_WR)
+ |-> !$isunknown(lsu2dmem_wdata_o[8:0])
+ ) else $error("LSU Error: undefined dmem wdata");
+
+// Behavior checks
+
+SCR1_SVA_LSU_EXC_ONEHOT : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ $onehot0({dmem_resp_er, dmem_addr_mslgn_l, dmem_addr_mslgn_s})
+ ) else $error("LSU Error: more than one exception at a time");
+
+SCR1_SVA_LSU_UNEXPECTED_DMEM_RESP : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ lsu_fsm_idle |-> ~dmem_resp_received
+ ) else $error("LSU Error: not expecting memory response");
+
+SCR1_SVA_LSU_REQ_EXC : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ lsu2exu_exc_o |-> exu2lsu_req_i
+ ) else $error("LSU Error: impossible exception");
+
+`ifdef SCR1_TDU_EN
+
+SCR1_COV_LSU_MISALIGN_BRKPT : cover property (
+ @(negedge clk) disable iff (~rst_n)
+ (dmem_addr_mslgn_l | dmem_addr_mslgn_s) & lsu_exc_hwbrk
+);
+`endif // SCR1_TDU_EN
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_lsu
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_mprf.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_mprf.sv
new file mode 100644
index 0000000..6cb2a34
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_mprf.sv
@@ -0,0 +1,167 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_mprf.sv>
+/// @brief Multi Port Register File (MPRF)
+///
+
+`include "scr1_arch_description.svh"
+`include "scr1_arch_types.svh"
+
+module scr1_pipe_mprf (
+ // Common
+`ifdef SCR1_MPRF_RST_EN
+ input logic rst_n, // MPRF reset
+`endif // SCR1_MPRF_RST_EN
+ input logic clk, // MPRF clock
+
+ // EXU <-> MPRF interface
+ input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr_i, // MPRF rs1 read address
+ output logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data_o, // MPRF rs1 read data
+ input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr_i, // MPRF rs2 read address
+ output logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data_o, // MPRF rs2 read data
+ input logic exu2mprf_w_req_i, // MPRF write request
+ input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr_i, // MPRF rd write address
+ input logic [`SCR1_XLEN-1:0] exu2mprf_rd_data_i // MPRF rd write data
+);
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+
+logic wr_req_vd;
+
+logic rs1_addr_vd;
+logic rs2_addr_vd;
+
+`ifdef SCR1_MPRF_RAM
+logic rs1_addr_vd_ff;
+logic rs2_addr_vd_ff;
+
+logic rs1_new_data_req;
+logic rs2_new_data_req;
+logic rs1_new_data_req_ff;
+logic rs2_new_data_req_ff;
+logic read_new_data_req;
+
+logic [`SCR1_XLEN-1:0] rd_data_ff;
+
+logic [`SCR1_XLEN-1:0] rs1_data_ff;
+logic [`SCR1_XLEN-1:0] rs2_data_ff;
+
+// when using RAM, 2 memories are needed because 3 simultaneous independent
+// write/read operations can occur
+ `ifdef SCR1_TRGT_FPGA_INTEL_MAX10
+(* ramstyle = "M9K" *) logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
+(* ramstyle = "M9K" *) logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
+ `elsif SCR1_TRGT_FPGA_INTEL_ARRIAV
+(* ramstyle = "M10K" *) logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
+(* ramstyle = "M10K" *) logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
+ `else
+logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
+logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
+ `endif
+`else // distributed logic implementation
+type_scr1_mprf_v [1:`SCR1_MPRF_SIZE-1] mprf_int;
+`endif
+
+//------------------------------------------------------------------------------
+// MPRF control logic
+//------------------------------------------------------------------------------
+
+// control signals common for distributed logic and RAM implementations
+assign rs1_addr_vd = |exu2mprf_rs1_addr_i;
+assign rs2_addr_vd = |exu2mprf_rs2_addr_i;
+
+assign wr_req_vd = exu2mprf_w_req_i & |exu2mprf_rd_addr_i;
+
+// RAM implementation specific control signals
+`ifdef SCR1_MPRF_RAM
+assign rs1_new_data_req = wr_req_vd & ( exu2mprf_rs1_addr_i == exu2mprf_rd_addr_i );
+assign rs2_new_data_req = wr_req_vd & ( exu2mprf_rs2_addr_i == exu2mprf_rd_addr_i );
+assign read_new_data_req = rs1_new_data_req | rs2_new_data_req;
+
+always_ff @( posedge clk ) begin
+ rs1_addr_vd_ff <= rs1_addr_vd;
+ rs2_addr_vd_ff <= rs2_addr_vd;
+ rs1_new_data_req_ff <= rs1_new_data_req;
+ rs2_new_data_req_ff <= rs2_new_data_req;
+end
+`endif // SCR1_MPRF_RAM
+
+`ifdef SCR1_MPRF_RAM
+//-------------------------------------------------------------------------------
+// RAM implementation
+//-------------------------------------------------------------------------------
+
+// RAM is implemented with 2 simple dual-port memories with sync read operation;
+// logic for "write-first" RDW behavior is implemented externally to the embedded
+// memory blocks
+
+// bypass new wr_data to the read output if write/read collision occurs
+assign mprf2exu_rs1_data_o = ( rs1_new_data_req_ff ) ? rd_data_ff
+ : (( rs1_addr_vd_ff ) ? rs1_data_ff
+ : '0 );
+
+assign mprf2exu_rs2_data_o = ( rs2_new_data_req_ff ) ? rd_data_ff
+ : (( rs2_addr_vd_ff ) ? rs2_data_ff
+ : '0 );
+
+always_ff @( posedge clk ) begin
+ if ( read_new_data_req ) begin
+ rd_data_ff <= exu2mprf_rd_data_i;
+ end
+end
+
+// synchronous read operation
+always_ff @( posedge clk ) begin
+ rs1_data_ff <= mprf_int[exu2mprf_rs1_addr_i];
+ rs2_data_ff <= mprf_int2[exu2mprf_rs2_addr_i];
+end
+
+// write operation
+always_ff @( posedge clk ) begin
+ if ( wr_req_vd ) begin
+ mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
+ mprf_int2[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
+ end
+end
+`else // distributed logic implementation
+//------------------------------------------------------------------------------
+// distributed logic implementation
+//------------------------------------------------------------------------------
+
+// asynchronous read operation
+assign mprf2exu_rs1_data_o = ( rs1_addr_vd ) ? mprf_int[exu2mprf_rs1_addr_i] : '0;
+assign mprf2exu_rs2_data_o = ( rs2_addr_vd ) ? mprf_int[exu2mprf_rs2_addr_i] : '0;
+
+// write operation
+ `ifdef SCR1_MPRF_RST_EN
+always_ff @( posedge clk, negedge rst_n ) begin
+ if ( ~rst_n ) begin
+ mprf_int <= '{default: '0};
+ end else if ( wr_req_vd ) begin
+ mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
+ end
+end
+ `else // ~SCR1_MPRF_RST_EN
+always_ff @( posedge clk ) begin
+ if ( wr_req_vd ) begin
+ mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
+ end
+end
+ `endif // ~SCR1_MPRF_RST_EN
+`endif
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+`ifdef SCR1_MPRF_RST_EN
+SCR1_SVA_MPRF_WRITEX : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2mprf_w_req_i |-> !$isunknown({exu2mprf_rd_addr_i, (|exu2mprf_rd_addr_i ? exu2mprf_rd_data_i : `SCR1_XLEN'd0)})
+ ) else $error("MPRF error: unknown values");
+`endif // SCR1_MPRF_RST_EN
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_mprf
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_tdu.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_tdu.sv
new file mode 100644
index 0000000..441f6a4
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_tdu.sv
@@ -0,0 +1,610 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_tdu.sv>
+/// @brief Trigger Debug Unit (TDU)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Provides read/write interface for TDU CSRs
+ // - Provides triggers functionality:
+ // - Supports triggers either in both Debug and M modes or in Debug mode only
+ // - Supports virtual address matching (load, store, exec) triggers
+ // - Supports instruction count triggers
+ // - Supports the following actions on trigger firing:
+ // - Breakpoint exception raising
+ // - Debug Mode entering
+ // - Supports triggers chaining
+ //
+ // Structure:
+ // - CSR read/write i/f
+ // - TDU CSRs:
+ // - TSELECT
+ // - TDATA1/MCONTROL/ICOUNT
+ // - TDATA2
+ // - TINFO
+ // - TDU <-> EXU i/f
+ // - TDU <-> LSU i/f
+ // - TDU <-> HDU i/f
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_TDU_EN
+`include "scr1_riscv_isa_decoding.svh"
+`include "scr1_tdu.svh"
+
+module scr1_pipe_tdu (
+ // Common signals
+ input logic rst_n, // TDU reset
+ input logic clk, // TDU clock
+ input logic clk_en, // TDU clock enable
+ input logic tdu_dsbl_i, // TDU Disable
+
+ // TDU <-> CSR interface
+ input logic csr2tdu_req_i, // CSR-TDU i/f request
+ input type_scr1_csr_cmd_sel_e csr2tdu_cmd_i, // CSR-TDU i/f command
+ input logic [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] csr2tdu_addr_i, // CSR-TDU i/f address
+ input logic [SCR1_TDU_DATA_W-1:0] csr2tdu_wdata_i, // CSR-TDU i/f write data
+ output logic [SCR1_TDU_DATA_W-1:0] tdu2csr_rdata_o, // CSR-TDU i/f read data
+ output type_scr1_csr_resp_e tdu2csr_resp_o, // CSR-TDU i/f response
+
+ // TDU <-> EXU interface
+ input type_scr1_brkm_instr_mon_s exu2tdu_imon_i, // Instruction stream monitoring
+ output logic [SCR1_TDU_ALLTRIG_NUM-1 : 0] tdu2exu_ibrkpt_match_o, // Instruction BP match
+ output logic tdu2exu_ibrkpt_exc_req_o, // Instruction BP exception request
+ input logic [SCR1_TDU_ALLTRIG_NUM-1 : 0] exu2tdu_bp_retire_i, // Map of BPs being retired
+
+ // TDU <-> LSU interface
+`ifndef SCR1_TDU_EN
+ output logic tdu2lsu_brk_en_o, // TDU-LSU Breakpoint enable
+`endif // SCR1_TDU_EN
+ output logic tdu2lsu_ibrkpt_exc_req_o, // TDU-LSU Instruction BP exception request
+ input type_scr1_brkm_lsu_mon_s lsu2tdu_dmon_i, // TDU-LSU Data address stream monitoring
+ output logic [SCR1_TDU_MTRIG_NUM-1 : 0] tdu2lsu_dbrkpt_match_o, // TDU-LSU Data BP match
+ output logic tdu2lsu_dbrkpt_exc_req_o, // TDU-LSU Data BP exception request
+
+ // TDU <-> HDU interface
+ output logic tdu2hdu_dmode_req_o // Debug Mode redirection request
+);
+
+//------------------------------------------------------------------------------
+// Local parameters declaration
+//------------------------------------------------------------------------------
+
+localparam int unsigned MTRIG_NUM = SCR1_TDU_MTRIG_NUM;
+localparam int unsigned ALLTRIG_NUM = SCR1_TDU_ALLTRIG_NUM;
+localparam int unsigned ALLTRIG_W = $clog2(ALLTRIG_NUM+1);
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// TDU CSRs read/write i/f signals
+//------------------------------------------------------------------------------
+
+// Write signals
+logic csr_wr_req;
+logic [SCR1_TDU_DATA_W-1:0] csr_wr_data;
+
+// Register select
+logic csr_addr_tselect;
+logic [MTRIG_NUM-1:0] csr_addr_mcontrol;
+logic [MTRIG_NUM-1:0] csr_addr_tdata2;
+`ifdef SCR1_TDU_ICOUNT_EN
+logic csr_addr_icount;
+`endif // SCR1_TDU_ICOUNT_EN
+
+// TDU CSRs
+//------------------------------------------------------------------------------
+
+// TSELECT register
+logic csr_tselect_upd;
+logic [ALLTRIG_W-1:0] csr_tselect_ff;
+
+// MCONTROL register
+logic [MTRIG_NUM-1:0] csr_mcontrol_wr_req;
+logic [MTRIG_NUM-1:0] csr_mcontrol_clk_en;
+logic [MTRIG_NUM-1:0] csr_mcontrol_upd;
+
+logic [MTRIG_NUM-1:0] csr_mcontrol_dmode_ff;
+logic [MTRIG_NUM-1:0] csr_mcontrol_dmode_next;
+logic [MTRIG_NUM-1:0] csr_mcontrol_m_ff;
+logic [MTRIG_NUM-1:0] csr_mcontrol_m_next;
+logic [MTRIG_NUM-1:0] csr_mcontrol_exec_ff;
+logic [MTRIG_NUM-1:0] csr_mcontrol_exec_next;
+logic [MTRIG_NUM-1:0] csr_mcontrol_load_ff;
+logic [MTRIG_NUM-1:0] csr_mcontrol_load_next;
+logic [MTRIG_NUM-1:0] csr_mcontrol_store_ff;
+logic [MTRIG_NUM-1:0] csr_mcontrol_store_next;
+logic [MTRIG_NUM-1:0] csr_mcontrol_action_ff;
+logic [MTRIG_NUM-1:0] csr_mcontrol_action_next;
+logic [MTRIG_NUM-1:0] csr_mcontrol_hit_ff;
+logic [MTRIG_NUM-1:0] csr_mcontrol_hit_next;
+
+logic [MTRIG_NUM-1:0] csr_mcontrol_exec_hit;
+logic [MTRIG_NUM-1:0] csr_mcontrol_ldst_hit;
+
+// ICOUNT register
+`ifdef SCR1_TDU_ICOUNT_EN
+logic csr_icount_wr_req;
+logic csr_icount_clk_en;
+logic csr_icount_upd;
+
+logic csr_icount_dmode_ff;
+logic csr_icount_dmode_next;
+logic csr_icount_m_ff;
+logic csr_icount_m_next;
+logic csr_icount_action_ff;
+logic csr_icount_action_next;
+logic csr_icount_hit_ff;
+logic csr_icount_hit_next;
+logic [SCR1_TDU_ICOUNT_COUNT_HI-SCR1_TDU_ICOUNT_COUNT_LO:0]
+ csr_icount_count_ff;
+logic [SCR1_TDU_ICOUNT_COUNT_HI-SCR1_TDU_ICOUNT_COUNT_LO:0]
+ csr_icount_count_next;
+logic csr_icount_skip_ff;
+logic csr_icount_skip_next;
+
+logic csr_icount_decr_en;
+logic csr_icount_count_decr;
+logic csr_icount_skip_dsbl;
+logic csr_icount_hit;
+`endif // SCR1_TDU_ICOUNT_EN
+
+// TDATA2 register
+logic [MTRIG_NUM-1:0] csr_tdata2_upd;
+logic [MTRIG_NUM-1:0] [SCR1_TDU_DATA_W-1:0] csr_tdata2_ff;
+
+//------------------------------------------------------------------------------
+// CSR read/write interface
+//------------------------------------------------------------------------------
+
+// Read logic
+//------------------------------------------------------------------------------
+
+assign tdu2csr_resp_o = csr2tdu_req_i ? SCR1_CSR_RESP_OK : SCR1_CSR_RESP_ER;
+
+always_comb begin
+ tdu2csr_rdata_o = '0;
+ if (csr2tdu_req_i) begin
+ case (csr2tdu_addr_i)
+ SCR1_CSR_ADDR_TDU_OFFS_TSELECT: begin
+ tdu2csr_rdata_o = {'0, csr_tselect_ff};
+ end
+ SCR1_CSR_ADDR_TDU_OFFS_TDATA2 : begin
+ for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
+ if(csr_tselect_ff == ALLTRIG_W'(i)) begin
+ tdu2csr_rdata_o = csr_tdata2_ff[i];
+ end
+ end
+ end
+ SCR1_CSR_ADDR_TDU_OFFS_TDATA1 : begin
+ for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
+ if(csr_tselect_ff == ALLTRIG_W'(i)) begin
+ tdu2csr_rdata_o[SCR1_TDU_TDATA1_TYPE_HI:
+ SCR1_TDU_TDATA1_TYPE_LO] = SCR1_TDU_MCONTROL_TYPE_VAL;
+ tdu2csr_rdata_o[SCR1_TDU_TDATA1_DMODE] = csr_mcontrol_dmode_ff[i];
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_MASKMAX_HI:
+ SCR1_TDU_MCONTROL_MASKMAX_LO] = SCR1_TDU_MCONTROL_MASKMAX_VAL;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_HIT] = csr_mcontrol_hit_ff[i];
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_SELECT] = SCR1_TDU_MCONTROL_SELECT_VAL;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_TIMING] = SCR1_TDU_MCONTROL_TIMING_VAL;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_ACTION_HI:
+ SCR1_TDU_MCONTROL_ACTION_LO] = {5'b0, csr_mcontrol_action_ff[i]};
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_CHAIN] = 1'b0;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_MATCH_HI:
+ SCR1_TDU_MCONTROL_MATCH_LO] = 4'b0;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_M] = csr_mcontrol_m_ff[i];
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_RESERVEDA] = SCR1_TDU_MCONTROL_RESERVEDA_VAL;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_S] = 1'b0;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_U] = 1'b0;
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_EXECUTE] = csr_mcontrol_exec_ff [i];
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_STORE] = csr_mcontrol_store_ff[i];
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_LOAD] = csr_mcontrol_load_ff [i];
+ end
+ end
+`ifdef SCR1_TDU_ICOUNT_EN
+ if(csr_tselect_ff == ALLTRIG_W'(SCR1_TDU_ALLTRIG_NUM - 1'b1)) begin
+ tdu2csr_rdata_o[SCR1_TDU_TDATA1_TYPE_HI:
+ SCR1_TDU_TDATA1_TYPE_LO] = SCR1_TDU_ICOUNT_TYPE_VAL;
+ tdu2csr_rdata_o[SCR1_TDU_TDATA1_DMODE] = csr_icount_dmode_ff;
+ tdu2csr_rdata_o[SCR1_TDU_ICOUNT_HIT] = csr_icount_hit_ff;
+ tdu2csr_rdata_o[SCR1_TDU_ICOUNT_COUNT_HI:
+ SCR1_TDU_ICOUNT_COUNT_LO] = csr_icount_count_ff;
+ tdu2csr_rdata_o[SCR1_TDU_ICOUNT_U] = 1'b0;
+ tdu2csr_rdata_o[SCR1_TDU_ICOUNT_S] = 1'b0;
+ tdu2csr_rdata_o[SCR1_TDU_ICOUNT_M] = csr_icount_m_ff;
+ tdu2csr_rdata_o[SCR1_TDU_ICOUNT_ACTION_HI:
+ SCR1_TDU_ICOUNT_ACTION_LO] = {5'b0, csr_icount_action_ff};
+ end
+`endif // SCR1_TDU_ICOUNT_EN
+ end
+ SCR1_CSR_ADDR_TDU_OFFS_TINFO : begin
+ for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
+ if(csr_tselect_ff == ALLTRIG_W'(i)) begin
+ tdu2csr_rdata_o[SCR1_TDU_MCONTROL_TYPE_VAL] = 1'b1;
+ end
+ end
+`ifdef SCR1_TDU_ICOUNT_EN
+ if(csr_tselect_ff == ALLTRIG_W'(SCR1_TDU_ALLTRIG_NUM - 1'b1)) begin
+ tdu2csr_rdata_o[SCR1_TDU_ICOUNT_TYPE_VAL] = 1'b1;
+ end
+`endif // SCR1_TDU_ICOUNT_EN
+ end
+ default : begin
+ end
+ endcase
+ end
+end
+
+// Write logic
+//------------------------------------------------------------------------------
+
+always_comb begin
+ csr_wr_req = 1'b0;
+ csr_wr_data = '0;
+
+ case (csr2tdu_cmd_i)
+ SCR1_CSR_CMD_WRITE: begin
+ csr_wr_req = 1'b1;
+ csr_wr_data = csr2tdu_wdata_i;
+ end
+ SCR1_CSR_CMD_SET : begin
+ csr_wr_req = |csr2tdu_wdata_i;
+ csr_wr_data = tdu2csr_rdata_o | csr2tdu_wdata_i;
+ end
+ SCR1_CSR_CMD_CLEAR: begin
+ csr_wr_req = |csr2tdu_wdata_i;
+ csr_wr_data = tdu2csr_rdata_o & ~csr2tdu_wdata_i;
+ end
+ default : begin
+ end
+ endcase
+end
+
+// Register selection
+//------------------------------------------------------------------------------
+
+always_comb begin
+ csr_addr_tselect = 1'b0;
+ csr_addr_tdata2 = '0;
+ csr_addr_mcontrol = '0;
+`ifdef SCR1_TDU_ICOUNT_EN
+ csr_addr_icount = '0;
+`endif // SCR1_TDU_ICOUNT_EN
+
+ if (csr2tdu_req_i) begin
+ case (csr2tdu_addr_i)
+ SCR1_CSR_ADDR_TDU_OFFS_TSELECT: begin
+ csr_addr_tselect = 1'b1;
+ end
+ SCR1_CSR_ADDR_TDU_OFFS_TDATA1 : begin
+ for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
+ if(csr_tselect_ff == ALLTRIG_W'(i)) begin
+ csr_addr_mcontrol[i] = 1'b1;
+ end
+ end
+`ifdef SCR1_TDU_ICOUNT_EN
+ if(csr_tselect_ff == ALLTRIG_W'(SCR1_TDU_ALLTRIG_NUM - 1'b1)) begin
+ csr_addr_icount = 1'b1;
+ end
+`endif // SCR1_TDU_ICOUNT_EN
+ end
+ SCR1_CSR_ADDR_TDU_OFFS_TDATA2 : begin
+ for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
+ if(csr_tselect_ff == ALLTRIG_W'(i) ) begin
+ csr_addr_tdata2[i] = 1'b1;
+ end
+ end
+ end
+ default : begin
+ end
+ endcase
+ end
+end
+
+//------------------------------------------------------------------------------
+// TDU CSRs
+//------------------------------------------------------------------------------
+//
+ // TDU CSRs consist of the following registers:
+ // - TSELECT
+ // - TDATA1/MCONTROL/ICOUNT (depending on the type field value)
+ // - TDATA2
+//
+
+// TSELECT register
+//------------------------------------------------------------------------------
+// Determines which trigger is accessible through the other trigger registers
+
+assign csr_tselect_upd = clk_en & csr_addr_tselect & csr_wr_req
+ & (csr_wr_data[ALLTRIG_W-1:0] < ALLTRIG_W'(ALLTRIG_NUM));
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if(~rst_n) begin
+ csr_tselect_ff <= '0;
+ end else if(csr_tselect_upd) begin
+ csr_tselect_ff <= csr_wr_data[ALLTRIG_W-1:0];
+ end
+end
+
+`ifdef SCR1_TDU_ICOUNT_EN
+// ICOUNT register
+//------------------------------------------------------------------------------
+// Provides a trigger that fires when the certain number of instructions has retired
+// Is intended to be used as a single step trigger (in this case count must be 1)
+
+assign csr_icount_wr_req = csr_addr_icount & csr_wr_req;
+assign csr_icount_clk_en = clk_en & (csr_icount_wr_req | csr_icount_m_ff);
+assign csr_icount_upd = ~csr_icount_dmode_ff
+ ? csr_icount_wr_req
+ : tdu_dsbl_i & csr_icount_wr_req;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if(~rst_n) begin
+ csr_icount_dmode_ff <= 1'b0;
+ csr_icount_m_ff <= 1'b0;
+ csr_icount_action_ff <= 1'b0;
+ csr_icount_hit_ff <= 1'b0;
+ csr_icount_count_ff <= '0;
+ csr_icount_skip_ff <= 1'b0;
+ end else if (csr_icount_clk_en) begin
+ csr_icount_dmode_ff <= csr_icount_dmode_next;
+ csr_icount_m_ff <= csr_icount_m_next;
+ csr_icount_action_ff <= csr_icount_action_next;
+ csr_icount_hit_ff <= csr_icount_hit_next;
+ csr_icount_count_ff <= csr_icount_count_next;
+ csr_icount_skip_ff <= csr_icount_skip_next;
+ end
+end
+
+assign csr_icount_decr_en = (~tdu_dsbl_i & csr_icount_m_ff)
+ ? exu2tdu_imon_i.vd & (csr_icount_count_ff != 14'b0)
+ : 1'b0;
+assign csr_icount_count_decr = exu2tdu_imon_i.req & csr_icount_decr_en & ~csr_icount_skip_ff;
+assign csr_icount_skip_dsbl = exu2tdu_imon_i.req & csr_icount_decr_en & csr_icount_skip_ff;
+
+always_comb begin
+ if (csr_icount_upd) begin
+ csr_icount_dmode_next = csr_wr_data[SCR1_TDU_TDATA1_DMODE];
+ csr_icount_m_next = csr_wr_data[SCR1_TDU_ICOUNT_M];
+ csr_icount_action_next = (csr_wr_data[SCR1_TDU_ICOUNT_ACTION_HI
+ :SCR1_TDU_ICOUNT_ACTION_LO] == 'b1);
+ csr_icount_hit_next = csr_wr_data[SCR1_TDU_ICOUNT_HIT];
+ csr_icount_count_next = csr_wr_data[SCR1_TDU_ICOUNT_COUNT_HI:SCR1_TDU_ICOUNT_COUNT_LO];
+ end else begin
+ csr_icount_dmode_next = csr_icount_dmode_ff;
+ csr_icount_m_next = csr_icount_m_ff;
+ csr_icount_action_next = csr_icount_action_ff;
+ csr_icount_hit_next = exu2tdu_bp_retire_i[ALLTRIG_NUM - 1'b1]
+ ? 1'b1
+ : csr_icount_hit_ff;
+ csr_icount_count_next = csr_icount_count_decr
+ ? csr_icount_count_ff - 1'b1
+ : csr_icount_count_ff;
+ end
+end
+
+assign csr_icount_skip_next = csr_icount_wr_req ? csr_wr_data[SCR1_TDU_ICOUNT_M]
+ : csr_icount_skip_dsbl ? 1'b0
+ : csr_icount_skip_ff;
+`endif // SCR1_TDU_ICOUNT_EN
+
+// MCONTROL registers
+//------------------------------------------------------------------------------
+// Provides a trigger that fires on the virtual address (stored in TDATA2) match
+// (load, store, exec options supported). Triggers chaining supported
+
+genvar trig;
+generate
+for (trig = 0; $unsigned(trig) < MTRIG_NUM; ++trig) begin : gblock_mtrig
+
+assign csr_mcontrol_wr_req[trig] = csr_addr_mcontrol[trig] & csr_wr_req;
+assign csr_mcontrol_clk_en[trig] = clk_en
+ & (csr_mcontrol_wr_req[trig] | csr_mcontrol_m_ff[trig]);
+assign csr_mcontrol_upd [trig] = ~csr_mcontrol_dmode_ff[trig]
+ ? csr_mcontrol_wr_req[trig]
+ : tdu_dsbl_i & csr_mcontrol_wr_req[trig];
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if(~rst_n) begin
+ csr_mcontrol_dmode_ff [trig] <= 1'b0;
+ csr_mcontrol_m_ff [trig] <= 1'b0;
+ csr_mcontrol_exec_ff [trig] <= 1'b0;
+ csr_mcontrol_load_ff [trig] <= 1'b0;
+ csr_mcontrol_store_ff [trig] <= 1'b0;
+ csr_mcontrol_action_ff[trig] <= 1'b0;
+ csr_mcontrol_hit_ff [trig] <= 1'b0;
+ end else if(csr_mcontrol_clk_en[trig]) begin
+ csr_mcontrol_dmode_ff [trig] <= csr_mcontrol_dmode_next[trig];
+ csr_mcontrol_m_ff [trig] <= csr_mcontrol_m_next[trig];
+ csr_mcontrol_exec_ff [trig] <= csr_mcontrol_exec_next[trig];
+ csr_mcontrol_load_ff [trig] <= csr_mcontrol_load_next[trig];
+ csr_mcontrol_store_ff [trig] <= csr_mcontrol_store_next[trig];
+ csr_mcontrol_action_ff[trig] <= csr_mcontrol_action_next[trig];
+ csr_mcontrol_hit_ff [trig] <= csr_mcontrol_hit_next[trig];
+ end
+end
+
+always_comb begin
+ if (csr_mcontrol_upd[trig]) begin
+ csr_mcontrol_dmode_next [trig] = csr_wr_data[SCR1_TDU_TDATA1_DMODE];
+ csr_mcontrol_m_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_M];
+ csr_mcontrol_exec_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_EXECUTE];
+ csr_mcontrol_load_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_LOAD];
+ csr_mcontrol_store_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_STORE];
+ csr_mcontrol_action_next[trig] = (csr_wr_data[SCR1_TDU_MCONTROL_ACTION_HI
+ :SCR1_TDU_MCONTROL_ACTION_LO] == 'b1);
+ csr_mcontrol_hit_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_HIT];
+ end else begin
+ csr_mcontrol_dmode_next [trig] = csr_mcontrol_dmode_ff [trig];
+ csr_mcontrol_m_next [trig] = csr_mcontrol_m_ff [trig];
+ csr_mcontrol_exec_next [trig] = csr_mcontrol_exec_ff [trig];
+ csr_mcontrol_load_next [trig] = csr_mcontrol_load_ff [trig];
+ csr_mcontrol_store_next [trig] = csr_mcontrol_store_ff [trig];
+ csr_mcontrol_action_next[trig] = csr_mcontrol_action_ff[trig];
+ csr_mcontrol_hit_next [trig] = exu2tdu_bp_retire_i[trig]
+ ? 1'b1
+ : csr_mcontrol_hit_ff[trig];
+ end
+end
+
+// TDATA2 register
+//------------------------------------------------------------------------------
+
+assign csr_tdata2_upd[trig] = ~csr_mcontrol_dmode_ff[trig]
+ ? clk_en & csr_addr_tdata2[trig] & csr_wr_req
+ : clk_en & csr_addr_tdata2[trig] & csr_wr_req & tdu_dsbl_i;
+
+always_ff @(posedge clk) begin
+ if (csr_tdata2_upd[trig]) begin
+ csr_tdata2_ff[trig] <= csr_wr_data;
+ end
+end
+
+end
+endgenerate // gblock_mtrig
+
+//------------------------------------------------------------------------------
+// TDU <-> EXU interface
+//------------------------------------------------------------------------------
+
+assign csr_icount_hit = ~tdu_dsbl_i & csr_icount_m_ff
+ ? exu2tdu_imon_i.vd & (csr_icount_count_ff == 14'b1) & ~csr_icount_skip_ff
+ : 1'b0;
+
+`ifndef SCR1_TDU_ICOUNT_EN
+assign tdu2exu_ibrkpt_match_o = csr_mcontrol_exec_hit;
+assign tdu2exu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit;
+`else
+assign tdu2exu_ibrkpt_match_o = {csr_icount_hit, csr_mcontrol_exec_hit};
+assign tdu2exu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit | csr_icount_hit;
+`endif // SCR1_TDU_ICOUNT_EN
+
+//------------------------------------------------------------------------------
+// TDU <-> LSU interface
+//------------------------------------------------------------------------------
+
+// Breakpoint logic
+//------------------------------------------------------------------------------
+
+generate
+for (trig = 0; $unsigned(trig) < MTRIG_NUM; ++trig) begin : gblock_break_trig
+assign csr_mcontrol_exec_hit[trig] = ~tdu_dsbl_i
+ & csr_mcontrol_m_ff[trig]
+ & csr_mcontrol_exec_ff[trig]
+ & exu2tdu_imon_i.vd
+ & exu2tdu_imon_i.addr == csr_tdata2_ff[trig];
+end
+endgenerate
+
+`ifndef SCR1_TDU_ICOUNT_EN
+assign tdu2lsu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit;
+`else
+assign tdu2lsu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit | csr_icount_hit;
+`endif // SCR1_TDU_ICOUNT_EN
+
+// Watchpoint logic
+//------------------------------------------------------------------------------
+
+generate
+for( trig = 0; $unsigned(trig) < MTRIG_NUM; ++trig ) begin : gblock_watch_trig
+assign csr_mcontrol_ldst_hit[trig] = ~tdu_dsbl_i
+ & csr_mcontrol_m_ff[trig]
+ & lsu2tdu_dmon_i.vd
+ & ( (csr_mcontrol_load_ff [trig] & lsu2tdu_dmon_i.load)
+ | (csr_mcontrol_store_ff[trig] & lsu2tdu_dmon_i.store))
+ & lsu2tdu_dmon_i.addr == csr_tdata2_ff[trig];
+end
+endgenerate
+
+assign tdu2lsu_dbrkpt_match_o = csr_mcontrol_ldst_hit;
+assign tdu2lsu_dbrkpt_exc_req_o = |csr_mcontrol_ldst_hit;
+
+`ifndef SCR1_TDU_EN
+assign tdu2lsu_brk_en_o = |csr_mcontrol_m_ff | csr_icount_m_ff;
+`endif // SCR1_TDU_EN
+
+//------------------------------------------------------------------------------
+// TDU <-> HDU interface
+//------------------------------------------------------------------------------
+
+always_comb begin
+ tdu2hdu_dmode_req_o = 1'b0;
+
+ for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
+ tdu2hdu_dmode_req_o |= (csr_mcontrol_action_ff[i] & exu2tdu_bp_retire_i[i]);
+ end
+`ifdef SCR1_TDU_ICOUNT_EN
+ tdu2hdu_dmode_req_o |= (csr_icount_action_ff & exu2tdu_bp_retire_i[ALLTRIG_NUM-1]);
+`endif // SCR1_TDU_ICOUNT_EN
+end
+
+`ifdef SCR1_TRGT_SIMULATION
+//------------------------------------------------------------------------------
+// Assertion
+//------------------------------------------------------------------------------
+
+SVA_TDU_X_CONTROL : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({clk_en, tdu_dsbl_i, csr2tdu_req_i,
+ exu2tdu_imon_i.vd, lsu2tdu_dmon_i.vd, exu2tdu_bp_retire_i})
+ ) else $error("TDU Error: control signals is X - %0b", {clk_en,
+ tdu_dsbl_i, csr2tdu_req_i, exu2tdu_imon_i.vd, lsu2tdu_dmon_i.vd, exu2tdu_bp_retire_i});
+
+SVA_DM_X_CLK_EN : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(clk_en)
+ ) else $error("TDU Error: clk_en control signals is X");
+
+SVA_DM_X_DSBL : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(tdu_dsbl_i)
+ ) else $error("TDU Error: tdu_dsbl_i control signals is X");
+
+SVA_DM_X_CSR2TDU_REQ : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(csr2tdu_req_i)
+ ) else $error("TDU Error: csr2tdu_req_i control signals is X");
+
+SVA_DM_X_I_MON_VD : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(exu2tdu_imon_i.vd)
+ ) else $error("TDU Error: exu2tdu_imon_i.vd control signals is X");
+
+SVA_DM_X_D_MON_VD : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(lsu2tdu_dmon_i.vd)
+ ) else $error("TDU Error: lsu2tdu_dmon_i.vd control signals is X");
+
+SVA_DM_X_BP_RETIRE : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(exu2tdu_bp_retire_i)
+ ) else $error("TDU Error: exu2tdu_bp_retire_i control signals is X");
+
+SVA_TDU_X_CSR : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ csr2tdu_req_i |-> !$isunknown({csr2tdu_cmd_i,csr2tdu_addr_i})
+ ) else $error("TDU Error: csr is X");
+
+SVA_TDU_XW_CSR : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ (csr2tdu_req_i & csr_wr_req) |-> !$isunknown(csr2tdu_wdata_i)
+ ) else $error("TDU Error: csr wdata is X ");
+
+SVA_TDU_X_IMON : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ exu2tdu_imon_i.vd |-> !$isunknown({exu2tdu_imon_i.req,exu2tdu_imon_i.addr})
+ ) else $error("TDU Error: imonitor is X");
+
+SVA_TDU_X_DMON : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ lsu2tdu_dmon_i.vd |-> !$isunknown({lsu2tdu_dmon_i})
+ ) else $error("TDU Error: dmonitor is X");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_tdu
+
+`endif // SCR1_TDU_EN
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_top.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_top.sv
new file mode 100644
index 0000000..69ea0d1
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_pipe_top.sv
@@ -0,0 +1,809 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_pipe_top.sv>
+/// @brief SCR1 pipeline top
+///
+
+`include "scr1_arch_description.svh"
+`include "scr1_memif.svh"
+`include "scr1_riscv_isa_decoding.svh"
+`include "scr1_csr.svh"
+
+`ifdef SCR1_IPIC_EN
+`include "scr1_ipic.svh"
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_DBG_EN
+`include "scr1_hdu.svh"
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+`include "scr1_tdu.svh"
+`endif // SCR1_TDU_EN
+
+module scr1_pipe_top (
+ // Common
+ input logic pipe_rst_n, // Pipe reset
+`ifdef SCR1_DBG_EN
+ input logic pipe2hdu_rdc_qlfy_i, // Pipe RDC qualifier
+ input logic dbg_rst_n, // Debug reset
+`endif // SCR1_DBG_EN
+ input logic clk, // Pipe clock
+
+ // Instruction Memory Interface
+ output logic pipe2imem_req_o, // IMEM request
+ output type_scr1_mem_cmd_e pipe2imem_cmd_o, // IMEM command
+ output logic [`SCR1_IMEM_AWIDTH-1:0] pipe2imem_addr_o, // IMEM address
+ input logic imem2pipe_req_ack_i, // IMEM request acknowledge
+ input logic [`SCR1_IMEM_DWIDTH-1:0] imem2pipe_rdata_i, // IMEM read data
+ input type_scr1_mem_resp_e imem2pipe_resp_i, // IMEM response
+
+ // Data Memory Interface
+ output logic pipe2dmem_req_o, // DMEM request
+ output type_scr1_mem_cmd_e pipe2dmem_cmd_o, // DMEM command
+ output type_scr1_mem_width_e pipe2dmem_width_o, // DMEM data width
+ output logic [`SCR1_DMEM_AWIDTH-1:0] pipe2dmem_addr_o, // DMEM address
+ output logic [`SCR1_DMEM_DWIDTH-1:0] pipe2dmem_wdata_o, // DMEM write data
+ input logic dmem2pipe_req_ack_i, // DMEM request acknowledge
+ input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2pipe_rdata_i, // DMEM read data
+ input type_scr1_mem_resp_e dmem2pipe_resp_i, // DMEM response
+
+`ifdef SCR1_DBG_EN
+ // Debug interface:
+ input logic dbg_en, // 1 - debug operations enabled
+ // DM <-> Pipeline: HART Run Control i/f
+ input logic dm2pipe_active_i, // Debug Module active flag
+ input logic dm2pipe_cmd_req_i, // Request from Debug Module
+ input type_scr1_hdu_dbgstates_e dm2pipe_cmd_i, // Command from Debug Module
+ output logic pipe2dm_cmd_resp_o, // Response to Debug Module
+ output logic pipe2dm_cmd_rcode_o, // Debug Module return code: 0 - Ok; 1 - Error
+ output logic pipe2dm_hart_event_o, // HART event flag
+ output type_scr1_hdu_hartstatus_s pipe2dm_hart_status_o, // HART status
+
+ // DM <-> Pipeline: Program Buffer - HART instruction execution i/f
+ output logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pipe2dm_pbuf_addr_o, // Program Buffer address
+ input logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2pipe_pbuf_instr_i, // Program Buffer instruction
+
+ // DM <-> Pipeline: HART Abstract Data regs i/f
+ output logic pipe2dm_dreg_req_o, // Abstract Data Register request
+ output logic pipe2dm_dreg_wr_o, // Abstract Data Register write
+ output logic [`SCR1_XLEN-1:0] pipe2dm_dreg_wdata_o, // Abstract Data Register write data
+ input logic dm2pipe_dreg_resp_i, // Abstract Data Register response
+ input logic dm2pipe_dreg_fail_i, // Abstract Data Register fail - possibly not needed?
+ input logic [`SCR1_XLEN-1:0] dm2pipe_dreg_rdata_i, // Abstract Data Register read data
+
+ // DM <-> Pipeling: PC i/f
+ output logic [`SCR1_XLEN-1:0] pipe2dm_pc_sample_o, // Current PC for sampling
+`endif // SCR1_DBG_EN
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ input logic [SCR1_IRQ_LINES_NUM-1:0] soc2pipe_irq_lines_i, // External interrupt request lines
+`else // SCR1_IPIC_EN
+ input logic soc2pipe_irq_ext_i, // External interrupt request
+`endif // SCR1_IPIC_EN
+ input logic soc2pipe_irq_soft_i, // Software generated interrupt request
+ input logic soc2pipe_irq_mtimer_i, // Machine timer interrupt request
+
+ // Memory-mapped external timer
+ input logic [63:0] soc2pipe_mtimer_val_i, // Machine timer value
+
+`ifdef SCR1_CLKCTRL_EN
+ // CLK_CTRL interface
+ output logic pipe2clkctl_sleep_req_o, // CLK disable request to CLK gating circuit
+ output logic pipe2clkctl_wake_req_o, // CLK enable request to CLK gating circuit
+ input logic clkctl2pipe_clk_alw_on_i, // Not gated CLK
+ input logic clkctl2pipe_clk_dbgc_i, // CLK for HDU (not gated for now)
+ input logic clkctl2pipe_clk_en_i, // CLK enabled flag
+`endif // SCR1_CLKCTRL_EN
+
+ // Fuse
+ input logic [`SCR1_XLEN-1:0] soc2pipe_fuse_mhartid_i // Fuse MHARTID value
+);
+
+//-------------------------------------------------------------------------------
+// Local signals declaration
+//-------------------------------------------------------------------------------
+
+// Pipeline control
+logic [`SCR1_XLEN-1:0] curr_pc; // Current PC
+logic [`SCR1_XLEN-1:0] next_pc; // Is written to MEPC on interrupt trap
+logic new_pc_req; // New PC request (jumps, branches, traps etc)
+logic [`SCR1_XLEN-1:0] new_pc; // New PC
+
+logic stop_fetch; // Stop IFU
+logic exu_exc_req; // Exception request
+logic brkpt; // Breakpoint (sw) on current instruction
+logic exu_init_pc; // Reset exit
+logic wfi_run2halt; // Transition to WFI halted state
+logic instret; // Instruction retirement (with or without exception)
+logic instret_nexc; // Instruction retirement (without exception)
+`ifdef SCR1_IPIC_EN
+logic ipic2csr_irq; // IRQ request from IPIC
+`endif // SCR1_IPIC_EN
+`ifdef SCR1_TDU_EN
+logic brkpt_hw; // Hardware breakpoint on current instruction
+`endif // SCR1_TDU_EN
+`ifdef SCR1_CLKCTRL_EN
+logic imem_txns_pending; // There are pending imem transactions
+logic wfi_halted; // WFI halted state
+`endif // SCR1_CLKCTRL_EN
+
+// IFU <-> IDU
+logic ifu2idu_vd; // IFU request
+logic [`SCR1_IMEM_DWIDTH-1:0] ifu2idu_instr; // IFU instruction
+logic ifu2idu_imem_err; // IFU instruction access fault
+logic ifu2idu_err_rvi_hi; // 1 - imem fault when trying to fetch second half of an unaligned RVI instruction
+logic idu2ifu_rdy; // IDU ready for new data
+
+// IDU <-> EXU
+logic idu2exu_req; // IDU request
+type_scr1_exu_cmd_s idu2exu_cmd; // IDU command (see scr1_riscv_isa_decoding.svh)
+logic idu2exu_use_rs1; // Instruction uses rs1
+logic idu2exu_use_rs2; // Instruction uses rs2
+logic idu2exu_use_rd; // Instruction uses rd
+logic idu2exu_use_imm; // Instruction uses immediate
+logic exu2idu_rdy; // EXU ready for new data
+
+// EXU <-> MPRF
+logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr; // MPRF rs1 read address
+logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data; // MPRF rs1 read data
+logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr; // MPRF rs2 read address
+logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data; // MPRF rs2 read data
+logic exu2mprf_w_req; // MPRF write request
+logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr; // MPRF rd write address
+logic [`SCR1_XLEN-1:0] exu2mprf_rd_data; // MPRF rd write data
+
+// EXU <-> CSR
+logic [SCR1_CSR_ADDR_WIDTH-1:0] exu2csr_rw_addr; // CSR read/write address
+logic exu2csr_r_req; // CSR read request
+logic [`SCR1_XLEN-1:0] csr2exu_r_data; // CSR read data
+logic exu2csr_w_req; // CSR write request
+type_scr1_csr_cmd_sel_e exu2csr_w_cmd; // CSR write command
+logic [`SCR1_XLEN-1:0] exu2csr_w_data; // CSR write data
+logic csr2exu_rw_exc; // CSR read/write access exception
+
+// EXU <-> CSR event interface
+logic exu2csr_take_irq; // Take IRQ trap
+logic exu2csr_take_exc; // Take exception trap
+logic exu2csr_mret_update; // MRET update CSR
+logic exu2csr_mret_instr; // MRET instruction
+type_scr1_exc_code_e exu2csr_exc_code; // Exception code (see scr1_arch_types.svh)
+logic [`SCR1_XLEN-1:0] exu2csr_trap_val; // Trap value
+logic [`SCR1_XLEN-1:0] csr2exu_new_pc; // Exception/IRQ/MRET new PC
+logic csr2exu_irq; // IRQ request
+logic csr2exu_ip_ie; // Some IRQ pending and locally enabled
+logic csr2exu_mstatus_mie_up; // MSTATUS or MIE update in the current cycle
+
+`ifdef SCR1_IPIC_EN
+// CSR <-> IPIC
+logic csr2ipic_r_req; // IPIC read request
+logic csr2ipic_w_req; // IPIC write request
+logic [2:0] csr2ipic_addr; // IPIC address
+logic [`SCR1_XLEN-1:0] csr2ipic_wdata; // IPIC write data
+logic [`SCR1_XLEN-1:0] ipic2csr_rdata; // IPIC read data
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_TDU_EN
+// CSR <-> TDU
+logic csr2tdu_req; // Request to TDU
+type_scr1_csr_cmd_sel_e csr2tdu_cmd; // TDU command
+logic [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] csr2tdu_addr; // TDU address
+logic [`SCR1_XLEN-1:0] csr2tdu_wdata; // TDU write data
+logic [`SCR1_XLEN-1:0] tdu2csr_rdata; // TDU read data
+type_scr1_csr_resp_e tdu2csr_resp; // TDU response
+ `ifdef SCR1_DBG_EN
+ // Qualified TDU input signals from pipe_rst_n
+ // reset domain:
+logic csr2tdu_req_qlfy; // Request to TDU
+ `endif // SCR1_DBG_EN
+
+// EXU/LSU <-> TDU
+type_scr1_brkm_instr_mon_s exu2tdu_i_mon; // Instruction monitor
+type_scr1_brkm_lsu_mon_s lsu2tdu_d_mon; // Data monitor
+logic [SCR1_TDU_ALLTRIG_NUM-1:0] tdu2exu_i_match; // Instruction breakpoint(s) match
+logic [SCR1_TDU_MTRIG_NUM-1:0] tdu2lsu_d_match; // Data breakpoint(s) match
+logic tdu2exu_i_x_req; // Instruction breakpoint exception
+logic tdu2lsu_i_x_req; // Instruction breakpoint exception
+logic tdu2lsu_d_x_req; // Data breakpoint exception
+logic [SCR1_TDU_ALLTRIG_NUM-1:0] exu2tdu_bp_retire; // Instruction with breakpoint flag retire
+ `ifdef SCR1_DBG_EN
+ // Qualified TDU input signals from pipe_rst_n
+ // reset domain:
+type_scr1_brkm_instr_mon_s exu2tdu_i_mon_qlfy; // Instruction monitor
+type_scr1_brkm_lsu_mon_s lsu2tdu_d_mon_qlfy; // Data monitor
+logic [SCR1_TDU_ALLTRIG_NUM-1:0] exu2tdu_bp_retire_qlfy; // Instruction with breakpoint flag retire
+ `endif // SCR1_DBG_EN
+`endif // SCR1_TDU_EN
+
+`ifdef SCR1_DBG_EN
+// Debug signals:
+logic fetch_pbuf; // Fetch instructions provided by Program Buffer (via HDU)
+logic csr2hdu_req; // Request to HDU
+type_scr1_csr_cmd_sel_e csr2hdu_cmd; // HDU command
+logic [SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0] csr2hdu_addr; // HDU address
+logic [`SCR1_XLEN-1:0] csr2hdu_wdata; // HDU write data
+logic [`SCR1_XLEN-1:0] hdu2csr_rdata; // HDU read data
+type_scr1_csr_resp_e hdu2csr_resp; // HDU response
+ // Qualified HDU input signals from pipe_rst_n
+ // reset domain:
+logic csr2hdu_req_qlfy; // Request to HDU
+
+logic hwbrk_dsbl; // Disables TDU
+logic hdu_hwbrk_dsbl; // Disables TDU
+logic tdu2hdu_dmode_req; // TDU requests transition to debug mode
+
+logic exu_no_commit; // Forbid instruction commitment
+logic exu_irq_dsbl; // Disable IRQ
+logic exu_pc_advmt_dsbl; // Forbid PC advancement
+logic exu_dmode_sstep_en; // Enable single-step
+
+logic dbg_halted; // Debug halted state
+logic dbg_run2halt; // Transition to debug halted state
+logic dbg_halt2run; // Transition to run state
+logic dbg_run_start; // First cycle of run state
+logic [`SCR1_XLEN-1:0] dbg_new_pc; // New PC as starting point for HART Resume
+
+logic ifu2hdu_pbuf_rdy;
+logic hdu2ifu_pbuf_vd;
+logic hdu2ifu_pbuf_err;
+logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr;
+
+// Qualified HDU input signals from pipe_rst_n reset domain:
+logic ifu2hdu_pbuf_rdy_qlfy;
+logic exu_busy_qlfy;
+logic instret_qlfy;
+logic exu_init_pc_qlfy;
+logic exu_exc_req_qlfy;
+logic brkpt_qlfy;
+
+`endif // SCR1_DBG_EN
+
+logic exu_busy;
+
+
+`ifndef SCR1_CLKCTRL_EN
+logic pipe2clkctl_wake_req_o;
+`endif // SCR1_CLKCTRL_EN
+
+//-------------------------------------------------------------------------------
+// Pipeline logic
+//-------------------------------------------------------------------------------
+assign stop_fetch = wfi_run2halt
+`ifdef SCR1_DBG_EN
+ | fetch_pbuf
+`endif // SCR1_DBG_EN
+ ;
+
+`ifdef SCR1_CLKCTRL_EN
+assign pipe2clkctl_sleep_req_o = wfi_halted & ~imem_txns_pending;
+assign pipe2clkctl_wake_req_o = csr2exu_ip_ie
+`ifdef SCR1_DBG_EN
+ | dm2pipe_active_i
+`endif // SCR1_DBG_EN
+ ;
+`endif // SCR1_CLKCTRL_EN
+
+`ifdef SCR1_DBG_EN
+assign pipe2dm_pc_sample_o = curr_pc;
+`endif // SCR1_DBG_EN
+
+//-------------------------------------------------------------------------------
+// Instruction fetch unit
+//-------------------------------------------------------------------------------
+scr1_pipe_ifu i_pipe_ifu (
+ .rst_n (pipe_rst_n ),
+ .clk (clk ),
+
+ // Instruction memory interface
+ .imem2ifu_req_ack_i (imem2pipe_req_ack_i),
+ .ifu2imem_req_o (pipe2imem_req_o ),
+ .ifu2imem_cmd_o (pipe2imem_cmd_o ),
+ .ifu2imem_addr_o (pipe2imem_addr_o ),
+ .imem2ifu_rdata_i (imem2pipe_rdata_i ),
+ .imem2ifu_resp_i (imem2pipe_resp_i ),
+
+ // New PC interface
+ .exu2ifu_pc_new_req_i (new_pc_req ),
+ .exu2ifu_pc_new_i (new_pc ),
+ .pipe2ifu_stop_fetch_i (stop_fetch ),
+
+`ifdef SCR1_DBG_EN
+ // IFU <-> HDU Program Buffer interface
+ .hdu2ifu_pbuf_fetch_i (fetch_pbuf ),
+ .ifu2hdu_pbuf_rdy_o (ifu2hdu_pbuf_rdy ),
+ .hdu2ifu_pbuf_vd_i (hdu2ifu_pbuf_vd ),
+ .hdu2ifu_pbuf_err_i (hdu2ifu_pbuf_err ),
+ .hdu2ifu_pbuf_instr_i (hdu2ifu_pbuf_instr ),
+`endif // SCR1_DBG_EN
+`ifdef SCR1_CLKCTRL_EN
+ .ifu2pipe_imem_txns_pnd_o (imem_txns_pending ),
+`endif // SCR1_CLKCTRL_EN
+
+ // IFU <-> IDU interface
+ .idu2ifu_rdy_i (idu2ifu_rdy ),
+ .ifu2idu_instr_o (ifu2idu_instr ),
+ .ifu2idu_imem_err_o (ifu2idu_imem_err ),
+ .ifu2idu_err_rvi_hi_o (ifu2idu_err_rvi_hi ),
+ .ifu2idu_vd_o (ifu2idu_vd )
+);
+
+//-------------------------------------------------------------------------------
+// Instruction decode unit
+//-------------------------------------------------------------------------------
+scr1_pipe_idu i_pipe_idu (
+`ifdef SCR1_TRGT_SIMULATION
+ .rst_n (pipe_rst_n ),
+ .clk (clk ),
+`endif // SCR1_TRGT_SIMULATION
+ .idu2ifu_rdy_o (idu2ifu_rdy ),
+ .ifu2idu_instr_i (ifu2idu_instr ),
+ .ifu2idu_imem_err_i (ifu2idu_imem_err ),
+ .ifu2idu_err_rvi_hi_i (ifu2idu_err_rvi_hi),
+ .ifu2idu_vd_i (ifu2idu_vd ),
+
+ .idu2exu_req_o (idu2exu_req ),
+ .idu2exu_cmd_o (idu2exu_cmd ),
+ .idu2exu_use_rs1_o (idu2exu_use_rs1 ),
+ .idu2exu_use_rs2_o (idu2exu_use_rs2 ),
+ .idu2exu_use_rd_o (idu2exu_use_rd ),
+ .idu2exu_use_imm_o (idu2exu_use_imm ),
+ .exu2idu_rdy_i (exu2idu_rdy )
+);
+
+//-------------------------------------------------------------------------------
+// Execution unit
+//-------------------------------------------------------------------------------
+scr1_pipe_exu i_pipe_exu (
+ .rst_n (pipe_rst_n ),
+ .clk (clk ),
+`ifdef SCR1_CLKCTRL_EN
+ .clk_alw_on (clkctl2pipe_clk_alw_on_i),
+ .clk_pipe_en (clkctl2pipe_clk_en_i),
+`endif // SCR1_CLKCTRL_EN
+
+ // IDU <-> EXU interface
+ .idu2exu_req_i (idu2exu_req ),
+ .exu2idu_rdy_o (exu2idu_rdy ),
+ .idu2exu_cmd_i (idu2exu_cmd ),
+ .idu2exu_use_rs1_i (idu2exu_use_rs1 ),
+ .idu2exu_use_rs2_i (idu2exu_use_rs2 ),
+`ifndef SCR1_NO_EXE_STAGE
+ .idu2exu_use_rd_i (idu2exu_use_rd ),
+ .idu2exu_use_imm_i (idu2exu_use_imm ),
+`endif // SCR1_NO_EXE_STAGE
+
+ // EXU <-> MPRF interface
+ .exu2mprf_rs1_addr_o (exu2mprf_rs1_addr ),
+ .mprf2exu_rs1_data_i (mprf2exu_rs1_data ),
+ .exu2mprf_rs2_addr_o (exu2mprf_rs2_addr ),
+ .mprf2exu_rs2_data_i (mprf2exu_rs2_data ),
+ .exu2mprf_w_req_o (exu2mprf_w_req ),
+ .exu2mprf_rd_addr_o (exu2mprf_rd_addr ),
+ .exu2mprf_rd_data_o (exu2mprf_rd_data ),
+
+ // EXU <-> CSR read/write interface
+ .exu2csr_rw_addr_o (exu2csr_rw_addr ),
+ .exu2csr_r_req_o (exu2csr_r_req ),
+ .csr2exu_r_data_i (csr2exu_r_data ),
+ .exu2csr_w_req_o (exu2csr_w_req ),
+ .exu2csr_w_cmd_o (exu2csr_w_cmd ),
+ .exu2csr_w_data_o (exu2csr_w_data ),
+ .csr2exu_rw_exc_i (csr2exu_rw_exc ),
+
+ // EXU <-> CSR event interface
+ .exu2csr_take_irq_o (exu2csr_take_irq ),
+ .exu2csr_take_exc_o (exu2csr_take_exc ),
+ .exu2csr_mret_update_o (exu2csr_mret_update ),
+ .exu2csr_mret_instr_o (exu2csr_mret_instr ),
+ .exu2csr_exc_code_o (exu2csr_exc_code ),
+ .exu2csr_trap_val_o (exu2csr_trap_val ),
+ .csr2exu_new_pc_i (csr2exu_new_pc ),
+ .csr2exu_irq_i (csr2exu_irq ),
+ .csr2exu_ip_ie_i (csr2exu_ip_ie ),
+ .csr2exu_mstatus_mie_up_i (csr2exu_mstatus_mie_up ),
+
+ // EXU <-> DMEM interface
+ .exu2dmem_req_o (pipe2dmem_req_o ),
+ .exu2dmem_cmd_o (pipe2dmem_cmd_o ),
+ .exu2dmem_width_o (pipe2dmem_width_o ),
+ .exu2dmem_addr_o (pipe2dmem_addr_o ),
+ .exu2dmem_wdata_o (pipe2dmem_wdata_o ),
+ .dmem2exu_req_ack_i (dmem2pipe_req_ack_i ),
+ .dmem2exu_rdata_i (dmem2pipe_rdata_i ),
+ .dmem2exu_resp_i (dmem2pipe_resp_i ),
+
+`ifdef SCR1_DBG_EN
+ // EXU <-> HDU interface
+ .hdu2exu_no_commit_i (exu_no_commit ),
+ .hdu2exu_irq_dsbl_i (exu_irq_dsbl ),
+ .hdu2exu_pc_advmt_dsbl_i (exu_pc_advmt_dsbl ),
+ .hdu2exu_dmode_sstep_en_i (exu_dmode_sstep_en ),
+ .hdu2exu_pbuf_fetch_i (fetch_pbuf ),
+ .hdu2exu_dbg_halted_i (dbg_halted ),
+ .hdu2exu_dbg_run2halt_i (dbg_run2halt ),
+ .hdu2exu_dbg_halt2run_i (dbg_halt2run ),
+ .hdu2exu_dbg_run_start_i (dbg_run_start ),
+ .hdu2exu_dbg_new_pc_i (dbg_new_pc ),
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+ // EXU <-> TDU interface
+ .exu2tdu_imon_o (exu2tdu_i_mon ),
+ .tdu2exu_ibrkpt_match_i (tdu2exu_i_match ),
+ .tdu2exu_ibrkpt_exc_req_i (tdu2exu_i_x_req ),
+ .lsu2tdu_dmon_o (lsu2tdu_d_mon ),
+ .tdu2lsu_ibrkpt_exc_req_i (tdu2lsu_i_x_req ),
+ .tdu2lsu_dbrkpt_match_i (tdu2lsu_d_match ),
+ .tdu2lsu_dbrkpt_exc_req_i (tdu2lsu_d_x_req ),
+ .exu2tdu_ibrkpt_ret_o (exu2tdu_bp_retire ),
+ .exu2hdu_ibrkpt_hw_o (brkpt_hw ),
+`endif // SCR1_TDU_EN
+
+ // EXU control
+ .exu2pipe_exc_req_o (exu_exc_req ),
+ .exu2pipe_brkpt_o (brkpt ),
+ .exu2pipe_init_pc_o (exu_init_pc ),
+ .exu2pipe_wfi_run2halt_o (wfi_run2halt ),
+ .exu2pipe_instret_o (instret ),
+ .exu2csr_instret_no_exc_o (instret_nexc ),
+ .exu2pipe_exu_busy_o (exu_busy ),
+
+ // PC interface
+`ifdef SCR1_CLKCTRL_EN
+ .exu2pipe_wfi_halted_o (wfi_halted ),
+`endif // SCR1_CLKCTRL_EN
+ .exu2pipe_pc_curr_o (curr_pc ),
+ .exu2csr_pc_next_o (next_pc ),
+ .exu2ifu_pc_new_req_o (new_pc_req ),
+ .exu2ifu_pc_new_o (new_pc )
+);
+
+//-------------------------------------------------------------------------------
+// Multi-port register file
+//-------------------------------------------------------------------------------
+scr1_pipe_mprf i_pipe_mprf (
+`ifdef SCR1_MPRF_RST_EN
+ .rst_n (pipe_rst_n ),
+`endif // SCR1_MPRF_RST_EN
+ .clk (clk ),
+
+ // EXU <-> MPRF interface
+ .exu2mprf_rs1_addr_i (exu2mprf_rs1_addr),
+ .mprf2exu_rs1_data_o (mprf2exu_rs1_data),
+ .exu2mprf_rs2_addr_i (exu2mprf_rs2_addr),
+ .mprf2exu_rs2_data_o (mprf2exu_rs2_data),
+ .exu2mprf_w_req_i (exu2mprf_w_req ),
+ .exu2mprf_rd_addr_i (exu2mprf_rd_addr ),
+ .exu2mprf_rd_data_i (exu2mprf_rd_data )
+);
+
+//-------------------------------------------------------------------------------
+// Control and status registers
+//-------------------------------------------------------------------------------
+scr1_pipe_csr i_pipe_csr (
+ .rst_n (pipe_rst_n ),
+ .clk (clk ),
+`ifdef SCR1_CLKCTRL_EN
+ .clk_alw_on (clkctl2pipe_clk_alw_on_i),
+`endif // SCR1_CLKCTRL_EN
+
+ // EXU <-> CSR read/write interface
+ .exu2csr_r_req_i (exu2csr_r_req ),
+ .exu2csr_rw_addr_i (exu2csr_rw_addr ),
+ .csr2exu_r_data_o (csr2exu_r_data ),
+ .exu2csr_w_req_i (exu2csr_w_req ),
+ .exu2csr_w_cmd_i (exu2csr_w_cmd ),
+ .exu2csr_w_data_i (exu2csr_w_data ),
+ .csr2exu_rw_exc_o (csr2exu_rw_exc ),
+
+ // EXU <-> CSR event interface
+ .exu2csr_take_irq_i (exu2csr_take_irq ),
+ .exu2csr_take_exc_i (exu2csr_take_exc ),
+ .exu2csr_mret_update_i (exu2csr_mret_update ),
+ .exu2csr_mret_instr_i (exu2csr_mret_instr ),
+ .exu2csr_exc_code_i (exu2csr_exc_code ),
+ .exu2csr_trap_val_i (exu2csr_trap_val ),
+ .csr2exu_new_pc_o (csr2exu_new_pc ),
+ .csr2exu_irq_o (csr2exu_irq ),
+ .csr2exu_ip_ie_o (csr2exu_ip_ie ),
+ .csr2exu_mstatus_mie_up_o (csr2exu_mstatus_mie_up ),
+
+`ifdef SCR1_IPIC_EN
+ // CSR <-> IPIC interface
+ .csr2ipic_r_req_o (csr2ipic_r_req ),
+ .csr2ipic_w_req_o (csr2ipic_w_req ),
+ .csr2ipic_addr_o (csr2ipic_addr ),
+ .csr2ipic_wdata_o (csr2ipic_wdata ),
+ .ipic2csr_rdata_i (ipic2csr_rdata ),
+`endif // SCR1_IPIC_EN
+
+ // CSR <-> PC interface
+ .exu2csr_pc_curr_i (curr_pc ),
+ .exu2csr_pc_next_i (next_pc ),
+`ifndef SCR1_CSR_REDUCED_CNT
+ .exu2csr_instret_no_exc_i (instret_nexc ),
+`endif // SCR1_CSR_REDUCED_CNT
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ .soc2csr_irq_ext_i (ipic2csr_irq ),
+`else // SCR1_IPIC_EN
+ .soc2csr_irq_ext_i (soc2pipe_irq_ext_i ),
+`endif // SCR1_IPIC_EN
+ .soc2csr_irq_soft_i (soc2pipe_irq_soft_i ),
+ .soc2csr_irq_mtimer_i (soc2pipe_irq_mtimer_i ),
+
+ // Memory-mapped external timer
+ .soc2csr_mtimer_val_i (soc2pipe_mtimer_val_i ),
+
+`ifdef SCR1_DBG_EN
+ // CSR <-> HDU interface
+ .csr2hdu_req_o (csr2hdu_req ),
+ .csr2hdu_cmd_o (csr2hdu_cmd ),
+ .csr2hdu_addr_o (csr2hdu_addr ),
+ .csr2hdu_wdata_o (csr2hdu_wdata ),
+ .hdu2csr_rdata_i (hdu2csr_rdata ),
+ .hdu2csr_resp_i (hdu2csr_resp ),
+ .hdu2csr_no_commit_i (exu_no_commit ),
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TDU_EN
+ // CSR <-> TDU interface
+ .csr2tdu_req_o (csr2tdu_req ),
+ .csr2tdu_cmd_o (csr2tdu_cmd ),
+ .csr2tdu_addr_o (csr2tdu_addr ),
+ .csr2tdu_wdata_o (csr2tdu_wdata ),
+ .tdu2csr_rdata_i (tdu2csr_rdata ),
+ .tdu2csr_resp_i (tdu2csr_resp ),
+`endif // SCR1_TDU_EN
+ .soc2csr_fuse_mhartid_i (soc2pipe_fuse_mhartid_i )
+);
+
+//-------------------------------------------------------------------------------
+// Integrated programmable interrupt controller
+//-------------------------------------------------------------------------------
+`ifdef SCR1_IPIC_EN
+scr1_ipic i_pipe_ipic (
+ .rst_n (pipe_rst_n ),
+`ifdef SCR1_CLKCTRL_EN
+ .clk (clkctl2pipe_clk_alw_on_i),
+`else // SCR1_CLKCTRL_EN
+ .clk (clk ),
+`endif // SCR1_CLKCTRL_EN
+ .soc2ipic_irq_lines_i (soc2pipe_irq_lines_i ),
+ .csr2ipic_r_req_i (csr2ipic_r_req ),
+ .csr2ipic_w_req_i (csr2ipic_w_req ),
+ .csr2ipic_addr_i (csr2ipic_addr ),
+ .csr2ipic_wdata_i (csr2ipic_wdata ),
+ .ipic2csr_rdata_o (ipic2csr_rdata ),
+ .ipic2csr_irq_m_req_o (ipic2csr_irq )
+);
+`endif // SCR1_IPIC_EN
+
+//-------------------------------------------------------------------------------
+// Breakpoint module
+//-------------------------------------------------------------------------------
+`ifdef SCR1_TDU_EN
+scr1_pipe_tdu i_pipe_tdu (
+ // Common signals
+ `ifdef SCR1_DBG_EN
+ .rst_n (dbg_rst_n ),
+ `else
+ .rst_n (rst_n ),
+ `endif // SCR1_DBG_EN
+ .clk (clk ),
+ .clk_en (1'b1 ),
+ `ifdef SCR1_DBG_EN
+ .tdu_dsbl_i (hwbrk_dsbl ),
+ `else // SCR1_DBG_EN
+ .tdu_dsbl_i (1'b0 ),
+ `endif // SCR1_DBG_EN
+
+ // TDU <-> CSR interface
+ `ifdef SCR1_DBG_EN
+ .csr2tdu_req_i (csr2tdu_req_qlfy ),
+ .csr2tdu_cmd_i (csr2tdu_cmd ),
+ .csr2tdu_addr_i (csr2tdu_addr ),
+ .csr2tdu_wdata_i (csr2tdu_wdata ),
+ `else // SCR1_DBG_EN
+ .csr2tdu_req_i (csr2tdu_req ),
+ .csr2tdu_cmd_i (csr2tdu_cmd ),
+ .csr2tdu_addr_i (csr2tdu_addr ),
+ .csr2tdu_wdata_i (csr2tdu_wdata ),
+ `endif // SCR1_DBG_EN
+ .tdu2csr_rdata_o (tdu2csr_rdata ),
+ .tdu2csr_resp_o (tdu2csr_resp ),
+
+ // TDU <-> EXU interface
+ `ifdef SCR1_DBG_EN
+ .exu2tdu_imon_i (exu2tdu_i_mon_qlfy ),
+ `else // SCR1_DBG_EN
+ .exu2tdu_imon_i (exu2tdu_i_mon ),
+ `endif // SCR1_DBG_EN
+ .tdu2exu_ibrkpt_match_o (tdu2exu_i_match ),
+ .tdu2exu_ibrkpt_exc_req_o (tdu2exu_i_x_req ),
+ `ifdef SCR1_DBG_EN
+ .exu2tdu_bp_retire_i (exu2tdu_bp_retire_qlfy),
+ `else // SCR1_DBG_EN
+ .exu2tdu_bp_retire_i (exu2tdu_bp_retire ),
+ `endif // SCR1_DBG_EN
+
+ // TDU <-> LSU interface
+ .tdu2lsu_ibrkpt_exc_req_o (tdu2lsu_i_x_req ),
+ `ifdef SCR1_DBG_EN
+ .lsu2tdu_dmon_i (lsu2tdu_d_mon_qlfy ),
+ `else // SCR1_DBG_EN
+ .lsu2tdu_dmon_i (lsu2tdu_d_mon ),
+ `endif // SCR1_DBG_EN
+ .tdu2lsu_dbrkpt_match_o (tdu2lsu_d_match ),
+ .tdu2lsu_dbrkpt_exc_req_o (tdu2lsu_d_x_req ),
+ // EPU I/F
+ `ifdef SCR1_DBG_EN
+ .tdu2hdu_dmode_req_o (tdu2hdu_dmode_req )
+ `else // SCR1_DBG_EN
+ .tdu2hdu_dmode_req_o ( )
+ `endif // SCR1_DBG_EN
+);
+
+ `ifdef SCR1_DBG_EN
+assign hwbrk_dsbl = (~dbg_en) | hdu_hwbrk_dsbl;
+//
+assign csr2tdu_req_qlfy = dbg_en & csr2tdu_req & pipe2hdu_rdc_qlfy_i;
+//
+assign exu2tdu_i_mon_qlfy.vd = exu2tdu_i_mon.vd & pipe2hdu_rdc_qlfy_i;
+assign exu2tdu_i_mon_qlfy.req = exu2tdu_i_mon.req;
+assign exu2tdu_i_mon_qlfy.addr = exu2tdu_i_mon.addr;
+assign lsu2tdu_d_mon_qlfy.vd = lsu2tdu_d_mon.vd & pipe2hdu_rdc_qlfy_i;
+assign lsu2tdu_d_mon_qlfy.load = lsu2tdu_d_mon.load;
+assign lsu2tdu_d_mon_qlfy.store = lsu2tdu_d_mon.store;
+assign lsu2tdu_d_mon_qlfy.addr = lsu2tdu_d_mon.addr;
+assign exu2tdu_bp_retire_qlfy = exu2tdu_bp_retire & {$bits(exu2tdu_bp_retire){pipe2hdu_rdc_qlfy_i}};
+ `endif // SCR1_DBG_EN
+
+`endif // SCR1_TDU_EN
+
+//-------------------------------------------------------------------------------
+// HART Debug Unit (HDU)
+//-------------------------------------------------------------------------------
+`ifdef SCR1_DBG_EN
+scr1_pipe_hdu i_pipe_hdu (
+ // Common signals
+ .rst_n (dbg_rst_n ),
+ .clk_en (dm2pipe_active_i ),
+`ifdef SCR1_CLKCTRL_EN
+ .clk_pipe_en (clkctl2pipe_clk_en_i ),
+ .clk (clkctl2pipe_clk_dbgc_i),
+`else
+ .clk (clk ),
+`endif // SCR1_CLKCTRL_EN
+
+ // Control/status registers i/f
+ .csr2hdu_req_i (csr2hdu_req_qlfy ),
+ .csr2hdu_cmd_i (csr2hdu_cmd ),
+ .csr2hdu_addr_i (csr2hdu_addr ),
+ .csr2hdu_wdata_i (csr2hdu_wdata ),
+ .hdu2csr_resp_o (hdu2csr_resp ),
+ .hdu2csr_rdata_o (hdu2csr_rdata ),
+
+ // HART Run Control i/f
+ .pipe2hdu_rdc_qlfy_i (pipe2hdu_rdc_qlfy_i ),
+ .dm2hdu_cmd_req_i (dm2pipe_cmd_req_i ),
+ .dm2hdu_cmd_i (dm2pipe_cmd_i ),
+ .hdu2dm_cmd_resp_o (pipe2dm_cmd_resp_o ),
+ .hdu2dm_cmd_rcode_o (pipe2dm_cmd_rcode_o ),
+ .hdu2dm_hart_event_o (pipe2dm_hart_event_o ),
+ .hdu2dm_hart_status_o (pipe2dm_hart_status_o ),
+
+ // Program Buffer - HART instruction execution i/f
+ .hdu2dm_pbuf_addr_o (pipe2dm_pbuf_addr_o ),
+ .dm2hdu_pbuf_instr_i (dm2pipe_pbuf_instr_i ),
+
+ // HART Abstract Data regs i/f
+ .hdu2dm_dreg_req_o (pipe2dm_dreg_req_o ),
+ .hdu2dm_dreg_wr_o (pipe2dm_dreg_wr_o ),
+ .hdu2dm_dreg_wdata_o (pipe2dm_dreg_wdata_o ),
+ .dm2hdu_dreg_resp_i (dm2pipe_dreg_resp_i ),
+ .dm2hdu_dreg_fail_i (dm2pipe_dreg_fail_i ),
+ .dm2hdu_dreg_rdata_i (dm2pipe_dreg_rdata_i ),
+ //
+`ifdef SCR1_TDU_EN
+ // HDU <-> TDU interface
+ .hdu2tdu_hwbrk_dsbl_o (hdu_hwbrk_dsbl ),
+ .tdu2hdu_dmode_req_i (tdu2hdu_dmode_req ),
+ .exu2hdu_ibrkpt_hw_i (brkpt_hw ),
+`endif // SCR1_TDU_EN
+
+ // HART Run Status
+ .pipe2hdu_exu_busy_i (exu_busy_qlfy ),
+ .pipe2hdu_instret_i (instret_qlfy ),
+ .pipe2hdu_init_pc_i (exu_init_pc_qlfy ),
+
+ // HART Halt Status
+ .pipe2hdu_exu_exc_req_i (exu_exc_req_qlfy ),
+ .pipe2hdu_brkpt_i (brkpt_qlfy ),
+
+ // HART Run Control
+ .hdu2exu_pbuf_fetch_o (fetch_pbuf ),
+ .hdu2exu_no_commit_o (exu_no_commit ),
+ .hdu2exu_irq_dsbl_o (exu_irq_dsbl ),
+ .hdu2exu_pc_advmt_dsbl_o (exu_pc_advmt_dsbl ),
+ .hdu2exu_dmode_sstep_en_o (exu_dmode_sstep_en ),
+
+ // HART state
+ .hdu2exu_dbg_halted_o (dbg_halted ),
+ .hdu2exu_dbg_run2halt_o (dbg_run2halt ),
+ .hdu2exu_dbg_halt2run_o (dbg_halt2run ),
+ .hdu2exu_dbg_run_start_o (dbg_run_start ),
+
+ // PC interface
+ .pipe2hdu_pc_curr_i (curr_pc ),
+ .hdu2exu_dbg_new_pc_o (dbg_new_pc ),
+
+ // Prgram Buffer Instruction interface
+ .ifu2hdu_pbuf_instr_rdy_i (ifu2hdu_pbuf_rdy_qlfy ),
+ .hdu2ifu_pbuf_instr_vd_o (hdu2ifu_pbuf_vd ),
+ .hdu2ifu_pbuf_instr_err_o (hdu2ifu_pbuf_err ),
+ .hdu2ifu_pbuf_instr_o (hdu2ifu_pbuf_instr )
+);
+
+assign csr2hdu_req_qlfy = csr2hdu_req & dbg_en & pipe2hdu_rdc_qlfy_i;
+//
+assign exu_busy_qlfy = exu_busy & {$bits(exu_busy){pipe2hdu_rdc_qlfy_i}};
+assign instret_qlfy = instret & {$bits(instret){pipe2hdu_rdc_qlfy_i}};
+assign exu_init_pc_qlfy = exu_init_pc & {$bits(exu_init_pc){pipe2hdu_rdc_qlfy_i}};
+assign exu_exc_req_qlfy = exu_exc_req & {$bits(exu_exc_req){pipe2hdu_rdc_qlfy_i}};
+assign brkpt_qlfy = brkpt & {$bits(brkpt){pipe2hdu_rdc_qlfy_i}};
+assign ifu2hdu_pbuf_rdy_qlfy = ifu2hdu_pbuf_rdy & {$bits(ifu2hdu_pbuf_rdy){pipe2hdu_rdc_qlfy_i}};
+
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Tracelog
+//-------------------------------------------------------------------------------
+
+scr1_tracelog i_tracelog (
+ .rst_n (pipe_rst_n ),
+ .clk (clk ),
+ .soc2pipe_fuse_mhartid_i (soc2pipe_fuse_mhartid_i ),
+
+ // MPRF
+ .mprf2trace_int_i (i_pipe_mprf.mprf_int ),
+ .mprf2trace_wr_en_i (i_pipe_mprf.exu2mprf_w_req_i ),
+ .mprf2trace_wr_addr_i (i_pipe_mprf.exu2mprf_rd_addr_i ),
+ .mprf2trace_wr_data_i (i_pipe_mprf.exu2mprf_rd_data_i ),
+
+ // EXU
+ .exu2trace_update_pc_en_i (i_pipe_exu.update_pc_en ),
+ .exu2trace_update_pc_i (i_pipe_exu.update_pc ),
+
+ // IFU
+ .ifu2trace_instr_i (i_pipe_ifu.ifu2idu_instr_o ),
+
+ // CSR
+ .csr2trace_mstatus_mie_i (i_pipe_csr.csr_mstatus_mie_ff ),
+ .csr2trace_mstatus_mpie_i (i_pipe_csr.csr_mstatus_mpie_ff ),
+ .csr2trace_mtvec_base_i (i_pipe_csr.csr_mtvec_base ),
+ .csr2trace_mtvec_mode_i (i_pipe_csr.csr_mtvec_mode ),
+ .csr2trace_mie_meie_i (i_pipe_csr.csr_mie_meie_ff ),
+ .csr2trace_mie_mtie_i (i_pipe_csr.csr_mie_mtie_ff ),
+ .csr2trace_mie_msie_i (i_pipe_csr.csr_mie_msie_ff ),
+ .csr2trace_mip_meip_i (i_pipe_csr.csr_mip_meip ),
+ .csr2trace_mip_mtip_i (i_pipe_csr.csr_mip_mtip ),
+ .csr2trace_mip_msip_i (i_pipe_csr.csr_mip_msip ),
+ .csr2trace_mepc_i (i_pipe_csr.csr_mepc_ff ),
+ .csr2trace_mcause_irq_i (i_pipe_csr.csr_mcause_i_ff ),
+ .csr2trace_mcause_ec_i (i_pipe_csr.csr_mcause_ec_ff ),
+ .csr2trace_mtval_i (i_pipe_csr.csr_mtval_ff ),
+ .csr2trace_mstatus_mie_up_i (i_pipe_csr.csr2exu_mstatus_mie_up_o),
+
+ // Events
+ .csr2trace_e_exc_i (i_pipe_csr.e_exc ),
+ .csr2trace_e_irq_i (i_pipe_csr.e_irq ),
+ .pipe2trace_e_wake_i (pipe2clkctl_wake_req_o ),
+ .csr2trace_e_mret_i (i_pipe_csr.e_mret )
+);
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_pipe_top
diff --git a/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_tracelog.sv b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_tracelog.sv
new file mode 100644
index 0000000..1d86001
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/pipeline/scr1_tracelog.sv
@@ -0,0 +1,455 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_tracelog.sv>
+/// @brief Core tracelog module
+///
+
+`include "scr1_arch_description.svh"
+`include "scr1_arch_types.svh"
+`include "scr1_csr.svh"
+
+`ifdef SCR1_TRGT_SIMULATION
+
+module scr1_tracelog (
+ input logic rst_n, // Tracelog reset
+ input logic clk, // Tracelog clock
+ input logic [`SCR1_XLEN-1:0] soc2pipe_fuse_mhartid_i, // Fuse MHARTID
+
+ // MPRF
+`ifdef SCR1_MPRF_RAM
+ input logic [`SCR1_XLEN-1:0] mprf2trace_int_i [1:`SCR1_MPRF_SIZE-1], // MPRF registers content
+`else // SCR1_MPRF_RAM
+ input type_scr1_mprf_v [1:`SCR1_MPRF_SIZE-1] mprf2trace_int_i, // MPRF registers content
+`endif // SCR1_MPRF_RAM
+ input logic mprf2trace_wr_en_i, // MPRF write enable
+ input logic [`SCR1_MPRF_AWIDTH-1:0] mprf2trace_wr_addr_i, // MPRF write address
+ input logic [`SCR1_XLEN-1:0] mprf2trace_wr_data_i, // MPRF write data
+
+ // EXU
+ input logic exu2trace_update_pc_en_i, // PC updated flag
+ input logic [`SCR1_XLEN-1:0] exu2trace_update_pc_i, // Next PC value
+
+ // IFU
+ input logic [`SCR1_IMEM_DWIDTH-1:0] ifu2trace_instr_i, // Current instruction from IFU stage
+
+ // CSR
+ input logic csr2trace_mstatus_mie_i, // CSR MSTATUS.mie bit
+ input logic csr2trace_mstatus_mpie_i, // CSR MSTATUS.mpie bit
+ input logic [`SCR1_XLEN-1:6] csr2trace_mtvec_base_i, // CSR MTVEC.
+ input logic csr2trace_mtvec_mode_i, // CSR MTVEC.
+ input logic csr2trace_mie_meie_i, // CSR MIE.meie bit
+ input logic csr2trace_mie_mtie_i, // CSR MIE.mtie bit
+ input logic csr2trace_mie_msie_i, // CSR MIE.msie bit
+ input logic csr2trace_mip_meip_i, // CSR MIP.meip bit
+ input logic csr2trace_mip_mtip_i, // CSR MIP.mtip bit
+ input logic csr2trace_mip_msip_i, // CSR MIP.msip bit
+ `ifdef SCR1_RVC_EXT
+ input logic [`SCR1_XLEN-1:1] csr2trace_mepc_i, // CSR MEPC register
+ `else // SCR1_RVC_EXT
+ input logic [`SCR1_XLEN-1:2] csr2trace_mepc_i, // CSR MEPC register
+ `endif // SCR1_RVC_EXT
+ input logic csr2trace_mcause_irq_i, // CSR MCAUSE.interrupt bit
+ input type_scr1_exc_code_e csr2trace_mcause_ec_i, // CSR MCAUSE.exception_code bit
+ input logic [`SCR1_XLEN-1:0] csr2trace_mtval_i, // CSR MTVAL register
+ input logic csr2trace_mstatus_mie_up_i, // CSR MSTATUS.mie update flag
+
+ // Events
+ input logic csr2trace_e_exc_i, // exception event
+ input logic csr2trace_e_irq_i, // interrupt event
+ input logic pipe2trace_e_wake_i, // pipe wakeup event
+ input logic csr2trace_e_mret_i // MRET instruction
+);
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+typedef struct {
+ logic [`SCR1_XLEN-1:0] INT_00_ZERO ;
+ logic [`SCR1_XLEN-1:0] INT_01_RA ;
+ logic [`SCR1_XLEN-1:0] INT_02_SP ;
+ logic [`SCR1_XLEN-1:0] INT_03_GP ;
+ logic [`SCR1_XLEN-1:0] INT_04_TP ;
+ logic [`SCR1_XLEN-1:0] INT_05_T0 ;
+ logic [`SCR1_XLEN-1:0] INT_06_T1 ;
+ logic [`SCR1_XLEN-1:0] INT_07_T2 ;
+ logic [`SCR1_XLEN-1:0] INT_08_S0 ;
+ logic [`SCR1_XLEN-1:0] INT_09_S1 ;
+ logic [`SCR1_XLEN-1:0] INT_10_A0 ;
+ logic [`SCR1_XLEN-1:0] INT_11_A1 ;
+ logic [`SCR1_XLEN-1:0] INT_12_A2 ;
+ logic [`SCR1_XLEN-1:0] INT_13_A3 ;
+ logic [`SCR1_XLEN-1:0] INT_14_A4 ;
+ logic [`SCR1_XLEN-1:0] INT_15_A5 ;
+`ifndef SCR1_RVE_EXT
+ logic [`SCR1_XLEN-1:0] INT_16_A6 ;
+ logic [`SCR1_XLEN-1:0] INT_17_A7 ;
+ logic [`SCR1_XLEN-1:0] INT_18_S2 ;
+ logic [`SCR1_XLEN-1:0] INT_19_S3 ;
+ logic [`SCR1_XLEN-1:0] INT_20_S4 ;
+ logic [`SCR1_XLEN-1:0] INT_21_S5 ;
+ logic [`SCR1_XLEN-1:0] INT_22_S6 ;
+ logic [`SCR1_XLEN-1:0] INT_23_S7 ;
+ logic [`SCR1_XLEN-1:0] INT_24_S8 ;
+ logic [`SCR1_XLEN-1:0] INT_25_S9 ;
+ logic [`SCR1_XLEN-1:0] INT_26_S10 ;
+ logic [`SCR1_XLEN-1:0] INT_27_S11 ;
+ logic [`SCR1_XLEN-1:0] INT_28_T3 ;
+ logic [`SCR1_XLEN-1:0] INT_29_T4 ;
+ logic [`SCR1_XLEN-1:0] INT_30_T5 ;
+ logic [`SCR1_XLEN-1:0] INT_31_T6 ;
+`endif // SCR1_RVE_EXT
+} type_scr1_ireg_name_s;
+
+typedef struct packed {
+ logic [`SCR1_XLEN-1:0] mstatus;
+ logic [`SCR1_XLEN-1:0] mtvec;
+ logic [`SCR1_XLEN-1:0] mie;
+ logic [`SCR1_XLEN-1:0] mip;
+ logic [`SCR1_XLEN-1:0] mepc;
+ logic [`SCR1_XLEN-1:0] mcause;
+ logic [`SCR1_XLEN-1:0] mtval;
+} type_scr1_csr_trace_s;
+
+//-------------------------------------------------------------------------------
+// Local Signal Declaration
+//-------------------------------------------------------------------------------
+
+type_scr1_ireg_name_s mprf_int_alias;
+
+`ifdef SCR1_TRACE_LOG_EN
+
+time current_time;
+
+// Tracelog control signals
+logic trace_flag;
+logic trace_update;
+logic trace_update_r;
+byte event_type;
+
+logic [`SCR1_XLEN-1:0] trace_pc;
+logic [`SCR1_XLEN-1:0] trace_npc;
+logic [`SCR1_IMEM_DWIDTH-1:0] trace_instr;
+
+type_scr1_csr_trace_s csr_trace1;
+
+// File handlers
+int unsigned trace_fhandler_core;
+
+// MPRF signals
+logic mprf_up;
+logic [`SCR1_MPRF_AWIDTH-1:0] mprf_addr;
+logic [`SCR1_XLEN-1:0] mprf_wdata;
+
+string hart;
+string test_name;
+
+`endif // SCR1_TRACE_LOG_EN
+
+//-------------------------------------------------------------------------------
+// Local tasks
+//-------------------------------------------------------------------------------
+
+`ifdef SCR1_TRACE_LOG_EN
+
+task trace_write_common;
+ $fwrite(trace_fhandler_core, "%16d ", current_time);
+ // $fwrite(trace_fhandler_core, " 0 ");
+ $fwrite(trace_fhandler_core, " %s ", event_type);
+ $fwrite(trace_fhandler_core, " %8x ", trace_pc);
+ $fwrite(trace_fhandler_core, " %8x ", trace_instr);
+ $fwrite(trace_fhandler_core, " %8x ", trace_npc);
+endtask // trace_write_common
+
+task trace_write_int_walias;
+ case (mprf_addr)
+ 0 : $fwrite(trace_fhandler_core, " x00_zero ");
+ 1 : $fwrite(trace_fhandler_core, " x01_ra ");
+ 2 : $fwrite(trace_fhandler_core, " x02_sp ");
+ 3 : $fwrite(trace_fhandler_core, " x03_gp ");
+ 4 : $fwrite(trace_fhandler_core, " x04_tp ");
+ 5 : $fwrite(trace_fhandler_core, " x05_t0 ");
+ 6 : $fwrite(trace_fhandler_core, " x06_t1 ");
+ 7 : $fwrite(trace_fhandler_core, " x07_t2 ");
+ 8 : $fwrite(trace_fhandler_core, " x08_s0 ");
+ 9 : $fwrite(trace_fhandler_core, " x09_s1 ");
+ 10 : $fwrite(trace_fhandler_core, " x10_a0 ");
+ 11 : $fwrite(trace_fhandler_core, " x11_a1 ");
+ 12 : $fwrite(trace_fhandler_core, " x12_a2 ");
+ 13 : $fwrite(trace_fhandler_core, " x13_a3 ");
+ 14 : $fwrite(trace_fhandler_core, " x14_a4 ");
+ 15 : $fwrite(trace_fhandler_core, " x15_a5 ");
+`ifndef SCR1_RVE_EXT
+ 16 : $fwrite(trace_fhandler_core, " x16_a6 ");
+ 17 : $fwrite(trace_fhandler_core, " x17_a7 ");
+ 18 : $fwrite(trace_fhandler_core, " x18_s2 ");
+ 19 : $fwrite(trace_fhandler_core, " x19_s3 ");
+ 20 : $fwrite(trace_fhandler_core, " x20_s4 ");
+ 21 : $fwrite(trace_fhandler_core, " x21_s5 ");
+ 22 : $fwrite(trace_fhandler_core, " x22_s6 ");
+ 23 : $fwrite(trace_fhandler_core, " x23_s7 ");
+ 24 : $fwrite(trace_fhandler_core, " x24_s8 ");
+ 25 : $fwrite(trace_fhandler_core, " x25_s9 ");
+ 26 : $fwrite(trace_fhandler_core, " x26_s10 ");
+ 27 : $fwrite(trace_fhandler_core, " x27_s11 ");
+ 28 : $fwrite(trace_fhandler_core, " x28_t3 ");
+ 29 : $fwrite(trace_fhandler_core, " x29_t4 ");
+ 30 : $fwrite(trace_fhandler_core, " x30_t5 ");
+ 31 : $fwrite(trace_fhandler_core, " x31_t6 ");
+`endif // SCR1_RVE_EXT
+ default: begin
+ $fwrite(trace_fhandler_core, " xxx ");
+ end
+ endcase
+endtask
+
+`endif // SCR1_TRACE_LOG_EN
+
+//-------------------------------------------------------------------------------
+// MPRF Registers assignment
+//-------------------------------------------------------------------------------
+assign mprf_int_alias.INT_00_ZERO = '0;
+assign mprf_int_alias.INT_01_RA = mprf2trace_int_i[1];
+assign mprf_int_alias.INT_02_SP = mprf2trace_int_i[2];
+assign mprf_int_alias.INT_03_GP = mprf2trace_int_i[3];
+assign mprf_int_alias.INT_04_TP = mprf2trace_int_i[4];
+assign mprf_int_alias.INT_05_T0 = mprf2trace_int_i[5];
+assign mprf_int_alias.INT_06_T1 = mprf2trace_int_i[6];
+assign mprf_int_alias.INT_07_T2 = mprf2trace_int_i[7];
+assign mprf_int_alias.INT_08_S0 = mprf2trace_int_i[8];
+assign mprf_int_alias.INT_09_S1 = mprf2trace_int_i[9];
+assign mprf_int_alias.INT_10_A0 = mprf2trace_int_i[10];
+assign mprf_int_alias.INT_11_A1 = mprf2trace_int_i[11];
+assign mprf_int_alias.INT_12_A2 = mprf2trace_int_i[12];
+assign mprf_int_alias.INT_13_A3 = mprf2trace_int_i[13];
+assign mprf_int_alias.INT_14_A4 = mprf2trace_int_i[14];
+assign mprf_int_alias.INT_15_A5 = mprf2trace_int_i[15];
+`ifndef SCR1_RVE_EXT
+assign mprf_int_alias.INT_16_A6 = mprf2trace_int_i[16];
+assign mprf_int_alias.INT_17_A7 = mprf2trace_int_i[17];
+assign mprf_int_alias.INT_18_S2 = mprf2trace_int_i[18];
+assign mprf_int_alias.INT_19_S3 = mprf2trace_int_i[19];
+assign mprf_int_alias.INT_20_S4 = mprf2trace_int_i[20];
+assign mprf_int_alias.INT_21_S5 = mprf2trace_int_i[21];
+assign mprf_int_alias.INT_22_S6 = mprf2trace_int_i[22];
+assign mprf_int_alias.INT_23_S7 = mprf2trace_int_i[23];
+assign mprf_int_alias.INT_24_S8 = mprf2trace_int_i[24];
+assign mprf_int_alias.INT_25_S9 = mprf2trace_int_i[25];
+assign mprf_int_alias.INT_26_S10 = mprf2trace_int_i[26];
+assign mprf_int_alias.INT_27_S11 = mprf2trace_int_i[27];
+assign mprf_int_alias.INT_28_T3 = mprf2trace_int_i[28];
+assign mprf_int_alias.INT_29_T4 = mprf2trace_int_i[29];
+assign mprf_int_alias.INT_30_T5 = mprf2trace_int_i[30];
+assign mprf_int_alias.INT_31_T6 = mprf2trace_int_i[31];
+`endif // SCR1_RVE_EXT
+
+//-------------------------------------------------------------------------------
+// Legacy time counter
+//-------------------------------------------------------------------------------
+// The counter is left for compatibility with the current UVM environment
+
+int time_cnt;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ time_cnt <= 0;
+ end else begin
+ time_cnt <= time_cnt + 1;
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Initial part pipeline tracelog
+//-------------------------------------------------------------------------------
+
+`ifdef SCR1_TRACE_LOG_EN
+// Files opening and writing initial header
+initial begin
+ $timeformat(-9, 0, " ns", 10);
+ #1 hart.hextoa(soc2pipe_fuse_mhartid_i);
+
+ trace_fhandler_core = $fopen({"tracelog_core_", hart, ".log"}, "w");
+
+ // Writing initial header
+ $fwrite(trace_fhandler_core, "# RTL_ID %h\n", SCR1_CSR_MIMPID);
+ $fwrite(trace_fhandler_core, "#\n");
+ // $fwrite(trace_fhandler_core, "# R - return from trap:\n");
+ // $fwrite(trace_fhandler_core, "# 1 - MRET\n");
+ // $fwrite(trace_fhandler_core, "# 0 - no return\n");
+ $fwrite(trace_fhandler_core, "# Events:\n");
+ $fwrite(trace_fhandler_core, "# N - no event\n");
+ $fwrite(trace_fhandler_core, "# E - exception\n");
+ $fwrite(trace_fhandler_core, "# I - interrupt\n");
+ $fwrite(trace_fhandler_core, "# W - wakeup\n");
+end
+
+// Core reset logging and header printing
+always @(posedge rst_n) begin
+ $fwrite(trace_fhandler_core, "# =====================================================================================\n");
+`ifndef VERILATOR
+ $fwrite(trace_fhandler_core, "# %14t : Core Reset\n", $time());
+`else
+ $fwrite(trace_fhandler_core, "# : Core Reset\n");
+`endif
+ $fwrite(trace_fhandler_core, "# =====================================================================================\n");
+ $fwrite(trace_fhandler_core, "# Test: %s\n", test_name);
+ $fwrite(trace_fhandler_core, "# Time ");
+ // $fwrite(trace_fhandler_core, " R ");
+ $fwrite(trace_fhandler_core, " Ev ");
+ $fwrite(trace_fhandler_core, " Curr_PC ");
+ $fwrite(trace_fhandler_core, " Instr ");
+ $fwrite(trace_fhandler_core, " Next_PC ");
+ $fwrite(trace_fhandler_core, " Reg ");
+ $fwrite(trace_fhandler_core, " Value ");
+ $fwrite(trace_fhandler_core, "\n");
+ $fwrite(trace_fhandler_core, "# =====================================================================================\n");
+end
+
+//-------------------------------------------------------------------------------
+// Common trace part
+//-------------------------------------------------------------------------------
+
+assign trace_flag = 1'b1;
+assign trace_update = (exu2trace_update_pc_en_i | mprf2trace_wr_en_i) & trace_flag;
+
+always_ff @(posedge clk) begin
+ if (~rst_n) begin
+ current_time <= 0;
+ event_type <= "N";
+
+ trace_pc <= 'x;
+ trace_npc <= 'x;
+ trace_instr <= 'x;
+
+ trace_update_r <= 1'b0;
+
+ mprf_up <= '0;
+ mprf_addr <= '0;
+ mprf_wdata <= '0;
+ end else begin
+ trace_update_r <= trace_update;
+ if (trace_update) begin
+`ifdef VERILATOR
+ current_time <= time_cnt;
+`else
+ current_time <= $time();
+`endif
+ trace_pc <= trace_npc;
+ trace_npc <= exu2trace_update_pc_i;
+ trace_instr <= ifu2trace_instr_i;
+
+ if (csr2trace_e_exc_i) begin
+ // Exception
+ event_type <= "E";
+ end
+ else if (csr2trace_e_irq_i) begin
+ // IRQ
+ event_type <= "I";
+ end
+ else if (pipe2trace_e_wake_i) begin
+ // Wake
+ event_type <= "W";
+ end
+ // if (csr2trace_e_mret_i) begin
+ // // MRET
+ // event_type <= "R";
+ // end
+ else begin
+ // No event
+ event_type <= "N";
+ end
+ end
+
+ // Write log signals
+ mprf_up <= mprf2trace_wr_en_i;
+ mprf_addr <= mprf2trace_wr_en_i ? mprf2trace_wr_addr_i : 'x;
+ mprf_wdata <= mprf2trace_wr_en_i ? mprf2trace_wr_data_i : 'x;
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Core MPRF logging
+//-------------------------------------------------------------------------------
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ end else begin
+ if (trace_update_r) begin
+
+ trace_write_common();
+
+ case (event_type)
+ "W" : begin
+ // Wakeup
+ if (csr_trace1.mip & csr_trace1.mie) begin
+ $fwrite(trace_fhandler_core, " mip %08x\n", csr_trace1.mip );
+ trace_write_common();
+ $fwrite(trace_fhandler_core, " mie %08x", csr_trace1.mie );
+ end
+ end
+ "N" : begin
+ // Regular
+ if (mprf_up && mprf_addr != 0) begin
+ // $fwrite(trace_fhandler_core, " x%2d %08x", mprf_addr, mprf_wdata);
+ trace_write_int_walias();
+ $fwrite(trace_fhandler_core, " %08x", mprf_wdata);
+ end else begin
+ $fwrite(trace_fhandler_core, " --- --------");
+ end
+ end
+ "R" : begin
+ // MRET
+ $fwrite(trace_fhandler_core, " mstatus %08x", csr_trace1.mstatus);
+ end
+ "E", "I": begin
+ // IRQ/Exception
+ $fwrite(trace_fhandler_core, " mstatus %08x\n", csr_trace1.mstatus);
+ trace_write_common();
+ $fwrite(trace_fhandler_core, " mepc %08x\n", csr_trace1.mepc);
+ trace_write_common();
+ $fwrite(trace_fhandler_core, " mcause %08x\n", csr_trace1.mcause);
+ trace_write_common();
+ $fwrite(trace_fhandler_core, " mtval %08x", csr_trace1.mtval);
+ end
+ default : begin
+ $fwrite(trace_fhandler_core, "\n");
+ end
+ endcase
+ $fwrite(trace_fhandler_core, "\n");
+ end
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Core CSR logging
+//-------------------------------------------------------------------------------
+
+always_comb begin
+ csr_trace1.mtvec = {csr2trace_mtvec_base_i, 4'd0, 2'(csr2trace_mtvec_mode_i)};
+ csr_trace1.mepc =
+`ifdef SCR1_RVC_EXT
+ {csr2trace_mepc_i, 1'b0};
+`else // SCR1_RVC_EXT
+ {csr2trace_mepc_i, 2'b00};
+`endif // SCR1_RVC_EXT
+ csr_trace1.mcause = {csr2trace_mcause_irq_i, type_scr1_csr_mcause_ec_v'(csr2trace_mcause_ec_i)};
+ csr_trace1.mtval = csr2trace_mtval_i;
+
+ csr_trace1.mstatus = '0;
+ csr_trace1.mie = '0;
+ csr_trace1.mip = '0;
+
+ csr_trace1.mstatus[SCR1_CSR_MSTATUS_MIE_OFFSET] = csr2trace_mstatus_mie_i;
+ csr_trace1.mstatus[SCR1_CSR_MSTATUS_MPIE_OFFSET] = csr2trace_mstatus_mpie_i;
+ csr_trace1.mstatus[SCR1_CSR_MSTATUS_MPP_OFFSET+1:SCR1_CSR_MSTATUS_MPP_OFFSET] = SCR1_CSR_MSTATUS_MPP;
+ csr_trace1.mie[SCR1_CSR_MIE_MSIE_OFFSET] = csr2trace_mie_msie_i;
+ csr_trace1.mie[SCR1_CSR_MIE_MTIE_OFFSET] = csr2trace_mie_mtie_i;
+ csr_trace1.mie[SCR1_CSR_MIE_MEIE_OFFSET] = csr2trace_mie_meie_i;
+ csr_trace1.mip[SCR1_CSR_MIE_MSIE_OFFSET] = csr2trace_mip_msip_i;
+ csr_trace1.mip[SCR1_CSR_MIE_MTIE_OFFSET] = csr2trace_mip_mtip_i;
+ csr_trace1.mip[SCR1_CSR_MIE_MEIE_OFFSET] = csr2trace_mip_meip_i;
+end
+
+`endif // SCR1_TRACE_LOG_EN
+
+endmodule : scr1_tracelog
+
+`endif // SCR1_TRGT_SIMULATION
diff --git a/verilog/rtl/syntacore_scr1/src/core/primitives/scr1_cg.sv b/verilog/rtl/syntacore_scr1/src/core/primitives/scr1_cg.sv
new file mode 100644
index 0000000..b0f6154
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/primitives/scr1_cg.sv
@@ -0,0 +1,32 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_cg.sv>
+/// @brief SCR1 clock gate primitive
+///
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_CLKCTRL_EN
+module scr1_cg (
+ input logic clk,
+ input logic clk_en,
+ input logic test_mode,
+ output logic clk_out
+);
+
+// The code below is a clock gate model for simulation.
+// For synthesis, it should be replaced by implementation-specific
+// clock gate code.
+
+logic latch_en;
+
+always_latch begin
+ if (~clk) begin
+ latch_en <= test_mode | clk_en;
+ end
+end
+
+assign clk_out = latch_en & clk;
+
+endmodule : scr1_cg
+
+`endif // SCR1_CLKCTRL_EN
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/src/core/primitives/scr1_reset_cells.sv b/verilog/rtl/syntacore_scr1/src/core/primitives/scr1_reset_cells.sv
new file mode 100644
index 0000000..1af347c
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/primitives/scr1_reset_cells.sv
@@ -0,0 +1,231 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_sync_rstn.sv>
+/// @brief Cells for reset handling
+///
+
+//--------------------------------------------------------------------
+// Reset Buffer Cell
+//--------------------------------------------------------------------
+module scr1_reset_buf_cell (
+ input logic rst_n,
+ input logic clk,
+ input logic test_mode,
+ input logic test_rst_n,
+ input logic reset_n_in,
+ output logic reset_n_out,
+ output logic reset_n_status
+);
+
+logic reset_n_ff;
+logic reset_n_status_ff;
+logic rst_n_mux;
+
+assign rst_n_mux = (test_mode == 1'b1) ? test_rst_n : rst_n;
+
+always_ff @(negedge rst_n_mux, posedge clk) begin
+ if (~rst_n_mux) begin
+ reset_n_ff <= 1'b0;
+ end else begin
+ reset_n_ff <= reset_n_in;
+ end
+end
+
+assign reset_n_out = (test_mode == 1'b1) ? test_rst_n : reset_n_ff;
+
+always_ff @(negedge rst_n_mux, posedge clk) begin
+ if (~rst_n_mux) begin
+ reset_n_status_ff <= 1'b0;
+ end else begin
+ reset_n_status_ff <= reset_n_in;
+ end
+end
+assign reset_n_status = reset_n_status_ff;
+
+endmodule : scr1_reset_buf_cell
+
+//--------------------------------------------------------------------
+// Reset CDC Synchronization Cell
+//--------------------------------------------------------------------
+module scr1_reset_sync_cell #(
+ parameter int unsigned STAGES_AMOUNT = 2
+) (
+ input logic rst_n,
+ input logic clk,
+ input logic test_rst_n,
+ input logic test_mode,
+ input logic rst_n_in,
+ output logic rst_n_out
+);
+
+logic [STAGES_AMOUNT-1:0] rst_n_dff;
+logic local_rst_n_in;
+
+assign local_rst_n_in = (test_mode == 1'b1) ? test_rst_n : rst_n;
+
+generate
+
+if (STAGES_AMOUNT == 1)
+
+begin : gen_reset_sync_cell_single
+ always_ff @(negedge local_rst_n_in, posedge clk) begin
+ if (~local_rst_n_in) begin
+ rst_n_dff <= 1'b0;
+ end else begin
+ rst_n_dff <= rst_n_in;
+ end
+ end
+end : gen_reset_sync_cell_single
+
+else // STAGES_AMOUNT > 1
+
+begin : gen_reset_sync_cell_multi
+ always_ff @(negedge local_rst_n_in, posedge clk)
+ begin
+ if (~local_rst_n_in) begin
+ rst_n_dff <= '0;
+ end else begin
+ rst_n_dff <= {rst_n_dff[STAGES_AMOUNT-2:0], rst_n_in};
+ end
+ end
+end : gen_reset_sync_cell_multi
+
+endgenerate
+
+assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : rst_n_dff[STAGES_AMOUNT-1];
+
+endmodule : scr1_reset_sync_cell
+
+//--------------------------------------------------------------------
+// Data CDC/RDC Synchronization Cell
+//--------------------------------------------------------------------
+module scr1_data_sync_cell #(
+ parameter int unsigned STAGES_AMOUNT = 1
+) (
+ input logic rst_n,
+ input logic clk,
+ input logic data_in,
+ output logic data_out
+);
+
+logic [STAGES_AMOUNT-1:0] data_dff;
+
+generate
+
+if (STAGES_AMOUNT == 1)
+
+begin : gen_data_sync_cell_single
+ always_ff @(negedge rst_n, posedge clk)
+ begin
+ if (~rst_n) begin
+ data_dff <= 1'b0;
+ end else begin
+ data_dff <= data_in;
+ end
+ end
+end : gen_data_sync_cell_single
+
+else // STAGES_AMOUNT > 1
+
+begin : gen_data_sync_cell_multi
+ always_ff @(negedge rst_n, posedge clk)
+ begin
+ if (~rst_n) begin
+ data_dff <= '0;
+ end else begin
+ data_dff <= {data_dff[STAGES_AMOUNT-2:0], data_in};
+ end
+ end
+end : gen_data_sync_cell_multi
+
+endgenerate
+
+assign data_out = data_dff[STAGES_AMOUNT-1];
+
+endmodule : scr1_data_sync_cell
+
+//--------------------------------------------------------------------
+// Reset / RDC Qualifyer Adapter Cell
+// (Reset Generation Cell w/ RDC Qualifyer Adaptation circuitry)
+//--------------------------------------------------------------------
+// Total stages amount =
+// 1 Front Sync stage \
+// + 1 (delay introduced by the reset output buffer register)
+//--------------------------------------------------------------------
+module scr1_reset_qlfy_adapter_cell_sync (
+ input logic rst_n,
+ input logic clk,
+ input logic test_rst_n,
+ input logic test_mode,
+ input logic reset_n_in_sync,
+ output logic reset_n_out_qlfy,
+ output logic reset_n_out,
+ output logic reset_n_status
+);
+
+logic rst_n_mux;
+logic reset_n_front_ff;
+
+// Front sync stage
+assign rst_n_mux = (test_mode == 1'b1) ? test_rst_n : rst_n;
+
+always_ff @(negedge rst_n_mux, posedge clk) begin
+ if (~rst_n_mux) begin
+ reset_n_front_ff <= 1'b0;
+ end else begin
+ reset_n_front_ff <= reset_n_in_sync;
+ end
+end
+
+// Sync reset output for all reset qualifier chains targeting this reset domain
+// (for reset-domain-crossings with the given reset domain as a destination).
+assign reset_n_out_qlfy = reset_n_front_ff;
+
+// Reset output buffer
+scr1_reset_buf_cell
+i_reset_output_buf (
+ .rst_n (rst_n),
+ .clk (clk),
+ .test_mode (test_mode),
+ .test_rst_n (test_rst_n),
+ .reset_n_in (reset_n_front_ff),
+ .reset_n_out (reset_n_out),
+ .reset_n_status (reset_n_status)
+);
+
+endmodule : scr1_reset_qlfy_adapter_cell_sync
+
+module scr1_reset_and2_cell (
+ input logic [1:0] rst_n_in,
+ input logic test_rst_n,
+ input logic test_mode,
+ output logic rst_n_out
+);
+
+assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : (&rst_n_in);
+
+endmodule : scr1_reset_and2_cell
+
+
+module scr1_reset_and3_cell (
+ input logic [2:0] rst_n_in,
+ input logic test_rst_n,
+ input logic test_mode,
+ output logic rst_n_out
+);
+
+assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : (&rst_n_in);
+
+endmodule : scr1_reset_and3_cell
+
+
+module scr1_reset_mux2_cell (
+ input logic [1:0] rst_n_in,
+ input logic select,
+ input logic test_rst_n,
+ input logic test_mode,
+ output logic rst_n_out
+);
+
+assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : rst_n_in[select];
+
+endmodule : scr1_reset_mux2_cell
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_clk_ctrl.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_clk_ctrl.sv
new file mode 100644
index 0000000..09b72f4
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_clk_ctrl.sv
@@ -0,0 +1,55 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_clk_ctrl.sv>
+/// @brief SCR1 clock control
+///
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_CLKCTRL_EN
+module scr1_clk_ctrl (
+ input logic clk, // Clock control module clock
+ input logic rst_n, // Clock control module reset
+ input logic test_mode, // DFT Test Mode
+ input logic test_rst_n, // DFT Test reset
+
+ input logic pipe2clkctl_sleep_req_i, // CLK disable request from pipe
+ input logic pipe2clkctl_wake_req_i, // CLK enable request from pipe
+
+ output logic clkctl2pipe_clk_alw_on_o, // Not gated pipe CLK
+ output logic clkctl2pipe_clk_o, // Gated pipe
+ output logic clkctl2pipe_clk_en_o, // CLK enabled flag
+ output logic clkctl2pipe_clk_dbgc_o // CLK for pipe debug subsystem
+);
+
+logic ctrl_rst_n;
+
+assign clkctl2pipe_clk_alw_on_o = clk;
+assign clkctl2pipe_clk_dbgc_o = clk;
+assign ctrl_rst_n = (test_mode) ? test_rst_n : rst_n;
+
+always_ff @(posedge clk, negedge ctrl_rst_n) begin
+ if (~ctrl_rst_n) begin
+ clkctl2pipe_clk_en_o <= 1'b1;
+ end else begin
+ if (clkctl2pipe_clk_en_o) begin
+ if (pipe2clkctl_sleep_req_i & ~pipe2clkctl_wake_req_i) begin
+ clkctl2pipe_clk_en_o <= 1'b0;
+ end
+ end else begin // ~clkctl2pipe_clk_en_o
+ if (pipe2clkctl_wake_req_i) begin
+ clkctl2pipe_clk_en_o <= 1'b1;
+ end
+ end // pipeline
+ end
+end
+
+scr1_cg i_scr1_cg_pipe (
+ .clk (clk ),
+ .clk_en (clkctl2pipe_clk_en_o),
+ .test_mode (test_mode ),
+ .clk_out (clkctl2pipe_clk_o )
+);
+
+endmodule : scr1_clk_ctrl
+
+`endif // SCR1_CLKCTRL_EN
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_core_top.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_core_top.sv
new file mode 100644
index 0000000..582e4bb
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_core_top.sv
@@ -0,0 +1,519 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_core_top.sv>
+/// @brief SCR1 core top
+///
+
+`include "scr1_arch_description.svh"
+`include "scr1_arch_types.svh"
+`include "scr1_memif.svh"
+
+`ifdef SCR1_DBG_EN
+`include "scr1_tapc.svh"
+`include "scr1_dm.svh"
+`include "scr1_hdu.svh"
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_IPIC_EN
+`include "scr1_ipic.svh"
+`endif // SCR1_IPIC_EN
+
+module scr1_core_top (
+ // Common
+ input logic pwrup_rst_n, // Power-Up reset
+ input logic rst_n, // Regular reset
+ input logic cpu_rst_n, // CPU reset
+ input logic test_mode, // DFT Test Mode
+ input logic test_rst_n, // DFT Test Reset
+ input logic clk, // Core clock
+ output logic core_rst_n_o, // Core reset
+ output logic core_rdc_qlfy_o, // Core RDC qualifier
+`ifdef SCR1_DBG_EN
+ output logic sys_rst_n_o, // System reset
+ output logic sys_rdc_qlfy_o, // System RDC qualifier
+`endif // SCR1_DBG_EN
+
+ // Fuses
+ input logic [`SCR1_XLEN-1:0] core_fuse_mhartid_i, // Fuse MHARTID value
+`ifdef SCR1_DBG_EN
+ input logic [31:0] tapc_fuse_idcode_i, // Fuse IDCODE value
+`endif // SCR1_DBG_EN
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ input logic [SCR1_IRQ_LINES_NUM-1:0] core_irq_lines_i, // External interrupt request lines
+`else
+ input logic core_irq_ext_i, // External interrupt request
+`endif // SCR1_IPIC_EN
+ input logic core_irq_soft_i, // Software generated interrupt request
+ input logic core_irq_mtimer_i, // Machine timer interrupt request
+
+ // Memory-mapped external timer
+ input logic [63:0] core_mtimer_val_i, // Machine timer value
+
+`ifdef SCR1_DBG_EN
+ // Debug Interface
+ input logic tapc_trst_n, // Test Reset (TRSTn)
+ input logic tapc_tck, // Test Clock (TCK)
+ input logic tapc_tms, // Test Mode Select (TMS)
+ input logic tapc_tdi, // Test Data Input (TDI)
+ output logic tapc_tdo, // Test Data Output (TDO)
+ output logic tapc_tdo_en, // TDO Enable, signal for TDO buffer control
+`endif // SCR1_DBG_EN
+
+ // Instruction Memory Interface
+ input logic imem2core_req_ack_i, // IMEM request acknowledge
+ output logic core2imem_req_o, // IMEM request
+ output type_scr1_mem_cmd_e core2imem_cmd_o, // IMEM command
+ output logic [`SCR1_IMEM_AWIDTH-1:0] core2imem_addr_o, // IMEM address
+ input logic [`SCR1_IMEM_DWIDTH-1:0] imem2core_rdata_i, // IMEM read data
+ input type_scr1_mem_resp_e imem2core_resp_i, // IMEM response
+
+ // Data Memory Interface
+ input logic dmem2core_req_ack_i, // DMEM request acknowledge
+ output logic core2dmem_req_o, // DMEM request
+ output type_scr1_mem_cmd_e core2dmem_cmd_o, // DMEM command
+ output type_scr1_mem_width_e core2dmem_width_o, // DMEM data width
+ output logic [`SCR1_DMEM_AWIDTH-1:0] core2dmem_addr_o, // DMEM address
+ output logic [`SCR1_DMEM_DWIDTH-1:0] core2dmem_wdata_o, // DMEM write data
+ input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2core_rdata_i, // DMEM read data
+ input type_scr1_mem_resp_e dmem2core_resp_i // DMEM response
+);
+
+//-------------------------------------------------------------------------------
+// Local parameters
+//-------------------------------------------------------------------------------
+localparam int unsigned SCR1_CORE_TOP_RST_SYNC_STAGES_NUM = 2;
+
+//-------------------------------------------------------------------------------
+// Local signals declaration
+//-------------------------------------------------------------------------------
+
+// Reset Logic
+`ifdef SCR1_DBG_EN
+`else // SCR1_DBG_EN
+logic core_rst_n_in_sync;
+logic core_rst_n_qlfy;
+logic core_rst_n_status;
+`endif // SCR1_DBG_EN
+logic core_rst_n;
+logic core_rst_n_status_sync;
+logic core_rst_status;
+logic core2hdu_rdc_qlfy;
+logic core2dm_rdc_qlfy;
+logic pwrup_rst_n_sync;
+logic rst_n_sync;
+logic cpu_rst_n_sync;
+
+`ifdef SCR1_DBG_EN
+// TAPC-DM Interface
+logic tapc_dmi_ch_sel;
+logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc_dmi_ch_id;
+logic tapc_dmi_ch_capture;
+logic tapc_dmi_ch_shift;
+logic tapc_dmi_ch_update;
+logic tapc_dmi_ch_tdi;
+logic tapc_dmi_ch_tdo;
+//
+logic tapc_dmi_ch_sel_tapout;
+logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc_dmi_ch_id_tapout;
+logic tapc_dmi_ch_capture_tapout;
+logic tapc_dmi_ch_shift_tapout;
+logic tapc_dmi_ch_update_tapout;
+logic tapc_dmi_ch_tdi_tapout;
+logic tapc_dmi_ch_tdo_tapin;
+//
+logic dmi_req;
+logic dmi_wr;
+logic [SCR1_DBG_DMI_ADDR_WIDTH-1:0] dmi_addr;
+logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi_wdata;
+logic dmi_resp;
+logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi_rdata;
+// TAPC-SCU Interface
+logic tapc_scu_ch_sel;
+logic tapc_scu_ch_sel_tapout;
+logic tapc_scu_ch_tdo;
+logic tapc_ch_tdo;
+// SCU nets
+logic sys_rst_n;
+logic sys_rst_status;
+logic hdu_rst_n;
+logic hdu2dm_rdc_qlfy;
+logic ndm_rst_n;
+logic dm_rst_n;
+logic hart_rst_n;
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_DBG_EN
+// DM-Pipeline Interface
+// HART Run Control i/f
+logic dm_active;
+logic dm_cmd_req;
+type_scr1_hdu_dbgstates_e dm_cmd;
+logic dm_cmd_resp;
+logic dm_cmd_resp_qlfy;
+logic dm_cmd_rcode;
+logic dm_hart_event;
+logic dm_hart_event_qlfy;
+type_scr1_hdu_hartstatus_s dm_hart_status;
+type_scr1_hdu_hartstatus_s dm_hart_status_qlfy;
+// Program Buffer - HART instruction execution i/f
+logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] dm_pbuf_addr;
+logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] dm_pbuf_addr_qlfy;
+logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm_pbuf_instr;
+// HART Abstract Data regs i/f
+logic dm_dreg_req;
+logic dm_dreg_req_qlfy;
+logic dm_dreg_wr;
+logic [SCR1_HDU_DATA_REG_WIDTH-1:0] dm_dreg_wdata;
+logic dm_dreg_resp;
+logic dm_dreg_fail;
+logic [SCR1_HDU_DATA_REG_WIDTH-1:0] dm_dreg_rdata;
+
+logic [`SCR1_XLEN-1 : 0] dm_pc_sample;
+logic [`SCR1_XLEN-1 : 0] dm_pc_sample_qlfy;
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_CLKCTRL_EN
+// Global clock gating logic
+logic sleep_pipe;
+logic wake_pipe;
+logic clk_pipe;
+logic clk_pipe_en;
+logic clk_dbgc;
+logic clk_alw_on;
+`endif // SCR1_CLKCTRL_EN
+
+
+//-------------------------------------------------------------------------------
+// Reset Logic
+//-------------------------------------------------------------------------------
+`ifdef SCR1_DBG_EN
+scr1_scu i_scu (
+ // Global signals
+ .pwrup_rst_n (pwrup_rst_n ),
+ .rst_n (rst_n ),
+ .cpu_rst_n (cpu_rst_n ),
+ .test_mode (test_mode ),
+ .test_rst_n (test_rst_n ),
+ .clk (clk ),
+
+ // TAPC scan-chains
+ .tapcsync2scu_ch_sel_i (tapc_scu_ch_sel ),
+ .tapcsync2scu_ch_id_i ('0 ),
+ .tapcsync2scu_ch_capture_i (tapc_dmi_ch_capture),
+ .tapcsync2scu_ch_shift_i (tapc_dmi_ch_shift ),
+ .tapcsync2scu_ch_update_i (tapc_dmi_ch_update ),
+ .tapcsync2scu_ch_tdi_i (tapc_dmi_ch_tdi ),
+ .scu2tapcsync_ch_tdo_o (tapc_scu_ch_tdo ),
+
+ // Input sync resets:
+ .ndm_rst_n_i (ndm_rst_n ),
+ .hart_rst_n_i (hart_rst_n ),
+
+ // Generated resets
+ .sys_rst_n_o (sys_rst_n ),
+ .core_rst_n_o (core_rst_n ),
+ .dm_rst_n_o (dm_rst_n ),
+ .hdu_rst_n_o (hdu_rst_n ),
+
+ // Resets statuses
+ .sys_rst_status_o (sys_rst_status ),
+ .core_rst_status_o (core_rst_status ),
+
+ // Reset Domain Crossing (RDC) qualifiers
+ .sys_rdc_qlfy_o (sys_rdc_qlfy_o ),
+ .core_rdc_qlfy_o (core_rdc_qlfy_o ),
+ .core2hdu_rdc_qlfy_o (core2hdu_rdc_qlfy ),
+ .core2dm_rdc_qlfy_o (core2dm_rdc_qlfy ),
+ .hdu2dm_rdc_qlfy_o (hdu2dm_rdc_qlfy )
+);
+
+assign sys_rst_n_o = sys_rst_n;
+
+// Reset inputs are assumed synchronous
+assign pwrup_rst_n_sync = pwrup_rst_n;
+
+`else // SCR1_DBG_EN
+
+// Reset inputs are assumed synchronous
+assign pwrup_rst_n_sync = pwrup_rst_n;
+assign rst_n_sync = rst_n;
+assign cpu_rst_n_sync = cpu_rst_n;
+assign core_rst_n_in_sync = rst_n_sync & cpu_rst_n_sync;
+
+// Core Reset: core_rst_n
+scr1_reset_qlfy_adapter_cell_sync i_core_rstn_qlfy_adapter_cell_sync (
+ .rst_n (pwrup_rst_n_sync ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .reset_n_in_sync (core_rst_n_in_sync),
+ .reset_n_out_qlfy (core_rst_n_qlfy ),
+ .reset_n_out (core_rst_n ),
+ .reset_n_status (core_rst_n_status )
+);
+
+scr1_data_sync_cell #(
+ .STAGES_AMOUNT (SCR1_CORE_TOP_RST_SYNC_STAGES_NUM)
+) i_core_rstn_status_sync (
+ .rst_n (pwrup_rst_n_sync ),
+ .clk (clk ),
+ .data_in (core_rst_n_status ),
+ .data_out (core_rst_n_status_sync)
+);
+
+assign core_rst_status = ~core_rst_n_status_sync;
+assign core_rdc_qlfy_o = core_rst_n_qlfy;
+
+`endif // SCR1_DBG_EN
+assign core_rst_n_o = core_rst_n;
+
+//-------------------------------------------------------------------------------
+// SCR1 pipeline
+//-------------------------------------------------------------------------------
+scr1_pipe_top i_pipe_top (
+ // Control
+ .pipe_rst_n (core_rst_n ),
+`ifdef SCR1_DBG_EN
+ .pipe2hdu_rdc_qlfy_i (core2hdu_rdc_qlfy ),
+ .dbg_rst_n (hdu_rst_n ),
+`endif // SCR1_DBG_EN
+`ifndef SCR1_CLKCTRL_EN
+ .clk (clk ),
+`else // SCR1_CLKCTRL_EN
+ .clk (clk_pipe ),
+ .pipe2clkctl_sleep_req_o (sleep_pipe ),
+ .pipe2clkctl_wake_req_o (wake_pipe ),
+ .clkctl2pipe_clk_alw_on_i (clk_alw_on ),
+ .clkctl2pipe_clk_dbgc_i (clk_dbgc ),
+ .clkctl2pipe_clk_en_i (clk_pipe_en ),
+`endif // SCR1_CLKCTRL_EN
+
+ // Instruction memory interface
+ .pipe2imem_req_o (core2imem_req_o ),
+ .pipe2imem_cmd_o (core2imem_cmd_o ),
+ .pipe2imem_addr_o (core2imem_addr_o ),
+ .imem2pipe_req_ack_i (imem2core_req_ack_i ),
+ .imem2pipe_rdata_i (imem2core_rdata_i ),
+ .imem2pipe_resp_i (imem2core_resp_i ),
+
+ // Data memory interface
+ .pipe2dmem_req_o (core2dmem_req_o ),
+ .pipe2dmem_cmd_o (core2dmem_cmd_o ),
+ .pipe2dmem_width_o (core2dmem_width_o ),
+ .pipe2dmem_addr_o (core2dmem_addr_o ),
+ .pipe2dmem_wdata_o (core2dmem_wdata_o ),
+ .dmem2pipe_req_ack_i (dmem2core_req_ack_i ),
+ .dmem2pipe_rdata_i (dmem2core_rdata_i ),
+ .dmem2pipe_resp_i (dmem2core_resp_i ),
+
+`ifdef SCR1_DBG_EN
+ // Debug interface:
+ .dbg_en (1'b1 ),
+ // Debug interface:
+ // DM <-> Pipeline: HART Run Control i/f
+ .dm2pipe_active_i (dm_active ),
+ .dm2pipe_cmd_req_i (dm_cmd_req ),
+ .dm2pipe_cmd_i (dm_cmd ),
+ .pipe2dm_cmd_resp_o (dm_cmd_resp ),
+ .pipe2dm_cmd_rcode_o (dm_cmd_rcode ),
+ .pipe2dm_hart_event_o (dm_hart_event ),
+ .pipe2dm_hart_status_o (dm_hart_status ),
+
+ // DM <-> Pipeline: Program Buffer - HART instruction execution i/f
+ .pipe2dm_pbuf_addr_o (dm_pbuf_addr ),
+ .dm2pipe_pbuf_instr_i (dm_pbuf_instr ),
+
+ // DM <-> Pipeline: HART Abstract Data regs i/f
+ .pipe2dm_dreg_req_o (dm_dreg_req ),
+ .pipe2dm_dreg_wr_o (dm_dreg_wr ),
+ .pipe2dm_dreg_wdata_o (dm_dreg_wdata ),
+ .dm2pipe_dreg_resp_i (dm_dreg_resp ),
+ .dm2pipe_dreg_fail_i (dm_dreg_fail ),
+ .dm2pipe_dreg_rdata_i (dm_dreg_rdata ),
+
+ // DM <-> Pipeline: PC i/f
+ .pipe2dm_pc_sample_o (dm_pc_sample ),
+`endif // SCR1_DBG_EN
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ .soc2pipe_irq_lines_i (core_irq_lines_i ),
+`else // SCR1_IPIC_EN
+ .soc2pipe_irq_ext_i (core_irq_ext_i ),
+`endif // SCR1_IPIC_EN
+ .soc2pipe_irq_soft_i (core_irq_soft_i ),
+ .soc2pipe_irq_mtimer_i (core_irq_mtimer_i ),
+
+ // Memory-mapped external timer
+ .soc2pipe_mtimer_val_i (core_mtimer_val_i ),
+
+ // Fuse
+ .soc2pipe_fuse_mhartid_i (core_fuse_mhartid_i )
+);
+
+
+`ifdef SCR1_DBG_EN
+//-------------------------------------------------------------------------------
+// TAP Controller (TAPC)
+//-------------------------------------------------------------------------------
+scr1_tapc i_tapc (
+ // JTAG signals
+ .tapc_trst_n (tapc_trst_n ),
+ .tapc_tck (tapc_tck ),
+ .tapc_tms (tapc_tms ),
+ .tapc_tdi (tapc_tdi ),
+ .tapc_tdo (tapc_tdo ),
+ .tapc_tdo_en (tapc_tdo_en ),
+
+ // Fuses
+ .soc2tapc_fuse_idcode_i (tapc_fuse_idcode_i ),
+
+ // DMI/SCU scan-chains
+ .tapc2tapcsync_scu_ch_sel_o (tapc_scu_ch_sel_tapout ),
+ .tapc2tapcsync_dmi_ch_sel_o (tapc_dmi_ch_sel_tapout ),
+ .tapc2tapcsync_ch_id_o (tapc_dmi_ch_id_tapout ),
+ .tapc2tapcsync_ch_capture_o (tapc_dmi_ch_capture_tapout),
+ .tapc2tapcsync_ch_shift_o (tapc_dmi_ch_shift_tapout ),
+ .tapc2tapcsync_ch_update_o (tapc_dmi_ch_update_tapout ),
+ .tapc2tapcsync_ch_tdi_o (tapc_dmi_ch_tdi_tapout ),
+ .tapcsync2tapc_ch_tdo_i (tapc_dmi_ch_tdo_tapin )
+);
+
+scr1_tapc_synchronizer i_tapc_synchronizer (
+ // System common signals
+ .pwrup_rst_n (pwrup_rst_n_sync ),
+ .dm_rst_n (dm_rst_n ),
+ .clk (clk ),
+
+ // JTAG common signals
+ .tapc_trst_n (tapc_trst_n ),
+ .tapc_tck (tapc_tck ),
+
+ // DMI/SCU scan-chains
+ .tapc2tapcsync_scu_ch_sel_i (tapc_scu_ch_sel_tapout ),
+ .tapcsync2scu_ch_sel_o (tapc_scu_ch_sel ),
+ .tapc2tapcsync_dmi_ch_sel_i (tapc_dmi_ch_sel_tapout ),
+ .tapcsync2dmi_ch_sel_o (tapc_dmi_ch_sel ),
+
+ .tapc2tapcsync_ch_id_i (tapc_dmi_ch_id_tapout ),
+ .tapcsync2core_ch_id_o (tapc_dmi_ch_id ),
+ .tapc2tapcsync_ch_capture_i (tapc_dmi_ch_capture_tapout),
+ .tapcsync2core_ch_capture_o (tapc_dmi_ch_capture ),
+ .tapc2tapcsync_ch_shift_i (tapc_dmi_ch_shift_tapout ),
+ .tapcsync2core_ch_shift_o (tapc_dmi_ch_shift ),
+ .tapc2tapcsync_ch_update_i (tapc_dmi_ch_update_tapout ),
+ .tapcsync2core_ch_update_o (tapc_dmi_ch_update ),
+ .tapc2tapcsync_ch_tdi_i (tapc_dmi_ch_tdi_tapout ),
+ .tapcsync2core_ch_tdi_o (tapc_dmi_ch_tdi ),
+ .tapc2tapcsync_ch_tdo_i (tapc_dmi_ch_tdo_tapin ),
+ .tapcsync2core_ch_tdo_o (tapc_ch_tdo )
+);
+assign tapc_ch_tdo = (tapc_scu_ch_tdo & tapc_scu_ch_sel)
+ | (tapc_dmi_ch_tdo & tapc_dmi_ch_sel);
+
+scr1_dmi i_dmi (
+ .rst_n (dm_rst_n ),
+ .clk (clk ),
+
+ // TAP scan-chains
+ .tapcsync2dmi_ch_sel_i (tapc_dmi_ch_sel ),
+ .tapcsync2dmi_ch_id_i (tapc_dmi_ch_id ),
+ .tapcsync2dmi_ch_capture_i (tapc_dmi_ch_capture),
+ .tapcsync2dmi_ch_shift_i (tapc_dmi_ch_shift ),
+ .tapcsync2dmi_ch_update_i (tapc_dmi_ch_update ),
+ .tapcsync2dmi_ch_tdi_i (tapc_dmi_ch_tdi ),
+ .dmi2tapcsync_ch_tdo_o (tapc_dmi_ch_tdo ),
+
+ // DMI
+ .dm2dmi_resp_i (dmi_resp ),
+ .dm2dmi_rdata_i (dmi_rdata ),
+ .dmi2dm_req_o (dmi_req ),
+ .dmi2dm_wr_o (dmi_wr ),
+ .dmi2dm_addr_o (dmi_addr ),
+ .dmi2dm_wdata_o (dmi_wdata )
+);
+
+`endif // SCR1_DBG_EN
+
+
+`ifdef SCR1_DBG_EN
+
+//-------------------------------------------------------------------------------
+// Debug Module (DM)
+//-------------------------------------------------------------------------------
+assign dm_cmd_resp_qlfy = dm_cmd_resp & {$bits(dm_cmd_resp){hdu2dm_rdc_qlfy}};
+assign dm_hart_event_qlfy = dm_hart_event & {$bits(dm_hart_event){hdu2dm_rdc_qlfy}};
+assign dm_hart_status_qlfy.dbg_state = hdu2dm_rdc_qlfy ? dm_hart_status.dbg_state
+ : SCR1_HDU_DBGSTATE_RESET;
+assign dm_hart_status_qlfy.except = dm_hart_status.except;
+assign dm_hart_status_qlfy.ebreak = dm_hart_status.ebreak;
+assign dm_pbuf_addr_qlfy = dm_pbuf_addr & {$bits(dm_pbuf_addr){hdu2dm_rdc_qlfy}};
+assign dm_dreg_req_qlfy = dm_dreg_req & {$bits(dm_dreg_req){hdu2dm_rdc_qlfy}};
+assign dm_pc_sample_qlfy = dm_pc_sample & {$bits(dm_pc_sample){core2dm_rdc_qlfy}};
+
+scr1_dm i_dm (
+ // Common signals
+ .rst_n (dm_rst_n ),
+ .clk (clk ),
+
+ // DM internal interface
+ .dmi2dm_req_i (dmi_req ),
+ .dmi2dm_wr_i (dmi_wr ),
+ .dmi2dm_addr_i (dmi_addr ),
+ .dmi2dm_wdata_i (dmi_wdata ),
+ .dm2dmi_resp_o (dmi_resp ),
+ .dm2dmi_rdata_o (dmi_rdata ),
+
+ // DM <-> Pipeline: HART Run Control i/f
+ .ndm_rst_n_o (ndm_rst_n ),
+ .hart_rst_n_o (hart_rst_n ),
+ .dm2pipe_active_o (dm_active ),
+ .dm2pipe_cmd_req_o (dm_cmd_req ),
+ .dm2pipe_cmd_o (dm_cmd ),
+ .pipe2dm_cmd_resp_i (dm_cmd_resp_qlfy ),
+ .pipe2dm_cmd_rcode_i (dm_cmd_rcode ),
+ .pipe2dm_hart_event_i (dm_hart_event_qlfy ),
+ .pipe2dm_hart_status_i (dm_hart_status_qlfy ),
+
+ .soc2dm_fuse_mhartid_i (core_fuse_mhartid_i ),
+ .pipe2dm_pc_sample_i (dm_pc_sample_qlfy ),
+
+ // DM <-> Pipeline: HART Abstract Command / Program Buffer i/f
+ .pipe2dm_pbuf_addr_i (dm_pbuf_addr_qlfy ),
+ .dm2pipe_pbuf_instr_o (dm_pbuf_instr ),
+
+ // DM <-> Pipeline: HART Abstract Data regs i/f
+ .pipe2dm_dreg_req_i (dm_dreg_req_qlfy ),
+ .pipe2dm_dreg_wr_i (dm_dreg_wr ),
+ .pipe2dm_dreg_wdata_i (dm_dreg_wdata ),
+ .dm2pipe_dreg_resp_o (dm_dreg_resp ),
+ .dm2pipe_dreg_fail_o (dm_dreg_fail ),
+ .dm2pipe_dreg_rdata_o (dm_dreg_rdata )
+);
+`endif // SCR1_DBG_EN
+
+
+`ifdef SCR1_CLKCTRL_EN
+//-------------------------------------------------------------------------------
+// Global clock gating logic
+//-------------------------------------------------------------------------------
+scr1_clk_ctrl i_clk_ctrl (
+ .clk (clk ),
+ .rst_n (core_rst_n ),
+ .test_mode (test_mode ),
+ .test_rst_n (test_rst_n ),
+
+ // Sleep/wake interface
+ .pipe2clkctl_sleep_req_i (sleep_pipe ),
+ .pipe2clkctl_wake_req_i (wake_pipe ),
+
+ // Clocks
+ .clkctl2pipe_clk_alw_on_o (clk_alw_on ),
+ .clkctl2pipe_clk_o (clk_pipe ),
+ .clkctl2pipe_clk_en_o (clk_pipe_en),
+ .clkctl2pipe_clk_dbgc_o (clk_dbgc )
+);
+`endif // SCR1_CLKCTRL_EN
+
+endmodule : scr1_core_top
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_dm.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_dm.sv
new file mode 100644
index 0000000..3dfd254
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_dm.sv
@@ -0,0 +1,1427 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_dm.sv>
+/// @brief Debug Module (DM)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Allows debugger to perform a system reset (ndm_rst)
+ // - Allows debugger to control the HART's state
+ // - Provides debugger with information about the current HART's state
+ // - Provides debugger with Abstract Command interface that allows to:
+ // - Access MPRF registers
+ // - Access CSR registers
+ // - Access memory with the same view and permission as the hart has
+ // - Provides debugger with Abstract Command status information (busy flag and error code)
+ // - Provides debugger with Program Buffer functionality that allows to execute
+ // small programs on a halted HART
+ //
+ // Structure:
+ // - DM <-> DMI interface
+ // - DM registers:
+ // - DMCONTROL
+ // - DMSTATUS
+ // - Abstract Command Control logic
+ // - Abstract Command FSM
+ // - Abstract Command Status logic
+ // - Abstract Instruction logic
+ // - Abstract registers:
+ // - COMMAND
+ // - ABSTRACTAUTO
+ // - PROGBUF0..5
+ // - DATA0..1
+ // - DHI FSM
+ // - HART command registers
+ // - DHI interface
+ //
+//
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+`include "scr1_csr.svh"
+`include "scr1_dm.svh"
+
+module scr1_dm (
+ // System
+ input logic rst_n, // DM reset
+ input logic clk, // DM clock
+
+ // DM internal interface
+ input logic dmi2dm_req_i, // DMI request
+ input logic dmi2dm_wr_i, // DMI write
+ input logic [SCR1_DBG_DMI_ADDR_WIDTH-1:0] dmi2dm_addr_i, // DMI address
+ input logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi2dm_wdata_i, // DMI write data
+ output logic dm2dmi_resp_o, // DMI response
+ output logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dm2dmi_rdata_o, // DMI read data
+
+ // DM <-> Pipeline: HART Run Control i/f
+ output logic ndm_rst_n_o, // Non-DM Reset output
+ output logic hart_rst_n_o, // HART reset output
+ output logic dm2pipe_active_o, // Debug Module active flag
+ output logic dm2pipe_cmd_req_o, // Request to pipe
+ output type_scr1_hdu_dbgstates_e dm2pipe_cmd_o, // Command to pipe
+ input logic pipe2dm_cmd_resp_i, // Response to Debug Module
+ input logic pipe2dm_cmd_rcode_i, // HART Command return code: 0 - Ok; 1 - Error
+ input logic pipe2dm_hart_event_i, // HART event flag
+ input type_scr1_hdu_hartstatus_s pipe2dm_hart_status_i, // HART Status
+
+ input logic [`SCR1_XLEN-1:0] soc2dm_fuse_mhartid_i, // RO MHARTID value
+ input logic [`SCR1_XLEN-1:0] pipe2dm_pc_sample_i, // RO PC value for sampling
+
+ // HART Abstract Command / Program Buffer i/f
+ input logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pipe2dm_pbuf_addr_i, // Program Buffer address
+ output logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2pipe_pbuf_instr_o, // Program Buffer instruction
+
+ // HART Abstract Data regs i/f
+ input logic pipe2dm_dreg_req_i, // Abstract Data Register request
+ input logic pipe2dm_dreg_wr_i, // Abstract Data Register write
+ input logic [`SCR1_XLEN-1:0] pipe2dm_dreg_wdata_i, // Abstract Data Register write data
+ output logic dm2pipe_dreg_resp_o, // Abstract Data Register response
+ output logic dm2pipe_dreg_fail_o, // Abstract Data Register fail - possibly not needed ?
+ output logic [`SCR1_XLEN-1:0] dm2pipe_dreg_rdata_o // Abstract Data Register read data
+);
+
+//------------------------------------------------------------------------------
+// Local types declaration
+//------------------------------------------------------------------------------
+
+typedef enum logic [3:0] {
+ ABS_STATE_IDLE,
+ ABS_STATE_ERR,
+ ABS_STATE_EXEC,
+ ABS_STATE_XREG_RW,
+ ABS_STATE_MEM_SAVE_XREG,
+ ABS_STATE_MEM_SAVE_XREG_FORADDR,
+ ABS_STATE_MEM_RW,
+ ABS_STATE_MEM_RETURN_XREG,
+ ABS_STATE_MEM_RETURN_XREG_FORADDR,
+ ABS_STATE_CSR_RO,
+ ABS_STATE_CSR_SAVE_XREG,
+ ABS_STATE_CSR_RW,
+ ABS_STATE_CSR_RETURN_XREG
+} type_scr1_abs_fsm_e;
+
+typedef enum logic [2:0] {
+ DHI_STATE_IDLE,
+ DHI_STATE_EXEC,
+ DHI_STATE_EXEC_RUN,
+ DHI_STATE_EXEC_HALT,
+ DHI_STATE_HALT_REQ,
+ DHI_STATE_RESUME_REQ,
+ DHI_STATE_RESUME_RUN
+} type_scr1_dhi_fsm_e;
+
+typedef enum logic [SCR1_DBG_ABSTRACTCS_CMDERR_WDTH:0] {
+ ABS_ERR_NONE = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d0),
+ ABS_ERR_BUSY = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d1),
+ ABS_ERR_CMD = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d2),
+ ABS_ERR_EXCEPTION = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d3),
+ ABS_ERR_NOHALT = (SCR1_DBG_ABSTRACTCS_CMDERR_WDTH+1)'('d4)
+} type_scr1_abs_err_e;
+
+
+//------------------------------------------------------------------------------
+// Local parameters declaration
+//------------------------------------------------------------------------------
+
+// Abstract instruction opcode parameters
+localparam SCR1_OP_SYSTEM = 7'b111_0011;
+localparam SCR1_OP_LOAD = 7'b000_0011;
+localparam SCR1_OP_STORE = 7'b010_0011;
+
+// Abstract instruction funct3 parameters
+localparam SCR1_FUNCT3_CSRRW = 3'b001;
+localparam SCR1_FUNCT3_CSRRS = 3'b010;
+localparam SCR1_FUNCT3_SB = 3'b000;
+localparam SCR1_FUNCT3_SH = 3'b001;
+localparam SCR1_FUNCT3_SW = 3'b010;
+localparam SCR1_FUNCT3_LW = 3'b010;
+localparam SCR1_FUNCT3_LBU = 3'b100;
+localparam SCR1_FUNCT3_LHU = 3'b101;
+
+// DMCONTROL parameters
+//------------------------------------------------------------------------------
+localparam DMCONTROL_HARTRESET = 1'd0;
+localparam DMCONTROL_RESERVEDB = 1'd0;
+localparam DMCONTROL_HASEL = 1'd0;
+localparam DMCONTROL_HARTSELLO = 1'd0;
+localparam DMCONTROL_HARTSELHI = 1'd0;
+localparam DMCONTROL_RESERVEDA = 1'd0;
+
+// DMSTATUS parameters
+//------------------------------------------------------------------------------
+localparam DMSTATUS_RESERVEDC = 1'd0;
+localparam DMSTATUS_IMPEBREAK = 1'd1;
+localparam DMSTATUS_RESERVEDB = 1'd0;
+localparam DMSTATUS_ALLUNAVAIL = 1'd0;
+localparam DMSTATUS_ANYUNAVAIL = 1'd0;
+localparam DMSTATUS_ALLANYUNAVAIL = 1'd0;
+localparam DMSTATUS_ALLANYNONEXIST = 1'b0;
+localparam DMSTATUS_AUTHENTICATED = 1'd1;
+localparam DMSTATUS_AUTHBUSY = 1'd0;
+localparam DMSTATUS_RESERVEDA = 1'd0;
+localparam DMSTATUS_DEVTREEVALID = 1'd0;
+localparam DMSTATUS_VERSION = 2'd2;
+
+// HARTINFO parameters
+//------------------------------------------------------------------------------
+localparam HARTINFO_RESERVEDB = 1'd0;
+localparam HARTINFO_NSCRATCH = 4'd1;
+localparam HARTINFO_RESERVEDA = 1'd0;
+localparam HARTINFO_DATAACCESS = 1'd0;
+localparam HARTINFO_DATASIZE = 4'd1;
+localparam HARTINFO_DATAADDR = 12'h7b2;
+
+// ABSTRACTCS parameters
+//------------------------------------------------------------------------------
+localparam ABSTRACTCS_RESERVEDD = 1'd0;
+localparam ABSTRACTCS_PROGBUFSIZE = 5'd6;
+localparam ABSTRACTCS_RESERVEDC = 1'd0;
+localparam ABSTRACTCS_RESERVEDB = 1'd0;
+localparam ABSTRACTCS_RESERVEDA = 1'd0;
+localparam ABSTRACTCS_DATACOUNT = 4'd2;
+
+localparam ABS_CMD_HARTREG = 1'd0;
+localparam ABS_CMD_HARTMEM = 2'd2;
+localparam ABS_CMD_HARTREG_CSR = 4'b0000;
+localparam ABS_CMD_HARTREG_INTFPU = 4'b0001;
+localparam ABS_CMD_HARTREG_INT = 7'b000_0000;
+localparam ABS_CMD_HARTREG_FPU = 7'b000_0001;
+localparam ABS_EXEC_EBREAK = 32'b000000000001_00000_000_00000_1110011;
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// DM <-> DMI interface internal signals
+//------------------------------------------------------------------------------
+
+// Register selection signals
+logic dmi_req_dmcontrol;
+logic dmi_req_abstractcs;
+logic dmi_req_abstractauto;
+logic dmi_req_command;
+logic dmi_rpt_command;
+logic dmi_req_data0;
+logic dmi_req_data1;
+logic dmi_req_progbuf0;
+logic dmi_req_progbuf1;
+logic dmi_req_progbuf2;
+logic dmi_req_progbuf3;
+logic dmi_req_progbuf4;
+logic dmi_req_progbuf5;
+
+logic dmi_req_any;
+
+// Registers write request signals
+logic dmcontrol_wr_req;
+logic abstractcs_wr_req;
+logic data0_wr_req;
+logic data1_wr_req;
+logic dreg_wr_req;
+logic command_wr_req;
+logic autoexec_wr_req;
+logic progbuf0_wr_req;
+logic progbuf1_wr_req;
+logic progbuf2_wr_req;
+logic progbuf3_wr_req;
+logic progbuf4_wr_req;
+logic progbuf5_wr_req;
+
+// DM registers
+//------------------------------------------------------------------------------
+
+// DM clock enable signals
+logic clk_en_dm;
+logic clk_en_dm_ff;
+
+// DMCONTROL register signals
+logic dmcontrol_haltreq_ff;
+logic dmcontrol_haltreq_next;
+logic dmcontrol_resumereq_ff;
+logic dmcontrol_resumereq_next;
+logic dmcontrol_ackhavereset_ff;
+logic dmcontrol_ackhavereset_next;
+logic dmcontrol_ndmreset_ff;
+logic dmcontrol_ndmreset_next;
+logic dmcontrol_dmactive_ff;
+logic dmcontrol_dmactive_next;
+
+// Auxilary Skip Reset On Powerup register
+logic havereset_skip_pwrup_ff;
+logic havereset_skip_pwrup_next;
+
+// DMSTATUS register signals
+logic dmstatus_allany_havereset_ff;
+logic dmstatus_allany_havereset_next;
+logic dmstatus_allany_resumeack_ff;
+logic dmstatus_allany_resumeack_next;
+logic dmstatus_allany_halted_ff;
+logic dmstatus_allany_halted_next;
+
+// Abstract command control logic signals
+//------------------------------------------------------------------------------
+
+logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] abs_cmd;
+
+logic abs_cmd_csr_ro;
+logic [SCR1_DBG_COMMAND_TYPE_WDTH:0] abs_cmd_type;
+logic abs_cmd_regacs;
+logic [SCR1_DBG_COMMAND_ACCESSREG_REGNO_HI-12:0] abs_cmd_regtype;
+logic [6:0] abs_cmd_regfile;
+logic abs_cmd_regwr;
+logic [SCR1_DBG_COMMAND_ACCESSREG_SIZE_WDTH:0] abs_cmd_regsize;
+logic abs_cmd_execprogbuf;
+logic abs_cmd_regvalid;
+logic [2:0] abs_cmd_memsize;
+logic abs_cmd_memwr;
+logic abs_cmd_memvalid;
+
+logic abs_cmd_regsize_vd;
+logic abs_cmd_memsize_vd;
+
+logic abs_cmd_wr_ff;
+logic abs_cmd_wr_next;
+logic abs_cmd_postexec_ff;
+logic abs_cmd_postexec_next;
+logic [11:0] abs_cmd_regno;
+logic [11:0] abs_cmd_regno_ff;
+logic [1:0] abs_cmd_size_ff;
+logic [1:0] abs_cmd_size_next;
+
+logic abs_reg_access_csr;
+logic abs_reg_access_mprf;
+
+logic abs_cmd_hartreg_vd;
+logic abs_cmd_hartmem_vd;
+
+logic abs_cmd_reg_access_req;
+logic abs_cmd_csr_access_req;
+logic abs_cmd_mprf_access_req;
+logic abs_cmd_execprogbuf_req;
+
+logic abs_cmd_csr_ro_access_vd;
+logic abs_cmd_csr_rw_access_vd;
+logic abs_cmd_mprf_access_vd;
+logic abs_cmd_mem_access_vd;
+
+// Abstract FSM signals
+//------------------------------------------------------------------------------
+
+type_scr1_abs_fsm_e abs_fsm_ff;
+type_scr1_abs_fsm_e abs_fsm_next;
+logic abs_fsm_idle;
+logic abs_fsm_exec;
+logic abs_fsm_csr_ro;
+logic abs_fsm_err;
+logic abs_fsm_use_addr;
+
+// Abstract registers
+//------------------------------------------------------------------------------
+
+logic clk_en_abs;
+
+// ABSTRACTCS register signals
+logic abstractcs_busy;
+logic abstractcs_ro_en;
+
+// COMMAND register signals
+logic [`SCR1_XLEN-1:0] abs_command_ff;
+logic [`SCR1_XLEN-1:0] abs_command_next;
+
+// ABSTRACTAUTO register signals
+logic abs_autoexec_ff;
+logic abs_autoexec_next;
+
+// Program buffer registers
+logic [`SCR1_XLEN-1:0] abs_progbuf0_ff;
+logic [`SCR1_XLEN-1:0] abs_progbuf1_ff;
+logic [`SCR1_XLEN-1:0] abs_progbuf2_ff;
+logic [`SCR1_XLEN-1:0] abs_progbuf3_ff;
+logic [`SCR1_XLEN-1:0] abs_progbuf4_ff;
+logic [`SCR1_XLEN-1:0] abs_progbuf5_ff;
+
+// Data 0/1 registers
+logic data0_xreg_save;
+logic [`SCR1_XLEN-1:0] abs_data0_ff;
+logic [`SCR1_XLEN-1:0] abs_data0_next;
+logic [`SCR1_XLEN-1:0] abs_data1_ff;
+logic [`SCR1_XLEN-1:0] abs_data1_next;
+
+// Abstract command status logic signals
+//------------------------------------------------------------------------------
+
+// Abstract error exception flag register
+logic abs_err_exc_upd;
+logic abs_err_exc_ff;
+logic abs_err_exc_next;
+
+logic abs_err_acc_busy_upd;
+logic abs_err_acc_busy_ff;
+logic abs_err_acc_busy_next;
+
+type_scr1_abs_err_e abstractcs_cmderr_ff;
+type_scr1_abs_err_e abstractcs_cmderr_next;
+
+// Abstract instruction signals
+//------------------------------------------------------------------------------
+
+// Abstract instruction execution request register
+logic abs_exec_req_next;
+logic abs_exec_req_ff;
+
+// Abstract instruction register
+logic [4:0] abs_instr_rd;
+logic [4:0] abs_instr_rs1;
+logic [4:0] abs_instr_rs2;
+logic [2:0] abs_instr_mem_funct3;
+logic [`SCR1_XLEN-1:0] abs_exec_instr_next;
+logic [`SCR1_XLEN-1:0] abs_exec_instr_ff;
+
+// DHI FSM signals
+//------------------------------------------------------------------------------
+
+type_scr1_dhi_fsm_e dhi_fsm_next;
+type_scr1_dhi_fsm_e dhi_fsm_ff;
+type_scr1_dhi_fsm_e dhi_req;
+
+logic dhi_fsm_idle;
+logic dhi_fsm_exec;
+logic dhi_fsm_exec_halt;
+logic dhi_fsm_halt_req;
+logic dhi_fsm_resume_req;
+
+// DHI interface signals
+//------------------------------------------------------------------------------
+
+logic cmd_resp_ok;
+logic hart_rst_unexp;
+logic halt_req_vd;
+logic resume_req_vd;
+
+logic dhi_resp;
+logic dhi_resp_exc;
+
+logic hart_pbuf_ebreak_ff;
+logic hart_pbuf_ebreak_next;
+
+// HART command registers
+//------------------------------------------------------------------------------
+
+logic hart_cmd_req_ff;
+logic hart_cmd_req_next;
+
+type_scr1_hdu_dbgstates_e hart_cmd_ff;
+type_scr1_hdu_dbgstates_e hart_cmd_next;
+
+// HART state signals
+//------------------------------------------------------------------------------
+
+logic hart_state_reset;
+logic hart_state_run;
+logic hart_state_drun;
+logic hart_state_dhalt;
+
+//------------------------------------------------------------------------------
+// DM <-> DMI interface
+//------------------------------------------------------------------------------
+
+// Register selection logic
+//------------------------------------------------------------------------------
+
+always_comb begin
+ dmi_req_dmcontrol = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_DMCONTROL);
+ dmi_req_abstractcs = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_ABSTRACTCS);
+ dmi_req_abstractauto = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_ABSTRACTAUTO);
+ dmi_req_data0 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_DATA0);
+ dmi_req_data1 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_DATA1);
+ dmi_req_command = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_COMMAND);
+ dmi_rpt_command = (abs_autoexec_ff & dmi_req_data0);
+ dmi_req_progbuf0 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF0);
+ dmi_req_progbuf1 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF1);
+ dmi_req_progbuf2 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF2);
+ dmi_req_progbuf3 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF3);
+ dmi_req_progbuf4 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF4);
+ dmi_req_progbuf5 = dmi2dm_req_i & (dmi2dm_addr_i == SCR1_DBG_PROGBUF5);
+end
+
+assign dmi_req_any = dmi_req_command | dmi_rpt_command | dmi_req_abstractauto
+ | dmi_req_data0 | dmi_req_data1 | dmi_req_progbuf0
+ | dmi_req_progbuf1 | dmi_req_progbuf2 | dmi_req_progbuf3
+ | dmi_req_progbuf4 | dmi_req_progbuf5;
+
+
+// Read data multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ dm2dmi_rdata_o = '0;
+
+ case (dmi2dm_addr_i)
+ SCR1_DBG_DMSTATUS: begin
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_RESERVEDC_HI:
+ SCR1_DBG_DMSTATUS_RESERVEDC_LO] = DMSTATUS_RESERVEDC;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_IMPEBREAK] = DMSTATUS_IMPEBREAK;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_RESERVEDB_HI:
+ SCR1_DBG_DMSTATUS_RESERVEDB_LO] = DMSTATUS_RESERVEDB;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLHAVERESET] = dmstatus_allany_havereset_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYHAVERESET] = dmstatus_allany_havereset_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLRESUMEACK] = dmstatus_allany_resumeack_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYRESUMEACK] = dmstatus_allany_resumeack_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLNONEXISTENT] = DMSTATUS_ALLANYNONEXIST;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYNONEXISTENT] = DMSTATUS_ALLANYNONEXIST;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLUNAVAIL] = DMSTATUS_ALLANYUNAVAIL;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYUNAVAIL] = DMSTATUS_ALLANYUNAVAIL;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLRUNNING] = ~dmstatus_allany_halted_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYRUNNING] = ~dmstatus_allany_halted_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ALLHALTED] = dmstatus_allany_halted_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_ANYHALTED] = dmstatus_allany_halted_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_AUTHENTICATED] = DMSTATUS_AUTHENTICATED;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_AUTHBUSY] = DMSTATUS_AUTHBUSY;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_RESERVEDA] = DMSTATUS_RESERVEDA;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_DEVTREEVALID] = DMSTATUS_DEVTREEVALID;
+ dm2dmi_rdata_o[SCR1_DBG_DMSTATUS_VERSION_HI:
+ SCR1_DBG_DMSTATUS_VERSION_LO] = DMSTATUS_VERSION;;
+ end
+
+ SCR1_DBG_DMCONTROL: begin
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HALTREQ] = dmcontrol_haltreq_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_RESUMEREQ] = dmcontrol_resumereq_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HARTRESET] = DMCONTROL_HARTRESET;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_ACKHAVERESET] = dmcontrol_ackhavereset_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_RESERVEDB] = DMCONTROL_RESERVEDB;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HASEL] = DMCONTROL_HASEL;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HARTSELLO_HI:
+ SCR1_DBG_DMCONTROL_HARTSELLO_LO] = DMCONTROL_HARTSELLO;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_HARTSELHI_HI:
+ SCR1_DBG_DMCONTROL_HARTSELHI_LO] = DMCONTROL_HARTSELHI;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_RESERVEDA_HI:
+ SCR1_DBG_DMCONTROL_RESERVEDA_LO] = DMCONTROL_RESERVEDA;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_NDMRESET] = dmcontrol_ndmreset_ff;
+ dm2dmi_rdata_o[SCR1_DBG_DMCONTROL_DMACTIVE] = dmcontrol_dmactive_ff;
+ end
+
+ SCR1_DBG_ABSTRACTCS: begin
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDD_HI:
+ SCR1_DBG_ABSTRACTCS_RESERVEDD_LO] = ABSTRACTCS_RESERVEDD;
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_HI:
+ SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_LO] = ABSTRACTCS_PROGBUFSIZE;
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDC_HI:
+ SCR1_DBG_ABSTRACTCS_RESERVEDC_LO] = ABSTRACTCS_RESERVEDC;
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_BUSY] = abstractcs_busy;
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDB] = ABSTRACTCS_RESERVEDB;
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_CMDERR_HI:
+ SCR1_DBG_ABSTRACTCS_CMDERR_LO] = abstractcs_cmderr_ff;
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_RESERVEDA_HI:
+ SCR1_DBG_ABSTRACTCS_RESERVEDA_LO] = ABSTRACTCS_RESERVEDA;
+ dm2dmi_rdata_o[SCR1_DBG_ABSTRACTCS_DATACOUNT_HI:
+ SCR1_DBG_ABSTRACTCS_DATACOUNT_LO] = ABSTRACTCS_DATACOUNT;
+ end
+
+ SCR1_DBG_HARTINFO: begin
+ dm2dmi_rdata_o[SCR1_DBG_HARTINFO_RESERVEDB_HI:
+ SCR1_DBG_HARTINFO_RESERVEDB_LO] = HARTINFO_RESERVEDB;
+ dm2dmi_rdata_o[SCR1_DBG_HARTINFO_NSCRATCH_HI:
+ SCR1_DBG_HARTINFO_NSCRATCH_LO] = HARTINFO_NSCRATCH;
+ dm2dmi_rdata_o[SCR1_DBG_HARTINFO_RESERVEDA_HI:
+ SCR1_DBG_HARTINFO_RESERVEDA_LO] = HARTINFO_RESERVEDA;
+ dm2dmi_rdata_o[SCR1_DBG_HARTINFO_DATAACCESS] = HARTINFO_DATAACCESS;
+ dm2dmi_rdata_o[SCR1_DBG_HARTINFO_DATASIZE_HI:
+ SCR1_DBG_HARTINFO_DATASIZE_LO] = HARTINFO_DATASIZE;
+ dm2dmi_rdata_o[SCR1_DBG_HARTINFO_DATAADDR_HI:
+ SCR1_DBG_HARTINFO_DATAADDR_LO] = HARTINFO_DATAADDR;
+ end
+
+ SCR1_DBG_ABSTRACTAUTO: dm2dmi_rdata_o[0] = abs_autoexec_ff;
+ SCR1_DBG_DATA0 : dm2dmi_rdata_o = abs_data0_ff;
+ SCR1_DBG_DATA1 : dm2dmi_rdata_o = abs_data1_ff;
+ SCR1_DBG_PROGBUF0 : dm2dmi_rdata_o = abs_progbuf0_ff;
+ SCR1_DBG_PROGBUF1 : dm2dmi_rdata_o = abs_progbuf1_ff;
+ SCR1_DBG_PROGBUF2 : dm2dmi_rdata_o = abs_progbuf2_ff;
+ SCR1_DBG_PROGBUF3 : dm2dmi_rdata_o = abs_progbuf3_ff;
+ SCR1_DBG_PROGBUF4 : dm2dmi_rdata_o = abs_progbuf4_ff;
+ SCR1_DBG_PROGBUF5 : dm2dmi_rdata_o = abs_progbuf5_ff;
+ SCR1_DBG_HALTSUM0 : dm2dmi_rdata_o[0] = dmstatus_allany_halted_ff;
+
+ default: begin
+ dm2dmi_rdata_o = '0;
+ end
+ endcase
+end
+
+// Response
+assign dm2dmi_resp_o = 1'b1;
+
+// Write requests signals
+//------------------------------------------------------------------------------
+
+assign dmcontrol_wr_req = dmi_req_dmcontrol & dmi2dm_wr_i;
+assign data0_wr_req = dmi_req_data0 & dmi2dm_wr_i;
+assign data1_wr_req = dmi_req_data1 & dmi2dm_wr_i;
+assign dreg_wr_req = pipe2dm_dreg_req_i & pipe2dm_dreg_wr_i;
+assign command_wr_req = dmi_req_command & dmi2dm_wr_i;
+assign autoexec_wr_req = dmi_req_abstractauto & dmi2dm_wr_i;
+assign progbuf0_wr_req = dmi_req_progbuf0 & dmi2dm_wr_i;
+assign progbuf1_wr_req = dmi_req_progbuf1 & dmi2dm_wr_i;
+assign progbuf2_wr_req = dmi_req_progbuf2 & dmi2dm_wr_i;
+assign progbuf3_wr_req = dmi_req_progbuf3 & dmi2dm_wr_i;
+assign progbuf4_wr_req = dmi_req_progbuf4 & dmi2dm_wr_i;
+assign progbuf5_wr_req = dmi_req_progbuf5 & dmi2dm_wr_i;
+assign abstractcs_wr_req = dmi_req_abstractcs & dmi2dm_wr_i;
+
+// HART state signals
+//------------------------------------------------------------------------------
+
+assign hart_state_reset = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_RESET);
+assign hart_state_run = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_RUN);
+assign hart_state_dhalt = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_DHALTED);
+assign hart_state_drun = (pipe2dm_hart_status_i.dbg_state == SCR1_HDU_DBGSTATE_DRUN);
+
+//------------------------------------------------------------------------------
+// DM registers
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - DM clock enable register
+ // - Auxilary Skip Reset On Powerup register
+ // - DMCONTROL register
+ // - DMSTATUS register
+
+// DM clock enable logic
+//------------------------------------------------------------------------------
+
+assign clk_en_dm = dmcontrol_wr_req | dmcontrol_dmactive_ff | clk_en_dm_ff;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ clk_en_dm_ff <= 1'b0;
+ end else if (clk_en_dm) begin
+ clk_en_dm_ff <= dmcontrol_dmactive_ff;
+ end
+end
+
+assign dm2pipe_active_o = clk_en_dm_ff;
+
+// DMCONTROL register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ dmcontrol_dmactive_ff <= 1'b0;
+ dmcontrol_ndmreset_ff <= 1'b0;
+ dmcontrol_ackhavereset_ff <= 1'b0;
+ dmcontrol_haltreq_ff <= 1'b0;
+ dmcontrol_resumereq_ff <= 1'b0;
+ end else if (clk_en_dm) begin
+ dmcontrol_dmactive_ff <= dmcontrol_dmactive_next;
+ dmcontrol_ndmreset_ff <= dmcontrol_ndmreset_next;
+ dmcontrol_ackhavereset_ff <= dmcontrol_ackhavereset_next;
+ dmcontrol_haltreq_ff <= dmcontrol_haltreq_next;
+ dmcontrol_resumereq_ff <= dmcontrol_resumereq_next;
+ end
+end
+
+assign dmcontrol_dmactive_next = dmcontrol_wr_req
+ ? dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_DMACTIVE]
+ : dmcontrol_dmactive_ff;
+
+always_comb begin
+ dmcontrol_ndmreset_next = dmcontrol_ndmreset_ff;
+ dmcontrol_ackhavereset_next = dmcontrol_ackhavereset_ff;
+ dmcontrol_haltreq_next = dmcontrol_haltreq_ff;
+ dmcontrol_resumereq_next = dmcontrol_resumereq_ff;
+ if (~dmcontrol_dmactive_ff) begin
+ dmcontrol_ndmreset_next = 1'b0;
+ dmcontrol_ackhavereset_next = 1'b0;
+ dmcontrol_haltreq_next = 1'b0;
+ dmcontrol_resumereq_next = 1'b0;
+ end else if (dmcontrol_wr_req) begin
+ dmcontrol_ndmreset_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_NDMRESET];
+ dmcontrol_ackhavereset_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_ACKHAVERESET];
+ dmcontrol_haltreq_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_HALTREQ];
+ dmcontrol_resumereq_next = dmi2dm_wdata_i[SCR1_DBG_DMCONTROL_RESUMEREQ];
+ end
+end
+
+// Reset signal for system controlled by Debug Module
+assign hart_rst_n_o = ~dmcontrol_ndmreset_ff;
+assign ndm_rst_n_o = ~dmcontrol_ndmreset_ff;
+
+// Skip reset on powerup register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ havereset_skip_pwrup_ff <= 1'b1;
+ end else if (clk_en_dm) begin
+ havereset_skip_pwrup_ff <= havereset_skip_pwrup_next;
+ end
+end
+
+assign havereset_skip_pwrup_next = ~dmcontrol_dmactive_ff ? 1'b1
+ : havereset_skip_pwrup_ff ? hart_state_reset & ndm_rst_n_o & hart_rst_n_o
+ : havereset_skip_pwrup_ff;
+
+// DMSTATUS register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ dmstatus_allany_havereset_ff <= 1'b0;
+ dmstatus_allany_resumeack_ff <= 1'b0;
+ dmstatus_allany_halted_ff <= 1'b0;
+ end else if (clk_en_dm) begin
+ dmstatus_allany_havereset_ff <= dmstatus_allany_havereset_next;
+ dmstatus_allany_resumeack_ff <= dmstatus_allany_resumeack_next;
+ dmstatus_allany_halted_ff <= dmstatus_allany_halted_next;
+ end
+end
+
+assign dmstatus_allany_havereset_next = ~dmcontrol_dmactive_ff ? 1'b0
+ : ~havereset_skip_pwrup_ff & hart_state_reset ? 1'b1
+ : dmcontrol_ackhavereset_ff ? 1'b0
+ : dmstatus_allany_havereset_ff;
+assign dmstatus_allany_resumeack_next = ~dmcontrol_dmactive_ff ? 1'b0
+ : ~dmcontrol_resumereq_ff ? 1'b0
+ : hart_state_run ? 1'b1
+ : dmstatus_allany_resumeack_ff;
+
+assign dmstatus_allany_halted_next = ~dmcontrol_dmactive_ff ? 1'b0
+ : hart_state_dhalt ? 1'b1
+ : hart_state_run ? 1'b0
+ : dmstatus_allany_halted_ff;
+
+//------------------------------------------------------------------------------
+// Abstract Command control logic
+//------------------------------------------------------------------------------
+//
+ // Consists of the following functional units:
+ // - Abstract command decoder
+ // - Abstract command access valid flags
+ // - Abstract command control registers
+
+assign clk_en_abs = clk_en_dm & dmcontrol_dmactive_ff;
+
+// Abstract command decoder
+//------------------------------------------------------------------------------
+
+assign abs_cmd = dmi_req_command ? dmi2dm_wdata_i : abs_command_ff;
+
+always_comb begin
+ abs_cmd_regno = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_REGNO_LO +: 12];
+
+ abs_cmd_csr_ro = (abs_cmd_regno == SCR1_CSR_ADDR_MISA)
+ | (abs_cmd_regno == SCR1_CSR_ADDR_MVENDORID)
+ | (abs_cmd_regno == SCR1_CSR_ADDR_MARCHID)
+ | (abs_cmd_regno == SCR1_CSR_ADDR_MIMPID)
+ | (abs_cmd_regno == SCR1_CSR_ADDR_MHARTID)
+ | (abs_cmd_regno == SCR1_HDU_DBGCSR_ADDR_DPC);
+
+ abs_cmd_type = abs_cmd[SCR1_DBG_COMMAND_TYPE_HI:SCR1_DBG_COMMAND_TYPE_LO];
+ abs_cmd_regacs = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_TRANSFER];
+ abs_cmd_regtype = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_REGNO_HI:12];
+ abs_cmd_regfile = abs_cmd[11:5];
+ abs_cmd_regsize = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_SIZE_HI:
+ SCR1_DBG_COMMAND_ACCESSREG_SIZE_LO];
+ abs_cmd_regwr = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_WRITE];
+ abs_cmd_execprogbuf = abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_POSTEXEC];
+
+ abs_cmd_regvalid = ~(|{abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_RESERVEDB],
+ abs_cmd[SCR1_DBG_COMMAND_ACCESSREG_RESERVEDA]});
+
+ abs_cmd_memsize = abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_HI:
+ SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_LO];
+ abs_cmd_memwr = abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_WRITE];
+
+ abs_cmd_memvalid = ~(|{abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_AAMVIRTUAL],
+ abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_AAMPOSTINC],
+ abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_HI:
+ SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_HI],
+ abs_cmd[SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_HI:
+ SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_HI]});
+end
+
+assign abs_reg_access_csr = (abs_cmd_regtype == ABS_CMD_HARTREG_CSR);
+assign abs_reg_access_mprf = (abs_cmd_regtype == ABS_CMD_HARTREG_INTFPU)
+ & (abs_cmd_regfile == ABS_CMD_HARTREG_INT);
+
+// Abstract command access request and valid flags
+//------------------------------------------------------------------------------
+
+assign abs_cmd_regsize_vd = (abs_cmd_regsize == 3'h2);
+assign abs_cmd_memsize_vd = (abs_cmd_memsize < 3'h3);
+
+assign abs_cmd_hartreg_vd = (abs_cmd_type == ABS_CMD_HARTREG) & abs_cmd_regvalid;
+assign abs_cmd_hartmem_vd = (abs_cmd_type == ABS_CMD_HARTMEM) & abs_cmd_memvalid;
+
+// Abstract command requests
+assign abs_cmd_reg_access_req = abs_cmd_hartreg_vd & abs_cmd_regacs;
+assign abs_cmd_csr_access_req = abs_cmd_reg_access_req & abs_reg_access_csr;
+assign abs_cmd_mprf_access_req = abs_cmd_reg_access_req & abs_reg_access_mprf;
+assign abs_cmd_execprogbuf_req = abs_cmd_hartreg_vd & abs_cmd_execprogbuf;
+
+// Abstract command access valid flags
+assign abs_cmd_csr_ro_access_vd = abs_cmd_csr_access_req & abs_cmd_regsize_vd & ~abs_cmd_regwr
+ & ~abs_cmd_execprogbuf & abs_cmd_csr_ro & hart_state_run;
+assign abs_cmd_csr_rw_access_vd = abs_cmd_csr_access_req & abs_cmd_regsize_vd
+ & (abs_cmd_regwr | ~abs_cmd_csr_ro_access_vd);
+assign abs_cmd_mprf_access_vd = abs_cmd_mprf_access_req & abs_cmd_regsize_vd;
+assign abs_cmd_mem_access_vd = abs_cmd_hartmem_vd & abs_cmd_memsize_vd;
+
+// Abstract command control registers
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_abs & abs_fsm_idle) begin
+ abs_cmd_postexec_ff <= abs_cmd_postexec_next;
+ abs_cmd_wr_ff <= abs_cmd_wr_next;
+ abs_cmd_regno_ff <= abs_cmd_regno;
+ abs_cmd_size_ff <= abs_cmd_size_next;
+ end
+end
+
+always_comb begin
+ abs_cmd_wr_next = 1'b0;
+ abs_cmd_postexec_next = 1'b0;
+ abs_cmd_size_next = abs_cmd_size_ff;
+ if ((command_wr_req | dmi_rpt_command) & hart_state_dhalt & abs_fsm_idle) begin
+ if (abs_cmd_csr_rw_access_vd) begin
+ abs_cmd_wr_next = abs_cmd_regwr;
+ abs_cmd_postexec_next = abs_cmd_execprogbuf;
+ end else if (abs_cmd_mprf_access_vd) begin
+ abs_cmd_wr_next = abs_cmd_regwr;
+ abs_cmd_size_next = abs_cmd_regsize[1:0];
+ abs_cmd_postexec_next = abs_cmd_execprogbuf;
+ end else if (abs_cmd_mem_access_vd) begin
+ abs_cmd_wr_next = abs_cmd_memwr;
+ abs_cmd_size_next = abs_cmd_memsize[1:0];
+ end
+ end
+end
+
+//------------------------------------------------------------------------------
+// Abstract command FSM
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_dm) begin
+ if (~dmcontrol_dmactive_ff) begin
+ abs_fsm_ff <= ABS_STATE_IDLE;
+ end else begin
+ abs_fsm_ff <= abs_fsm_next;
+ end
+ end
+end
+
+always_comb begin
+ abs_fsm_next = abs_fsm_ff;
+
+ case (abs_fsm_ff)
+ ABS_STATE_IDLE: begin
+ if (command_wr_req | dmi_rpt_command) begin
+ case (1'b1)
+ abs_cmd_csr_ro_access_vd: abs_fsm_next = ABS_STATE_CSR_RO;
+ abs_cmd_csr_rw_access_vd: abs_fsm_next = hart_state_dhalt ? ABS_STATE_CSR_SAVE_XREG : ABS_STATE_ERR;
+ abs_cmd_mprf_access_vd : abs_fsm_next = hart_state_dhalt ? ABS_STATE_XREG_RW : ABS_STATE_ERR;
+ abs_cmd_execprogbuf_req : abs_fsm_next = ABS_STATE_EXEC;
+ abs_cmd_mem_access_vd : abs_fsm_next = hart_state_dhalt ? ABS_STATE_MEM_SAVE_XREG : ABS_STATE_ERR;
+ default : abs_fsm_next = ABS_STATE_ERR;
+ endcase
+ end
+ end
+
+ ABS_STATE_EXEC: begin
+ if (dhi_resp) begin
+ if (dhi_resp_exc | abs_err_acc_busy_ff) begin
+ abs_fsm_next = ABS_STATE_ERR;
+ end else begin
+ abs_fsm_next = ABS_STATE_IDLE;
+ end
+ end
+ end
+
+ ABS_STATE_XREG_RW: begin
+ if (dhi_resp) begin
+ case (1'b1)
+ abs_err_acc_busy_ff: abs_fsm_next = ABS_STATE_ERR;
+ abs_cmd_postexec_ff: abs_fsm_next = ABS_STATE_EXEC;
+ default : abs_fsm_next = ABS_STATE_IDLE;
+ endcase
+ end
+ end
+
+ ABS_STATE_CSR_RO : abs_fsm_next = abs_err_acc_busy_ff ? ABS_STATE_ERR : ABS_STATE_IDLE;
+ ABS_STATE_CSR_SAVE_XREG: abs_fsm_next = dhi_resp ? ABS_STATE_CSR_RW : ABS_STATE_CSR_SAVE_XREG;
+ ABS_STATE_CSR_RW : abs_fsm_next = dhi_resp ? ABS_STATE_CSR_RETURN_XREG : ABS_STATE_CSR_RW;
+
+ ABS_STATE_CSR_RETURN_XREG: begin
+ if (dhi_resp) begin
+ case (1'b1)
+ abs_err_exc_ff : abs_fsm_next = ABS_STATE_ERR;
+ abs_err_acc_busy_ff : abs_fsm_next = ABS_STATE_ERR;
+ abs_cmd_postexec_ff : abs_fsm_next = ABS_STATE_EXEC;
+ default : abs_fsm_next = ABS_STATE_IDLE;
+ endcase
+ end
+ end
+
+ ABS_STATE_MEM_SAVE_XREG : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_SAVE_XREG_FORADDR : ABS_STATE_MEM_SAVE_XREG;
+ ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_RW : ABS_STATE_MEM_SAVE_XREG_FORADDR;
+ ABS_STATE_MEM_RW : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_RETURN_XREG : ABS_STATE_MEM_RW;
+ ABS_STATE_MEM_RETURN_XREG : abs_fsm_next = dhi_resp ? ABS_STATE_MEM_RETURN_XREG_FORADDR : ABS_STATE_MEM_RETURN_XREG;
+
+ ABS_STATE_MEM_RETURN_XREG_FORADDR: begin
+ if (dhi_resp) begin
+ case (1'b1)
+ abs_err_exc_ff: abs_fsm_next = ABS_STATE_ERR;
+ abs_err_acc_busy_ff : abs_fsm_next = ABS_STATE_ERR;
+ abs_cmd_postexec_ff : abs_fsm_next = ABS_STATE_EXEC;
+ default : abs_fsm_next = ABS_STATE_IDLE;
+ endcase
+ end
+ end
+
+ ABS_STATE_ERR: begin
+ if (abstractcs_wr_req & (abstractcs_cmderr_next == 3'b0)) begin
+ abs_fsm_next = ABS_STATE_IDLE;
+ end
+ end
+ endcase
+
+ if (~abs_fsm_idle & hart_state_reset) begin
+ abs_fsm_next = ABS_STATE_ERR;
+ end
+end
+
+assign abs_fsm_idle = (abs_fsm_ff == ABS_STATE_IDLE);
+assign abs_fsm_exec = (abs_fsm_ff == ABS_STATE_EXEC);
+assign abs_fsm_csr_ro = (abs_fsm_ff == ABS_STATE_CSR_RO);
+assign abs_fsm_err = (abs_fsm_ff == ABS_STATE_ERR);
+assign abs_fsm_use_addr = (abs_fsm_ff == ABS_STATE_MEM_SAVE_XREG_FORADDR)
+ | (abs_fsm_ff == ABS_STATE_MEM_RETURN_XREG_FORADDR);
+
+//------------------------------------------------------------------------------
+// Abstract command status logic
+//------------------------------------------------------------------------------
+
+// Abstract command access busy error register
+//------------------------------------------------------------------------------
+
+assign abs_err_acc_busy_upd = clk_en_abs & (abs_fsm_idle | dmi_req_any);
+
+always_ff @(posedge clk) begin
+ if (abs_err_acc_busy_upd) abs_err_acc_busy_ff <= abs_err_acc_busy_next;
+end
+
+assign abs_err_acc_busy_next = ~abs_fsm_idle & dmi_req_any;
+
+// Abstract command access exception error register
+//------------------------------------------------------------------------------
+
+assign abs_err_exc_upd = clk_en_abs & (abs_fsm_idle | (dhi_resp & dhi_resp_exc));
+
+always_ff @(posedge clk) begin
+ if (abs_err_exc_upd) abs_err_exc_ff <= abs_err_exc_next;
+end
+
+assign abs_err_exc_next = ~abs_fsm_idle & dhi_resp & dhi_resp_exc;
+
+//------------------------------------------------------------------------------
+// Abstract Instruction logic
+//------------------------------------------------------------------------------
+//
+ // Cosists of the following functional units:
+ // - Instruction execution request register
+ // - Instruction memory FUNCT3 field multiplexer
+ // - Instruction RS1 multiplexer
+ // - Instruction RD multiplexer
+ // - Abstract Instruction register
+
+// Abstract instruction execution request register
+//------------------------------------------------------------------------------
+
+assign abs_exec_req_next = ~(abs_fsm_idle | abs_fsm_csr_ro | abs_fsm_err) & ~dhi_resp;
+
+always_ff @(posedge clk) begin
+ if (clk_en_dm) begin
+ if (~dmcontrol_dmactive_ff) begin
+ abs_exec_req_ff <= 1'b0;
+ end else begin
+ abs_exec_req_ff <= abs_exec_req_next;
+ end
+ end
+end
+
+// Abstract instruction memory FUNCT3 field multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ case (abs_cmd_size_ff)
+ 2'b00 : abs_instr_mem_funct3 = abs_cmd_wr_ff ? SCR1_FUNCT3_SB : SCR1_FUNCT3_LBU;
+ 2'b01 : abs_instr_mem_funct3 = abs_cmd_wr_ff ? SCR1_FUNCT3_SH : SCR1_FUNCT3_LHU;
+ 2'b10 : abs_instr_mem_funct3 = abs_cmd_wr_ff ? SCR1_FUNCT3_SW : SCR1_FUNCT3_LW;
+ default: abs_instr_mem_funct3 = SCR1_FUNCT3_SB;
+ endcase
+end
+
+// Abstract instruction RS1 multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ abs_instr_rs1 = 5'h0;
+ case (abs_fsm_ff)
+ ABS_STATE_XREG_RW : abs_instr_rs1 = abs_cmd_wr_ff ? 5'h0 : abs_cmd_regno_ff[4:0];
+ ABS_STATE_CSR_SAVE_XREG : abs_instr_rs1 = 5'h5;
+ ABS_STATE_MEM_SAVE_XREG : abs_instr_rs1 = 5'h5;
+ ABS_STATE_CSR_RETURN_XREG : abs_instr_rs1 = 5'h5;
+ ABS_STATE_MEM_RETURN_XREG : abs_instr_rs1 = 5'h5;
+ ABS_STATE_CSR_RW : abs_instr_rs1 = abs_cmd_wr_ff ? 5'h5 : 5'h0;
+ ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_instr_rs1 = 5'h6;
+ ABS_STATE_MEM_RETURN_XREG_FORADDR: abs_instr_rs1 = 5'h6;
+ ABS_STATE_MEM_RW : abs_instr_rs1 = 5'h6;
+ default : begin end
+ endcase
+end
+
+assign abs_instr_rs2 = 5'h5;
+
+// Abstract instruction RD multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ abs_instr_rd = 5'h0;
+ case (abs_fsm_ff)
+ ABS_STATE_XREG_RW : abs_instr_rd = abs_cmd_wr_ff ? abs_cmd_regno_ff[4:0] : 5'h0;
+ ABS_STATE_CSR_SAVE_XREG : abs_instr_rd = abs_cmd_wr_ff ? 5'h5 : 5'h0;
+ ABS_STATE_MEM_SAVE_XREG : abs_instr_rd = abs_cmd_wr_ff ? 5'h5 : 5'h0;
+ ABS_STATE_CSR_RW : abs_instr_rd = abs_cmd_wr_ff ? 5'h0 : 5'h5;
+ ABS_STATE_MEM_RW : abs_instr_rd = abs_cmd_wr_ff ? 5'h0 : 5'h5;
+ ABS_STATE_CSR_RETURN_XREG : abs_instr_rd = 5'h5;
+ ABS_STATE_MEM_RETURN_XREG : abs_instr_rd = 5'h5;
+ ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_instr_rd = 5'h6;
+ ABS_STATE_MEM_RETURN_XREG_FORADDR: abs_instr_rd = 5'h6;
+ default : begin end
+ endcase
+end
+
+// Abstract instruction register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_abs) begin
+ abs_exec_instr_ff <= abs_exec_instr_next;
+ end
+end
+
+always_comb begin
+ abs_exec_instr_next = abs_exec_instr_ff;
+ case (abs_fsm_ff)
+ ABS_STATE_XREG_RW,
+ ABS_STATE_CSR_SAVE_XREG,
+ ABS_STATE_CSR_RETURN_XREG,
+ ABS_STATE_MEM_SAVE_XREG,
+ ABS_STATE_MEM_SAVE_XREG_FORADDR,
+ ABS_STATE_MEM_RETURN_XREG,
+ ABS_STATE_MEM_RETURN_XREG_FORADDR: begin
+ abs_exec_instr_next = {SCR1_HDU_DBGCSR_ADDR_DSCRATCH0, abs_instr_rs1, SCR1_FUNCT3_CSRRW, abs_instr_rd, SCR1_OP_SYSTEM};
+ end
+
+ ABS_STATE_CSR_RW: begin
+ abs_exec_instr_next = abs_cmd_wr_ff
+ ? {abs_cmd_regno_ff[11:0], abs_instr_rs1, SCR1_FUNCT3_CSRRW, abs_instr_rd, SCR1_OP_SYSTEM}
+ : {abs_cmd_regno_ff[11:0], abs_instr_rs1, SCR1_FUNCT3_CSRRS, abs_instr_rd, SCR1_OP_SYSTEM};
+ end
+
+ ABS_STATE_MEM_RW: begin
+ abs_exec_instr_next = abs_cmd_wr_ff
+ ? {7'h0, abs_instr_rs2, abs_instr_rs1, abs_instr_mem_funct3, 5'h0, SCR1_OP_STORE}
+ : {12'h0, abs_instr_rs1, abs_instr_mem_funct3, abs_instr_rd, SCR1_OP_LOAD};
+ end
+
+ default: begin end
+ endcase
+end
+
+//------------------------------------------------------------------------------
+// Abstract registers
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - ABSTRACTCS register
+ // - COMMAND register
+ // - ABSTRACTAUTO register
+ // - PROGBUF0..5 registers
+ // - DATA0..1 registers
+
+// ABSTRACTCS register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_dm) begin
+ if (~dmcontrol_dmactive_ff) begin
+ abstractcs_cmderr_ff <= ABS_ERR_NONE;
+ end else begin
+ abstractcs_cmderr_ff <= abstractcs_cmderr_next;
+ end
+ end
+end
+
+always_comb begin
+ abstractcs_cmderr_next = abstractcs_cmderr_ff;
+
+ case (abs_fsm_ff)
+ ABS_STATE_IDLE: begin
+ if (command_wr_req | dmi_rpt_command) begin
+ if (abs_cmd_hartreg_vd) begin
+ case (1'b1)
+ abs_cmd_reg_access_req : begin
+ case (1'b1)
+ abs_cmd_csr_rw_access_vd: abstractcs_cmderr_next = hart_state_dhalt
+ ? abstractcs_cmderr_ff
+ : ABS_ERR_NOHALT;
+ abs_cmd_mprf_access_vd : abstractcs_cmderr_next = hart_state_dhalt
+ ? abstractcs_cmderr_ff
+ : ABS_ERR_NOHALT;
+ abs_cmd_csr_ro_access_vd: abstractcs_cmderr_next = abstractcs_cmderr_ff;
+ default : abstractcs_cmderr_next = ABS_ERR_CMD;
+ endcase
+ end
+ abs_cmd_execprogbuf_req : abstractcs_cmderr_next = abstractcs_cmderr_ff;
+ default : abstractcs_cmderr_next = ABS_ERR_CMD;
+ endcase
+ end else if (abs_cmd_hartmem_vd) begin
+ abstractcs_cmderr_next = ~abs_cmd_memsize_vd ? ABS_ERR_CMD
+ : ~hart_state_dhalt ? ABS_ERR_NOHALT
+ : abstractcs_cmderr_ff;
+ end else begin
+ abstractcs_cmderr_next = ABS_ERR_CMD;
+ end
+ end
+ end
+
+ ABS_STATE_EXEC: begin
+ if (dhi_resp) begin
+ if (dhi_resp_exc) begin
+ abstractcs_cmderr_next = ABS_ERR_EXCEPTION;
+ end else if (abs_err_acc_busy_ff) begin
+ abstractcs_cmderr_next = ABS_ERR_BUSY;
+ end
+ end
+ end
+
+ ABS_STATE_XREG_RW,
+ ABS_STATE_CSR_RO: begin
+ if (abs_err_acc_busy_ff) begin
+ abstractcs_cmderr_next = ABS_ERR_BUSY;
+ end
+ end
+
+ ABS_STATE_CSR_RETURN_XREG,
+ ABS_STATE_MEM_RETURN_XREG_FORADDR: begin
+ if (dhi_resp) begin
+ case (1'b1)
+ abs_err_exc_ff : abstractcs_cmderr_next = ABS_ERR_EXCEPTION;
+ abs_err_acc_busy_ff: abstractcs_cmderr_next = ABS_ERR_BUSY;
+ default: abstractcs_cmderr_next = abstractcs_cmderr_ff;
+ endcase
+ end
+ end
+
+ ABS_STATE_ERR: begin
+ if (dmi_req_abstractcs & dmi2dm_wr_i) begin
+ abstractcs_cmderr_next = type_scr1_abs_err_e'(logic'(abstractcs_cmderr_ff)
+ & (~dmi2dm_wdata_i[SCR1_DBG_ABSTRACTCS_CMDERR_HI:
+ SCR1_DBG_ABSTRACTCS_CMDERR_LO]));
+ end
+ end
+
+ default: begin
+ end
+ endcase
+
+ if (~abs_fsm_idle & hart_state_reset) begin
+ abstractcs_cmderr_next = ABS_ERR_EXCEPTION;
+ end
+end
+
+assign abstractcs_busy = ~abs_fsm_idle & ~abs_fsm_err;
+
+// Abstract COMMAND register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_dm) abs_command_ff <= abs_command_next;
+end
+
+assign abs_command_next = ~dmcontrol_dmactive_ff ? '0
+ : (command_wr_req & abs_fsm_idle) ? dmi2dm_wdata_i
+ : abs_command_ff;
+
+// Abstract ABSTRACTAUTO register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_dm) abs_autoexec_ff <= abs_autoexec_next;
+end
+
+assign abs_autoexec_next = ~dmcontrol_dmactive_ff ? 1'b0
+ : (autoexec_wr_req & abs_fsm_idle) ? dmi2dm_wdata_i[0]
+ : abs_autoexec_ff;
+
+// Program Buffer registers
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_abs & abs_fsm_idle) begin
+ if (progbuf0_wr_req) abs_progbuf0_ff <= dmi2dm_wdata_i;
+ if (progbuf1_wr_req) abs_progbuf1_ff <= dmi2dm_wdata_i;
+ if (progbuf2_wr_req) abs_progbuf2_ff <= dmi2dm_wdata_i;
+ if (progbuf3_wr_req) abs_progbuf3_ff <= dmi2dm_wdata_i;
+ if (progbuf4_wr_req) abs_progbuf4_ff <= dmi2dm_wdata_i;
+ if (progbuf5_wr_req) abs_progbuf5_ff <= dmi2dm_wdata_i;
+ end
+end
+
+// Data 0 register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_abs) begin
+ abs_data0_ff <= abs_data0_next;
+ end
+end
+
+assign data0_xreg_save = dreg_wr_req & ~abs_cmd_wr_ff;
+
+always_comb begin
+ abs_data0_next = abs_data0_ff;
+
+ case (abs_fsm_ff)
+ ABS_STATE_IDLE : abs_data0_next = data0_wr_req ? dmi2dm_wdata_i : abs_data0_ff;
+ ABS_STATE_EXEC : abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff;
+ ABS_STATE_CSR_SAVE_XREG : abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff;
+ ABS_STATE_CSR_RETURN_XREG: abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff;
+ ABS_STATE_MEM_SAVE_XREG : abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff;
+ ABS_STATE_MEM_RETURN_XREG: abs_data0_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data0_ff;
+ ABS_STATE_XREG_RW : abs_data0_next = data0_xreg_save ? pipe2dm_dreg_wdata_i : abs_data0_ff;
+
+ ABS_STATE_CSR_RO: begin
+ case (abs_cmd_regno_ff[11:0])
+ SCR1_CSR_ADDR_MISA : abs_data0_next = SCR1_CSR_MISA;
+ SCR1_CSR_ADDR_MVENDORID: abs_data0_next = SCR1_CSR_MVENDORID;
+ SCR1_CSR_ADDR_MARCHID : abs_data0_next = SCR1_CSR_MARCHID;
+ SCR1_CSR_ADDR_MIMPID : abs_data0_next = SCR1_CSR_MIMPID;
+ SCR1_CSR_ADDR_MHARTID : abs_data0_next = soc2dm_fuse_mhartid_i;
+ default : abs_data0_next = pipe2dm_pc_sample_i;
+ endcase
+ end
+
+ default : begin end
+ endcase
+end
+
+// Data 1 register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_abs) begin
+ abs_data1_ff <= abs_data1_next;
+ end
+end
+
+always_comb begin
+ abs_data1_next = abs_data1_ff;
+ case (abs_fsm_ff)
+ ABS_STATE_IDLE : abs_data1_next = data1_wr_req ? dmi2dm_wdata_i : abs_data1_ff;
+ ABS_STATE_MEM_SAVE_XREG_FORADDR : abs_data1_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data1_ff;
+ ABS_STATE_MEM_RETURN_XREG_FORADDR: abs_data1_next = dreg_wr_req ? pipe2dm_dreg_wdata_i : abs_data1_ff;
+ default : begin end
+ endcase
+end
+
+//------------------------------------------------------------------------------
+// Debug Hart Interface : control
+//------------------------------------------------------------------------------
+
+assign cmd_resp_ok = pipe2dm_cmd_resp_i & ~pipe2dm_cmd_rcode_i;
+assign hart_rst_unexp = ~dhi_fsm_idle & ~dhi_fsm_halt_req & hart_state_reset;
+
+assign halt_req_vd = dmcontrol_haltreq_ff & ~hart_state_dhalt;
+assign resume_req_vd = dmcontrol_resumereq_ff & ~dmstatus_allany_resumeack_ff
+ & hart_state_dhalt;
+
+// DHI fsm
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ dhi_fsm_ff <= DHI_STATE_IDLE;
+ end else if (clk_en_dm) begin
+ dhi_fsm_ff <= dhi_fsm_next;
+ end
+end
+
+always_comb begin
+ dhi_fsm_next = dhi_fsm_ff;
+ if (~hart_rst_unexp & dmcontrol_dmactive_ff) begin
+ // Normal work
+ case (dhi_fsm_ff)
+ DHI_STATE_IDLE : dhi_fsm_next = dhi_req;
+ DHI_STATE_EXEC : dhi_fsm_next = cmd_resp_ok ? DHI_STATE_EXEC_RUN : DHI_STATE_EXEC;
+ DHI_STATE_EXEC_RUN : dhi_fsm_next = hart_state_drun ? DHI_STATE_EXEC_HALT : DHI_STATE_EXEC_RUN;
+ DHI_STATE_HALT_REQ : dhi_fsm_next = cmd_resp_ok ? DHI_STATE_EXEC_HALT : DHI_STATE_HALT_REQ;
+ DHI_STATE_EXEC_HALT : dhi_fsm_next = hart_state_dhalt ? DHI_STATE_IDLE : DHI_STATE_EXEC_HALT;
+ DHI_STATE_RESUME_REQ: dhi_fsm_next = cmd_resp_ok ? DHI_STATE_RESUME_RUN : DHI_STATE_RESUME_REQ;
+ DHI_STATE_RESUME_RUN: dhi_fsm_next = hart_state_run ? DHI_STATE_IDLE : DHI_STATE_RESUME_RUN;
+ default : dhi_fsm_next = dhi_fsm_ff;
+ endcase
+ end else begin
+ // In case of DM reset or core unexpected reset
+ dhi_fsm_next = DHI_STATE_IDLE;
+ end
+end
+
+assign dhi_fsm_idle = (dhi_fsm_ff == DHI_STATE_IDLE);
+assign dhi_fsm_halt_req = (dhi_fsm_ff == DHI_STATE_HALT_REQ);
+assign dhi_fsm_exec = (dhi_fsm_ff == DHI_STATE_EXEC);
+assign dhi_fsm_exec_halt = (dhi_fsm_ff == DHI_STATE_EXEC_HALT);
+assign dhi_fsm_resume_req = (dhi_fsm_ff == DHI_STATE_RESUME_REQ);
+
+always_comb begin
+ case (1'b1)
+ abs_exec_req_ff: dhi_req = DHI_STATE_EXEC;
+ halt_req_vd : dhi_req = DHI_STATE_HALT_REQ;
+ resume_req_vd : dhi_req = DHI_STATE_RESUME_REQ;
+ default : dhi_req = DHI_STATE_IDLE;
+ endcase
+end
+
+assign dhi_resp = dhi_fsm_exec_halt & hart_state_dhalt;
+assign dhi_resp_exc = pipe2dm_hart_event_i & pipe2dm_hart_status_i.except
+ & ~pipe2dm_hart_status_i.ebreak;
+
+// HART command registers
+//------------------------------------------------------------------------------
+
+// HART command request register
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ hart_cmd_req_ff <= 1'b0;
+ end else if (clk_en_dm) begin
+ hart_cmd_req_ff <= hart_cmd_req_next;
+ end
+end
+
+assign hart_cmd_req_next = (dhi_fsm_exec | dhi_fsm_halt_req | dhi_fsm_resume_req)
+ & ~cmd_resp_ok & dmcontrol_dmactive_ff;
+
+// HART command register
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ hart_cmd_ff <= SCR1_HDU_DBGSTATE_RUN;
+ end else if (clk_en_dm) begin
+ hart_cmd_ff <= hart_cmd_next;
+ end
+end
+
+always_comb begin
+ hart_cmd_next = SCR1_HDU_DBGSTATE_RUN;
+ if (dmcontrol_dmactive_ff) begin
+ case (dhi_fsm_ff)
+ DHI_STATE_EXEC : hart_cmd_next = SCR1_HDU_DBGSTATE_DRUN;
+ DHI_STATE_HALT_REQ : hart_cmd_next = SCR1_HDU_DBGSTATE_DHALTED;
+ DHI_STATE_RESUME_REQ: hart_cmd_next = SCR1_HDU_DBGSTATE_RUN;
+ default : hart_cmd_next = dm2pipe_cmd_o;
+ endcase
+ end
+end
+
+assign dm2pipe_cmd_req_o = hart_cmd_req_ff;
+assign dm2pipe_cmd_o = hart_cmd_ff;
+
+//------------------------------------------------------------------------------
+// Debug Hart Interface : program buffer
+//------------------------------------------------------------------------------
+
+// Program Buffer execution EBREAK flag
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk) begin
+ if (clk_en_dm) hart_pbuf_ebreak_ff <= hart_pbuf_ebreak_next;
+end
+
+assign hart_pbuf_ebreak_next = abs_fsm_exec & (dm2pipe_pbuf_instr_o == ABS_EXEC_EBREAK);
+
+// Program Buffer instruction multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ dm2pipe_pbuf_instr_o = ABS_EXEC_EBREAK;
+
+ if (abs_fsm_exec & ~hart_pbuf_ebreak_ff) begin
+ case (pipe2dm_pbuf_addr_i)
+ 3'h0: dm2pipe_pbuf_instr_o = abs_progbuf0_ff;
+ 3'h1: dm2pipe_pbuf_instr_o = abs_progbuf1_ff;
+ 3'h2: dm2pipe_pbuf_instr_o = abs_progbuf2_ff;
+ 3'h3: dm2pipe_pbuf_instr_o = abs_progbuf3_ff;
+ 3'h4: dm2pipe_pbuf_instr_o = abs_progbuf4_ff;
+ 3'h5: dm2pipe_pbuf_instr_o = abs_progbuf5_ff;
+ default: ;
+ endcase
+ end else if (pipe2dm_pbuf_addr_i == 3'b0) begin
+ dm2pipe_pbuf_instr_o = abs_exec_instr_ff;
+ end
+end
+
+//------------------------------------------------------------------------------
+// Debug Hart Interface : abstract command data
+//------------------------------------------------------------------------------
+
+assign dm2pipe_dreg_resp_o = 1'b1;
+assign dm2pipe_dreg_fail_o = 1'b0;
+assign dm2pipe_dreg_rdata_o = abs_fsm_use_addr ? abs_data1_ff : abs_data0_ff;
+
+`ifdef SCR1_TRGT_SIMULATION
+//------------------------------------------------------------------------------
+// Assertions
+//------------------------------------------------------------------------------
+
+SVA_DM_X_CONTROL : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({dmi2dm_req_i, pipe2dm_dreg_req_i, pipe2dm_cmd_resp_i,
+ pipe2dm_hart_event_i})
+) else $error("DM error: control signals is X - %0b", {dmi2dm_req_i,
+ pipe2dm_dreg_req_i, pipe2dm_cmd_resp_i, pipe2dm_hart_event_i});
+
+SVA_DM_X_DMI : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ dmi2dm_req_i |-> !$isunknown({dmi2dm_wr_i, dmi2dm_addr_i, dmi2dm_wdata_i})
+) else $error("DM error: data signals is X on dmi");
+
+SVA_DM_X_HART_PBUF : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown (pipe2dm_pbuf_addr_i)
+) else $error("DM error: data signals is X on hart_pbuf");
+
+SVA_DM_X_HART_DREG : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ pipe2dm_dreg_req_i |-> !$isunknown({pipe2dm_dreg_wr_i, pipe2dm_dreg_wdata_i})
+) else $error("DM error: data signals is X on hart_dreg");
+
+SVA_DM_X_HART_CMD : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ pipe2dm_cmd_resp_i |-> !$isunknown({pipe2dm_cmd_rcode_i})
+) else $error("DM error: data signals is X on dm2pipe_cmd_o");
+
+SVA_DM_X_HART_EVENT : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ pipe2dm_hart_event_i |-> !$isunknown(pipe2dm_hart_status_i)
+) else $error("DM error: data signals is X on pipe2dm_hart_event_i");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_dm
+
+`endif // SCR1_DBG_EN
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_dmi.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_dmi.sv
new file mode 100644
index 0000000..ba62c2a
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_dmi.sv
@@ -0,0 +1,182 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_dmi.sv>
+/// @brief Debug Module Interface (DMI)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Provides TAPC with access to Debug Module (DM) and DTMCS
+ //
+ // Structure:
+ // - DMI <-> TAP interface
+ // - DMI <-> DM interface
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+`include "scr1_dm.svh"
+
+module scr1_dmi (
+ // System
+ input logic rst_n, // DMI unit reset
+ input logic clk, // DMI unit clock
+
+ // TAP interface
+ input logic tapcsync2dmi_ch_sel_i, // Debug Transport Module Chain Select
+ input logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapcsync2dmi_ch_id_i, // Debug Transport Module Chain ID
+ input logic tapcsync2dmi_ch_capture_i, // Debug Transport Module Chain Capture
+ input logic tapcsync2dmi_ch_shift_i, // Debug Transport Module Chain Shift
+ input logic tapcsync2dmi_ch_update_i, // Debug Transport Module Chain Update
+ input logic tapcsync2dmi_ch_tdi_i, // Debug Transport Module Chain TDI
+ output logic dmi2tapcsync_ch_tdo_o, // Debug Transport Module Chain TDO
+
+ // DM interface
+ input logic dm2dmi_resp_i, // DMI response
+ input logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dm2dmi_rdata_i, // DMI read data
+ output logic dmi2dm_req_o, // DMI request
+ output logic dmi2dm_wr_o, // DMI write
+ output logic [SCR1_DBG_DMI_ADDR_WIDTH-1:0] dmi2dm_addr_o, // DMI address
+ output logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi2dm_wdata_o // DMI write data
+);
+
+//------------------------------------------------------------------------------
+// Local parameters declaration
+//------------------------------------------------------------------------------
+
+// Debug Transport Module Status parameters
+//------------------------------------------------------------------------------
+
+localparam DTMCS_RESERVEDB_HI = 5'd31;
+localparam DTMCS_RESERVEDB_LO = 5'd18;
+localparam DTMCS_DMIHARDRESET = 5'd17;
+localparam DTMCS_DMIRESET = 5'd16;
+localparam DTMCS_RESERVEDA = 5'd15;
+localparam DTMCS_IDLE_HI = 5'd14;
+localparam DTMCS_IDLE_LO = 5'd12;
+localparam DTMCS_DMISTAT_HI = 5'd11;
+localparam DTMCS_DMISTAT_LO = 5'd10;
+localparam DTMCS_ABITS_HI = 5'd9;
+localparam DTMCS_ABITS_LO = 5'd4;
+localparam DTMCS_VERSION_HI = 5'd3;
+localparam DTMCS_VERSION_LO = 5'd0;
+
+// Debug Module Interface parameters
+//------------------------------------------------------------------------------
+
+localparam DMI_OP_LO = 5'd0;
+localparam DMI_OP_HI = DMI_OP_LO + SCR1_DBG_DMI_OP_WIDTH - 1;
+localparam DMI_DATA_LO = DMI_OP_HI + 1;
+localparam DMI_DATA_HI = DMI_DATA_LO + SCR1_DBG_DMI_DATA_WIDTH - 1;
+localparam DMI_ADDR_LO = DMI_DATA_HI + 1;
+localparam DMI_ADDR_HI = DMI_ADDR_LO + SCR1_DBG_DMI_ADDR_WIDTH - 1;
+
+//------------------------------------------------------------------------------
+// Local signals declaration
+//------------------------------------------------------------------------------
+
+// TAP data register
+logic tap_dr_upd;
+logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_ff;
+logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_shift;
+logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_rdata;
+logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_next;
+
+// DM read data register
+logic dm_rdata_upd;
+logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dm_rdata_ff;
+
+logic tapc_dmi_access_req;
+logic tapc_dtmcs_sel;
+
+//------------------------------------------------------------------------------
+// DMI <-> TAP interface
+//------------------------------------------------------------------------------
+
+// TAPC read data multiplexer
+//------------------------------------------------------------------------------
+
+assign tapc_dtmcs_sel = (tapcsync2dmi_ch_id_i == 1'd1);
+
+// DMI operation is always successful in the current implementation
+always_comb begin
+ tap_dr_rdata = '0;
+
+ if(tapc_dtmcs_sel) begin
+ tap_dr_rdata[DTMCS_RESERVEDB_HI:DTMCS_RESERVEDB_LO] = 'b0;
+ tap_dr_rdata[DTMCS_DMIHARDRESET] = 'b0;
+ tap_dr_rdata[DTMCS_DMIRESET] = 'b0;
+ tap_dr_rdata[DTMCS_RESERVEDA] = 'b0;
+ tap_dr_rdata[DTMCS_IDLE_HI:DTMCS_IDLE_LO] = 'b0;
+ tap_dr_rdata[DTMCS_DMISTAT_HI:DTMCS_DMISTAT_LO] = 'b0;
+ tap_dr_rdata[DTMCS_ABITS_HI :DTMCS_ABITS_LO] = SCR1_DBG_DMI_ADDR_WIDTH;
+ tap_dr_rdata[DTMCS_VERSION_LO] = 1'b1;
+ end else begin
+ tap_dr_rdata[DMI_ADDR_HI:DMI_ADDR_LO] = 'b0;
+ tap_dr_rdata[DMI_DATA_HI:DMI_DATA_LO] = dm_rdata_ff;
+ tap_dr_rdata[DMI_OP_HI :DMI_OP_LO] = 'b0;
+ end
+end
+
+assign tap_dr_shift = tapc_dtmcs_sel
+ ? {9'b0, tapcsync2dmi_ch_tdi_i, tap_dr_ff[SCR1_DBG_DMI_DR_DTMCS_WIDTH-1:1]}
+ : {tapcsync2dmi_ch_tdi_i, tap_dr_ff[SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:1]};
+
+// TAP data register
+//------------------------------------------------------------------------------
+
+assign tap_dr_upd = tapcsync2dmi_ch_capture_i | tapcsync2dmi_ch_shift_i;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ tap_dr_ff <= '0;
+ end else if(tap_dr_upd) begin
+ tap_dr_ff <= tap_dr_next;
+ end
+end
+
+assign tap_dr_next = tapcsync2dmi_ch_capture_i ? tap_dr_rdata
+ : tapcsync2dmi_ch_shift_i ? tap_dr_shift
+ : tap_dr_ff;
+
+assign dmi2tapcsync_ch_tdo_o = tap_dr_ff[0];
+
+//------------------------------------------------------------------------------
+// DMI <-> DM interface
+//------------------------------------------------------------------------------
+
+assign tapc_dmi_access_req = tapcsync2dmi_ch_update_i & tapcsync2dmi_ch_sel_i
+ & (tapcsync2dmi_ch_id_i == 2'd2);
+
+always_comb begin
+ dmi2dm_req_o = 1'b0;
+ dmi2dm_wr_o = 1'b0;
+ dmi2dm_addr_o = 1'b0;
+ dmi2dm_wdata_o = 1'b0;
+
+ if(tapc_dmi_access_req) begin
+ dmi2dm_req_o = tap_dr_ff[DMI_OP_HI :DMI_OP_LO] != 2'b00;
+ dmi2dm_wr_o = tap_dr_ff[DMI_OP_HI :DMI_OP_LO] == 2'b10;
+ dmi2dm_addr_o = tap_dr_ff[DMI_ADDR_HI:DMI_ADDR_LO];
+ dmi2dm_wdata_o = tap_dr_ff[DMI_DATA_HI:DMI_DATA_LO];
+ end
+end
+
+// DM read data register
+//------------------------------------------------------------------------------
+
+assign dm_rdata_upd = dmi2dm_req_o & dm2dmi_resp_i & ~dmi2dm_wr_o;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ dm_rdata_ff <= '0;
+ end else if (dm_rdata_upd) begin
+ dm_rdata_ff <= dm2dmi_rdata_i;
+ end
+end
+
+endmodule : scr1_dmi
+
+`endif // SCR1_DBG_EN
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_scu.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_scu.sv
new file mode 100644
index 0000000..7f44ee6
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_scu.sv
@@ -0,0 +1,516 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_scu.sv>
+/// @brief System Control Unit (SCU)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Generates System, Core, HDU and DM resets and their qualifier signals
+ // - Provides debugger with software System and Core resets generation functionality
+ // - Allows to set the behavior of DM and HDU resets
+ // - Shows resets Statuses and Sticky Statuses
+
+ // Structure:
+ // - TAPC scan-chain interface
+ // - SCU CSRs write/read interface
+ // - SCU CSRS:
+ // - CONTROL register
+ // - MODE register
+ // - STATUS register
+ // - STICKY_STATUS register
+ // - Reset logic
+ // - System Reset
+ // - Core Reset
+ // - DM Reset
+ // - HDU Reset
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+`include "scr1_scu.svh"
+
+`ifdef SCR1_DBG_EN
+
+module scr1_scu (
+ // Global signals
+ input logic pwrup_rst_n, // Power-Up Reset
+ input logic rst_n, // Regular Reset
+ input logic cpu_rst_n, // CPU Reset
+ input logic test_mode, // DFT Test Mode
+ input logic test_rst_n, // DFT Test Reset
+ input logic clk, // SCU clock
+
+ // TAPC scan-chains
+ input logic tapcsync2scu_ch_sel_i, // TAPC Chain Select
+ input logic tapcsync2scu_ch_id_i, // TAPC Chain ID
+ input logic tapcsync2scu_ch_capture_i, // TAPC Chain Capture
+ input logic tapcsync2scu_ch_shift_i, // TAPC Chain Shift
+ input logic tapcsync2scu_ch_update_i, // TAPC Chain Update
+ input logic tapcsync2scu_ch_tdi_i, // TAPC Chain TDI
+ output logic scu2tapcsync_ch_tdo_o, // TAPC Chain TDO
+
+ // Input sync resets:
+ input logic ndm_rst_n_i, // Non-DM Reset input from DM
+ input logic hart_rst_n_i, // HART Reset from DM
+
+ // Generated resets
+ output logic sys_rst_n_o, // System/Cluster Reset
+ output logic core_rst_n_o, // Core Reset
+ output logic dm_rst_n_o, // Debug Module Reset
+ output logic hdu_rst_n_o, // HART Debug Unit Reset
+
+ // Resets statuses
+ output logic sys_rst_status_o, // System Reset Status (sync'ed to POR reset domain)
+ output logic core_rst_status_o, // Core Reset Status (sync'ed to POR reset domain)
+
+ // Reset Domain Crossing (RDC) qualifiers
+ output logic sys_rdc_qlfy_o, // System/Cluster-to-ExternalSOC Reset Domain Crossing Qualifier
+ output logic core_rdc_qlfy_o, // Core-to-ExternalSOC Reset Domain Crossing Qualifier
+ output logic core2hdu_rdc_qlfy_o, // Core-to-HDU Reset Domain Crossing Qualifier
+ output logic core2dm_rdc_qlfy_o, // Core-to-DM Reset Domain Crossing Qualifier
+ output logic hdu2dm_rdc_qlfy_o // HDU-to-DM Reset Domain Crossing Qualifier
+);
+
+//------------------------------------------------------------------------------
+// Local Parameters
+//======================================================================================================================
+localparam int unsigned SCR1_SCU_RST_SYNC_STAGES_NUM = 2;
+
+//------------------------------------------------------------------------------
+// Local Signals
+//------------------------------------------------------------------------------
+
+// SCU CSR write/read i/f
+//------------------------------------------------------------------------------
+
+// TAPC scan-chain control logic
+logic scu_csr_req;
+logic tapc_dr_cap_req;
+logic tapc_dr_shft_req;
+logic tapc_dr_upd_req;
+
+// TAPC shift register signals
+logic tapc_shift_upd;
+type_scr1_scu_sysctrl_dr_s tapc_shift_ff;
+type_scr1_scu_sysctrl_dr_s tapc_shift_next;
+
+// TAPC shadow register signals
+type_scr1_scu_sysctrl_dr_s tapc_shadow_ff;
+
+// SCU CSR write/read i/f
+//------------------------------------------------------------------------------
+
+logic [SCR1_SCU_DR_SYSCTRL_DATA_WIDTH-1:0] scu_csr_wdata;
+logic [SCR1_SCU_DR_SYSCTRL_DATA_WIDTH-1:0] scu_csr_rdata;
+
+// SCU CSRs signals
+//------------------------------------------------------------------------------
+
+// Control register
+type_scr1_scu_sysctrl_control_reg_s scu_control_ff;
+logic scu_control_wr_req;
+
+// Mode register
+type_scr1_scu_sysctrl_mode_reg_s scu_mode_ff;
+logic scu_mode_wr_req;
+
+// Status register
+type_scr1_scu_sysctrl_status_reg_s scu_status_ff;
+type_scr1_scu_sysctrl_status_reg_s scu_status_ff_dly;
+type_scr1_scu_sysctrl_status_reg_s scu_status_ff_posedge;
+
+// Sticky Status register
+type_scr1_scu_sysctrl_status_reg_s scu_sticky_sts_ff;
+logic scu_sticky_sts_wr_req;
+
+// Reset logic signals
+//------------------------------------------------------------------------------
+
+// Input resets synchronization signals
+logic pwrup_rst_n_sync;
+logic rst_n_sync;
+logic cpu_rst_n_sync;
+
+// System Reset signals
+logic sys_rst_n_in;
+logic sys_rst_n_status;
+logic sys_rst_n_status_sync;
+logic sys_rst_n_qlfy;
+logic sys_reset_n;
+
+// Core Reset signals
+logic core_rst_n_in_sync;
+logic core_rst_n_status;
+logic core_rst_n_status_sync;
+logic core_rst_n_qlfy;
+logic core_reset_n;
+
+// HDU Reset signals
+logic hdu_rst_n_in_sync;
+logic hdu_rst_n_status;
+logic hdu_rst_n_status_sync;
+logic hdu_rst_n_qlfy;
+
+// DM Reset signals
+logic dm_rst_n_in;
+logic dm_rst_n_status;
+
+//------------------------------------------------------------------------------
+// TAPC scan-chain i/f
+//------------------------------------------------------------------------------
+//
+ // Consists of the following functional units:
+ // - TAPC scan-chain control logic
+ // - TAPC shift register
+ // - TAPC shadow register
+//
+
+// TAPC scan-chain control logic
+//------------------------------------------------------------------------------
+
+assign scu_csr_req = tapcsync2scu_ch_sel_i & (tapcsync2scu_ch_id_i == '0);
+assign tapc_dr_cap_req = scu_csr_req & tapcsync2scu_ch_capture_i;
+assign tapc_dr_shft_req = scu_csr_req & tapcsync2scu_ch_shift_i;
+assign tapc_dr_upd_req = scu_csr_req & tapcsync2scu_ch_update_i;
+
+// TAPC shift register
+//------------------------------------------------------------------------------
+
+assign tapc_shift_upd = tapc_dr_cap_req | tapc_dr_shft_req;
+
+always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
+ if (~pwrup_rst_n_sync) begin
+ tapc_shift_ff <= '0;
+ end else if (tapc_shift_upd) begin
+ tapc_shift_ff <= tapc_shift_next;
+ end
+end
+
+assign tapc_shift_next = tapc_dr_cap_req ? tapc_shadow_ff
+ : tapc_dr_shft_req ? {tapcsync2scu_ch_tdi_i, tapc_shift_ff[$bits(type_scr1_scu_sysctrl_dr_s)-1:1]}
+ : tapc_shift_ff;
+
+// TAPC shadow register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
+ if (~pwrup_rst_n_sync) begin
+ tapc_shadow_ff <= '0;
+ end else if (tapc_dr_upd_req) begin
+ tapc_shadow_ff.op <= tapc_shift_ff.op;
+ tapc_shadow_ff.addr <= tapc_shift_ff.addr;
+ tapc_shadow_ff.data <= scu_csr_wdata;
+ end
+end
+
+assign scu2tapcsync_ch_tdo_o = tapc_shift_ff[0];
+
+//------------------------------------------------------------------------------
+// SCU CSRs write/read interface
+//------------------------------------------------------------------------------
+
+// Write interface
+//------------------------------------------------------------------------------
+
+// Register selection logic
+always_comb begin
+ scu_control_wr_req = 1'b0;
+ scu_mode_wr_req = 1'b0;
+ scu_sticky_sts_wr_req = 1'b0;
+
+ if (tapc_dr_upd_req && (tapc_shift_ff.op != SCR1_SCU_SYSCTRL_OP_READ)) begin
+ case (tapc_shift_ff.addr)
+ SCR1_SCU_SYSCTRL_ADDR_CONTROL: scu_control_wr_req = 1'b1;
+ SCR1_SCU_SYSCTRL_ADDR_MODE : scu_mode_wr_req = 1'b1;
+ SCR1_SCU_SYSCTRL_ADDR_STICKY : scu_sticky_sts_wr_req = (tapc_shift_ff.op == SCR1_SCU_SYSCTRL_OP_CLRBITS);
+ default : begin end
+ endcase
+ end
+end
+
+// Write data construction
+always_comb begin
+ scu_csr_wdata = '0;
+
+ if (tapc_dr_upd_req) begin
+ case (tapc_shift_ff.op)
+ SCR1_SCU_SYSCTRL_OP_WRITE : scu_csr_wdata = tapc_shift_ff.data;
+ SCR1_SCU_SYSCTRL_OP_READ : scu_csr_wdata = scu_csr_rdata;
+ SCR1_SCU_SYSCTRL_OP_SETBITS: scu_csr_wdata = scu_csr_rdata | tapc_shift_ff.data;
+ SCR1_SCU_SYSCTRL_OP_CLRBITS: scu_csr_wdata = scu_csr_rdata & (~tapc_shift_ff.data);
+ default : begin end
+ endcase
+ end
+end
+
+// Read interface
+//------------------------------------------------------------------------------
+
+// Read data multiplexer
+always_comb begin
+ scu_csr_rdata = '0;
+
+ if (tapc_dr_upd_req) begin
+ case (tapc_shift_ff.addr)
+ SCR1_SCU_SYSCTRL_ADDR_CONTROL: scu_csr_rdata = scu_control_ff;
+ SCR1_SCU_SYSCTRL_ADDR_MODE : scu_csr_rdata = scu_mode_ff;
+ SCR1_SCU_SYSCTRL_ADDR_STATUS : scu_csr_rdata = scu_status_ff;
+ SCR1_SCU_SYSCTRL_ADDR_STICKY : scu_csr_rdata = scu_sticky_sts_ff;
+ default : scu_csr_rdata = 'x;
+ endcase
+ end
+end
+
+//------------------------------------------------------------------------------
+// SCU CSRs
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - CONTROL register
+ // - MODE register
+ // - STATUS register
+ // - STICKY_STATUS register
+//
+
+// CONTROL register
+//------------------------------------------------------------------------------
+// Allows debugger to generate System and Core resets
+
+always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
+ if (~pwrup_rst_n_sync) begin
+ scu_control_ff <= '0;
+ end else if (scu_control_wr_req) begin
+ scu_control_ff <= scu_csr_wdata;
+ end
+end
+
+// MODE register
+//------------------------------------------------------------------------------
+// Sets reset behavior for DM Reset and HDU Reset signals
+
+always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
+ if (~pwrup_rst_n_sync) begin
+ scu_mode_ff <= '0;
+ end else if (scu_mode_wr_req) begin
+ scu_mode_ff <= scu_csr_wdata;
+ end
+end
+
+// STATUS register
+//------------------------------------------------------------------------------
+// Holds the status of every output reset signal (System, Core, DM and HDU)
+
+assign scu_status_ff.sys_reset = sys_rst_status_o ;
+assign scu_status_ff.core_reset = core_rst_status_o;
+assign scu_status_ff.dm_reset = ~dm_rst_n_status;
+assign scu_status_ff.hdu_reset = ~hdu_rst_n_status_sync;
+
+// Status Register positive edge detection logic
+always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
+ if (~pwrup_rst_n_sync) begin
+ scu_status_ff_dly <= '0;
+ end else begin
+ scu_status_ff_dly <= scu_status_ff;
+ end
+end
+
+assign scu_status_ff_posedge = scu_status_ff & ~scu_status_ff_dly;
+
+// STICKY_STATUS register
+//------------------------------------------------------------------------------
+// For every output reset signal shows if it was asserted since the last bit clearing
+
+always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
+ if (~pwrup_rst_n_sync) begin
+ scu_sticky_sts_ff <= '0;
+ end else begin
+ for (int unsigned i = 0; i < $bits(type_scr1_scu_sysctrl_status_reg_s); ++i) begin
+ if (scu_status_ff_posedge[i]) begin
+ scu_sticky_sts_ff[i] <= 1'b1;
+ end else if (scu_sticky_sts_wr_req) begin
+ scu_sticky_sts_ff[i] <= scu_csr_wdata[i];
+ end
+ end
+ end
+end
+
+//------------------------------------------------------------------------------
+// Reset logic
+//------------------------------------------------------------------------------
+//
+ // Consists of the following functional units:
+ // - System Reset logic
+ // - Core Reset logic
+ // - Hart Debug Unit Reset logic
+ // - Debug Module Reset logic
+//
+
+// Reset inputs are assumed synchronous
+assign pwrup_rst_n_sync = pwrup_rst_n;
+assign rst_n_sync = rst_n;
+assign cpu_rst_n_sync = cpu_rst_n;
+
+// Intermediate resets:
+assign sys_reset_n = ~scu_control_ff.sys_reset;
+assign core_reset_n = ~scu_control_ff.core_reset;
+
+// System/Cluster Reset: sys_rst_n_o
+//------------------------------------------------------------------------------
+
+scr1_reset_qlfy_adapter_cell_sync i_sys_rstn_qlfy_adapter_cell_sync (
+ .rst_n (pwrup_rst_n_sync),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .reset_n_in_sync (sys_rst_n_in ),
+ .reset_n_out_qlfy (sys_rst_n_qlfy ),
+ .reset_n_out (sys_rst_n_o ),
+ .reset_n_status (sys_rst_n_status)
+);
+
+assign sys_rst_n_in = sys_reset_n & ndm_rst_n_i & rst_n_sync;
+
+scr1_data_sync_cell #(
+ .STAGES_AMOUNT (SCR1_SCU_RST_SYNC_STAGES_NUM)
+) i_sys_rstn_status_sync (
+ .rst_n (pwrup_rst_n_sync ),
+ .clk (clk ),
+ .data_in (sys_rst_n_status ),
+ .data_out (sys_rst_n_status_sync)
+);
+
+assign sys_rst_status_o = ~sys_rst_n_status_sync;
+
+// System/Cluster-to-ExternalSOC RDC qualifier
+assign sys_rdc_qlfy_o = sys_rst_n_qlfy;
+
+// Core Reset: core_rst_n_o
+//------------------------------------------------------------------------------
+
+scr1_reset_qlfy_adapter_cell_sync i_core_rstn_qlfy_adapter_cell_sync (
+ .rst_n (pwrup_rst_n_sync ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .reset_n_in_sync (core_rst_n_in_sync),
+ .reset_n_out_qlfy (core_rst_n_qlfy ),
+ .reset_n_out (core_rst_n_o ),
+ .reset_n_status (core_rst_n_status )
+);
+
+assign core_rst_n_in_sync = sys_rst_n_in & hart_rst_n_i & core_reset_n & cpu_rst_n_sync;
+
+scr1_data_sync_cell #(
+ .STAGES_AMOUNT (SCR1_SCU_RST_SYNC_STAGES_NUM)
+) i_core_rstn_status_sync (
+ .rst_n (pwrup_rst_n_sync ),
+ .clk (clk ),
+ .data_in (core_rst_n_status ),
+ .data_out (core_rst_n_status_sync)
+);
+
+assign core_rst_status_o = ~core_rst_n_status_sync;
+
+// Core Reset RDC Qualifiers:
+// - Core-to-ExternalSOC RDC Qlfy
+assign core_rdc_qlfy_o = core_rst_n_qlfy;
+// - Core-to-HDU RDC Qlfy
+assign core2hdu_rdc_qlfy_o = core_rst_n_qlfy;
+// - Core-to-DebugModule RDC Qlfy
+assign core2dm_rdc_qlfy_o = core_rst_n_qlfy;
+
+// Hart Debug Unit Reset: hdu_rst_n_o
+//------------------------------------------------------------------------------
+
+scr1_reset_qlfy_adapter_cell_sync i_hdu_rstn_qlfy_adapter_cell_sync (
+ .rst_n (pwrup_rst_n_sync ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .reset_n_in_sync (hdu_rst_n_in_sync),
+ .reset_n_out_qlfy (hdu_rst_n_qlfy ),
+ .reset_n_out (hdu_rst_n_o ),
+ .reset_n_status (hdu_rst_n_status )
+);
+
+assign hdu_rst_n_in_sync = scu_mode_ff.hdu_rst_bhv | core_rst_n_in_sync;
+
+scr1_data_sync_cell #(
+ .STAGES_AMOUNT (SCR1_SCU_RST_SYNC_STAGES_NUM)
+) i_hdu_rstn_status_sync (
+ .rst_n (pwrup_rst_n_sync ),
+ .clk (clk ),
+ .data_in (hdu_rst_n_status ),
+ .data_out (hdu_rst_n_status_sync)
+);
+
+// Hart Debug Unit Reset RDC Qualifiers:
+// - HDU-to-DebugModule RDC Qlfy
+assign hdu2dm_rdc_qlfy_o = hdu_rst_n_qlfy;
+
+// Debug Module Reset: dm_rst_n_o
+//------------------------------------------------------------------------------
+
+scr1_reset_buf_cell i_dm_rstn_buf_cell (
+ .rst_n (pwrup_rst_n_sync),
+ .clk (clk ),
+ .test_mode (test_mode ),
+ .test_rst_n (test_rst_n ),
+ .reset_n_in (dm_rst_n_in ),
+ .reset_n_out (dm_rst_n_o ),
+ .reset_n_status (dm_rst_n_status )
+);
+
+assign dm_rst_n_in = ~scu_mode_ff.dm_rst_bhv | sys_reset_n;
+
+`ifdef SCR1_TRGT_SIMULATION
+//--------------------------------------------------------------------
+// Assertions
+//--------------------------------------------------------------------
+
+`ifndef VERILATOR
+// Preventing some assertions to be raised at 0 sim time or in the first cycle
+initial begin
+$assertoff(0, scr1_scu);
+repeat (2) @(posedge clk);
+$asserton(0, scr1_scu);
+end
+`endif // VERILATOR
+
+// X checks
+SCR1_SVA_SCU_RESETS_XCHECK : assert property (
+ @(negedge clk)
+ !$isunknown({pwrup_rst_n, rst_n, cpu_rst_n, ndm_rst_n_i, hart_rst_n_i})
+) else $error("SCU resets error: unknown values of input resets");
+
+// Qualifiers checks
+SCR1_SVA_SCU_SYS2SOC_QLFY_CHECK : assert property (
+ @(negedge clk) disable iff (~pwrup_rst_n)
+ $fell(sys_rst_n_o) |-> $fell($past(sys_rdc_qlfy_o))
+) else $error("SCU sys2soc qlfy error: qlfy wasn't raised prior to reset");
+
+SCR1_SVA_SCU_CORE2SOC_QLFY_CHECK : assert property (
+ @(negedge clk) disable iff (~pwrup_rst_n)
+ $fell(core_rst_n_o) |-> $fell($past(core_rdc_qlfy_o))
+) else $error("SCU core2soc qlfy error: qlfy wasn't raised prior to reset");
+
+SCR1_SVA_SCU_CORE2HDU_QLFY_CHECK : assert property (
+ @(negedge clk) disable iff (~pwrup_rst_n)
+ $fell(core_rst_n_o) |-> $fell($past(core2hdu_rdc_qlfy_o))
+) else $error("SCU core2hdu qlfy error: qlfy wasn't raised prior to reset");
+
+SCR1_SVA_SCU_CORE2DM_QLFY_CHECK : assert property (
+ @(negedge clk) disable iff (~pwrup_rst_n)
+ $fell(core_rst_n_o) |-> $fell($past(core2dm_rdc_qlfy_o))
+) else $error("SCU core2dm qlfy error: qlfy wasn't raised prior to reset");
+
+SCR1_SVA_SCU_HDU2DM_QLFY_CHECK : assert property (
+ @(negedge clk) disable iff (~pwrup_rst_n)
+ $fell(hdu_rst_n_o) |-> $fell($past(hdu2dm_rdc_qlfy_o))
+) else $error("SCU hdu2dm qlfy error: qlfy wasn't raised prior to reset");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_scu
+`endif // SCR1_DBG_EN
+
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_tapc.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_tapc.sv
new file mode 100644
index 0000000..45687f4
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_tapc.sv
@@ -0,0 +1,457 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_tapc.sv>
+/// @brief TAP Controller (TAPC)
+///
+
+//------------------------------------------------------------------------------
+ //
+ // Functionality:
+ // - Controls TAP operation
+ // - Allows debugger to access TAP Data registers and DMI/SCU scan-chains via
+ // command written in Instruction register
+ //
+ // Structure:
+ // - Synchronous reset generation
+ // - TAPC FSM
+ // - TAPC Instruction Registers
+ // - TAPC DRs/DMI/SCU scan-chains
+ // - TAPC TDO enable and output Registers
+ // - TAPC Data Registers
+ // - BYPASS
+ // - IDCODE
+ // - BUILD ID
+ //
+//------------------------------------------------------------------------------
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+`include "scr1_tapc.svh"
+`include "scr1_dm.svh"
+
+module scr1_tapc (
+ // JTAG signals
+ input logic tapc_trst_n, // Test Reset (TRSTn)
+ input logic tapc_tck, // Test Clock (TCK)
+ input logic tapc_tms, // Test Mode Select (TMS)
+ input logic tapc_tdi, // Test Data Input (TDI)
+ output logic tapc_tdo, // Test Data Output (TDO)
+ output logic tapc_tdo_en, // TDO Enable, signal for TDO buffer control
+
+ // Fuses:
+ input logic [31:0] soc2tapc_fuse_idcode_i, // IDCODE value from fuses
+
+ // DMI/SCU scan-chains
+ output logic tapc2tapcsync_scu_ch_sel_o, // SCU Chain Select
+ output logic tapc2tapcsync_dmi_ch_sel_o, // DMI Chain Select
+ output logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc2tapcsync_ch_id_o, // DMI/SCU Chain Identifier
+ output logic tapc2tapcsync_ch_capture_o, // DMI/SCU Chain Capture
+ output logic tapc2tapcsync_ch_shift_o, // DMI/SCU Chain Shift
+ output logic tapc2tapcsync_ch_update_o, // DMI/SCU Chain Update
+ output logic tapc2tapcsync_ch_tdi_o, // DMI/SCU Chain TDI
+ input logic tapcsync2tapc_ch_tdo_i // DMI/SCU Chain TDO
+);
+
+//------------------------------------------------------------------------------
+// Local Signals
+//------------------------------------------------------------------------------
+
+logic trst_n_int; // Sync reset signal
+
+// TAPC FSM signals
+//------------------------------------------------------------------------------
+
+type_scr1_tap_state_e tap_fsm_ff; // TAP's current state
+type_scr1_tap_state_e tap_fsm_next; // TAP's next state
+
+// Control signals
+logic tap_fsm_reset;
+logic tap_fsm_ir_upd;
+logic tap_fsm_ir_cap;
+logic tap_fsm_ir_shft;
+
+// Registered control signals
+logic tap_fsm_ir_shift_ff;
+logic tap_fsm_ir_shift_next;
+logic tap_fsm_dr_capture_ff;
+logic tap_fsm_dr_capture_next;
+logic tap_fsm_dr_shift_ff;
+logic tap_fsm_dr_shift_next;
+logic tap_fsm_dr_update_ff;
+logic tap_fsm_dr_update_next;
+
+// TAPC Instruction Registers signals
+//------------------------------------------------------------------------------
+
+logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_shift_ff; // Instruction Shift Register
+logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_shift_next; // Instruction Shift Register next value
+logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_ff; // Instruction Register
+logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_next; // Instruction Register next value
+
+// TAPC Data Registers signals
+//------------------------------------------------------------------------------
+
+// BYPASS register
+logic dr_bypass_sel;
+logic dr_bypass_tdo;
+
+// IDCODE register
+logic dr_idcode_sel;
+logic dr_idcode_tdo;
+
+// BUILD ID register
+logic dr_bld_id_sel;
+logic dr_bld_id_tdo;
+
+logic dr_out;
+
+// TDO registers
+//------------------------------------------------------------------------------
+
+// TDO enable register
+logic tdo_en_ff;
+logic tdo_en_next;
+
+// TDO output register
+logic tdo_out_ff;
+logic tdo_out_next;
+
+//------------------------------------------------------------------------------
+// TAPC Synchronous Reset logic
+//------------------------------------------------------------------------------
+
+always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ trst_n_int <= 1'b0;
+ end else begin
+ trst_n_int <= ~tap_fsm_reset;
+ end
+end
+
+//------------------------------------------------------------------------------
+// TAP's FSM
+//------------------------------------------------------------------------------
+
+always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tap_fsm_ff <= SCR1_TAP_STATE_RESET;
+ end else begin
+ tap_fsm_ff <= tap_fsm_next;
+ end
+end
+
+always_comb begin
+ case (tap_fsm_ff)
+ SCR1_TAP_STATE_RESET : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_RESET : SCR1_TAP_STATE_IDLE;
+ SCR1_TAP_STATE_IDLE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_SEL_SCAN : SCR1_TAP_STATE_IDLE;
+ SCR1_TAP_STATE_DR_SEL_SCAN: tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_SEL_SCAN : SCR1_TAP_STATE_DR_CAPTURE;
+ SCR1_TAP_STATE_DR_CAPTURE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_EXIT1 : SCR1_TAP_STATE_DR_SHIFT;
+ SCR1_TAP_STATE_DR_SHIFT : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_EXIT1 : SCR1_TAP_STATE_DR_SHIFT;
+ SCR1_TAP_STATE_DR_EXIT1 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_UPDATE : SCR1_TAP_STATE_DR_PAUSE;
+ SCR1_TAP_STATE_DR_PAUSE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_EXIT2 : SCR1_TAP_STATE_DR_PAUSE;
+ SCR1_TAP_STATE_DR_EXIT2 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_UPDATE : SCR1_TAP_STATE_DR_SHIFT;
+ SCR1_TAP_STATE_DR_UPDATE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_SEL_SCAN : SCR1_TAP_STATE_IDLE;
+ SCR1_TAP_STATE_IR_SEL_SCAN: tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_RESET : SCR1_TAP_STATE_IR_CAPTURE;
+ SCR1_TAP_STATE_IR_CAPTURE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_EXIT1 : SCR1_TAP_STATE_IR_SHIFT;
+ SCR1_TAP_STATE_IR_SHIFT : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_EXIT1 : SCR1_TAP_STATE_IR_SHIFT;
+ SCR1_TAP_STATE_IR_EXIT1 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_UPDATE : SCR1_TAP_STATE_IR_PAUSE;
+ SCR1_TAP_STATE_IR_PAUSE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_EXIT2 : SCR1_TAP_STATE_IR_PAUSE;
+ SCR1_TAP_STATE_IR_EXIT2 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_UPDATE : SCR1_TAP_STATE_IR_SHIFT;
+ SCR1_TAP_STATE_IR_UPDATE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_SEL_SCAN : SCR1_TAP_STATE_IDLE;
+`ifdef SCR1_XPROP_EN
+ default : tap_fsm_next = SCR1_TAP_STATE_XXX;
+`else // SCR1_XPROP_EN
+ default : tap_fsm_next = tap_fsm_ff;
+`endif // SCR1_XPROP_EN
+ endcase
+end
+
+assign tap_fsm_reset = (tap_fsm_ff == SCR1_TAP_STATE_RESET);
+assign tap_fsm_ir_upd = (tap_fsm_ff == SCR1_TAP_STATE_IR_UPDATE);
+assign tap_fsm_ir_cap = (tap_fsm_ff == SCR1_TAP_STATE_IR_CAPTURE);
+assign tap_fsm_ir_shft = (tap_fsm_ff == SCR1_TAP_STATE_IR_SHIFT);
+
+//------------------------------------------------------------------------------
+// TAPC Instruction Registers
+//------------------------------------------------------------------------------
+
+// TAPC Instruction Shift register
+//------------------------------------------------------------------------------
+
+always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tap_ir_shift_ff <= '0;
+ end else if (~trst_n_int) begin
+ tap_ir_shift_ff <= '0;
+ end else begin
+ tap_ir_shift_ff <= tap_ir_shift_next;
+ end
+end
+
+assign tap_ir_shift_next = tap_fsm_ir_cap ? {{($bits(tap_ir_shift_ff)-1){1'b0}}, 1'b1}
+ : tap_fsm_ir_shft ? {tapc_tdi, tap_ir_shift_ff[$left(tap_ir_shift_ff):1]}
+ : tap_ir_shift_ff;
+
+// TAPC Instruction register
+//------------------------------------------------------------------------------
+
+always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tap_ir_ff <= SCR1_TAP_INSTR_IDCODE;
+ end else if (~trst_n_int) begin
+ tap_ir_ff <= SCR1_TAP_INSTR_IDCODE;
+ end else begin
+ tap_ir_ff <= tap_ir_next;
+ end
+end
+
+assign tap_ir_next = tap_fsm_ir_upd ? tap_ir_shift_ff : tap_ir_ff;
+
+//------------------------------------------------------------------------------
+// Control signals
+//------------------------------------------------------------------------------
+
+always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tap_fsm_ir_shift_ff <= 1'b0;
+ end else if (~trst_n_int) begin
+ tap_fsm_ir_shift_ff <= 1'b0;
+ end else begin
+ tap_fsm_ir_shift_ff <= tap_fsm_ir_shift_next;
+ end
+end
+
+assign tap_fsm_ir_shift_next = (tap_fsm_next == SCR1_TAP_STATE_IR_SHIFT);
+
+always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tap_fsm_dr_capture_ff <= 1'b0;
+ end else if (~trst_n_int) begin
+ tap_fsm_dr_capture_ff <= 1'b0;
+ end else begin
+ tap_fsm_dr_capture_ff <= tap_fsm_dr_capture_next;
+ end
+end
+
+assign tap_fsm_dr_capture_next = (tap_fsm_next == SCR1_TAP_STATE_DR_CAPTURE);
+
+always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tap_fsm_dr_shift_ff <= 1'b0;
+ end else if (~trst_n_int) begin
+ tap_fsm_dr_shift_ff <= 1'b0;
+ end else begin
+ tap_fsm_dr_shift_ff <= tap_fsm_dr_shift_next;
+ end
+end
+
+assign tap_fsm_dr_shift_next = (tap_fsm_next == SCR1_TAP_STATE_DR_SHIFT);
+
+always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tap_fsm_dr_update_ff <= 1'b0;
+ end else if (~trst_n_int) begin
+ tap_fsm_dr_update_ff <= 1'b0;
+ end else begin
+ tap_fsm_dr_update_ff <= tap_fsm_dr_update_next;
+ end
+end
+
+assign tap_fsm_dr_update_next = (tap_fsm_next == SCR1_TAP_STATE_DR_UPDATE);
+
+//------------------------------------------------------------------------------
+// TAPC DRs/DMI/SCU scan-chains
+//------------------------------------------------------------------------------
+//
+ // Consists of the following functional units:
+ // - Data source/destination decoder
+ // - DMI channel ID decoder
+
+// - Read data multiplexer
+// Data source/destination decoder
+//------------------------------------------------------------------------------
+
+always_comb begin
+ dr_bypass_sel = 1'b0;
+ dr_idcode_sel = 1'b0;
+ dr_bld_id_sel = 1'b0;
+ tapc2tapcsync_scu_ch_sel_o = 1'b0;
+ tapc2tapcsync_dmi_ch_sel_o = 1'b0;
+ case (tap_ir_ff)
+ SCR1_TAP_INSTR_DTMCS : tapc2tapcsync_dmi_ch_sel_o = 1'b1;
+ SCR1_TAP_INSTR_DMI_ACCESS: tapc2tapcsync_dmi_ch_sel_o = 1'b1;
+ SCR1_TAP_INSTR_IDCODE : dr_idcode_sel = 1'b1;
+ SCR1_TAP_INSTR_BYPASS : dr_bypass_sel = 1'b1;
+ SCR1_TAP_INSTR_BLD_ID : dr_bld_id_sel = 1'b1;
+ SCR1_TAP_INSTR_SCU_ACCESS: tapc2tapcsync_scu_ch_sel_o = 1'b1;
+ default : dr_bypass_sel = 1'b1;
+ endcase
+end
+
+// DMI channel ID decoder
+//------------------------------------------------------------------------------
+
+always_comb begin
+ tapc2tapcsync_ch_id_o = '0;
+ case (tap_ir_ff)
+ SCR1_TAP_INSTR_DTMCS : tapc2tapcsync_ch_id_o = 'd1;
+ SCR1_TAP_INSTR_DMI_ACCESS: tapc2tapcsync_ch_id_o = 'd2;
+ default : tapc2tapcsync_ch_id_o = '0;
+ endcase
+end
+
+// Read data multiplexer
+//------------------------------------------------------------------------------
+
+always_comb begin
+ dr_out = 1'b0;
+ case (tap_ir_ff)
+ SCR1_TAP_INSTR_DTMCS : dr_out = tapcsync2tapc_ch_tdo_i;
+ SCR1_TAP_INSTR_DMI_ACCESS: dr_out = tapcsync2tapc_ch_tdo_i;
+ SCR1_TAP_INSTR_IDCODE : dr_out = dr_idcode_tdo;
+ SCR1_TAP_INSTR_BYPASS : dr_out = dr_bypass_tdo;
+ SCR1_TAP_INSTR_BLD_ID : dr_out = dr_bld_id_tdo;
+ SCR1_TAP_INSTR_SCU_ACCESS: dr_out = tapcsync2tapc_ch_tdo_i;
+ default : dr_out = dr_bypass_tdo;
+ endcase
+end
+
+//------------------------------------------------------------------------------
+// TDO enable and output registers
+//------------------------------------------------------------------------------
+
+// TDO enable register
+//------------------------------------------------------------------------------
+
+always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tdo_en_ff <= 1'b0;
+ end else if (~trst_n_int) begin
+ tdo_en_ff <= 1'b0;
+ end else begin
+ tdo_en_ff <= tdo_en_next;
+ end
+end
+
+assign tdo_en_next = tap_fsm_dr_shift_ff | tap_fsm_ir_shift_ff;
+
+// TDO output register
+//------------------------------------------------------------------------------
+
+always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tdo_out_ff <= 1'b0;
+ end else if (~trst_n_int) begin
+ tdo_out_ff <= 1'b0;
+ end else begin
+ tdo_out_ff <= tdo_out_next;
+ end
+end
+
+assign tdo_out_next = tap_fsm_dr_shift_ff ? dr_out
+ : tap_fsm_ir_shift_ff ? tap_ir_shift_ff[0]
+ : 1'b0;
+
+// TAPC TDO signals
+assign tapc_tdo_en = tdo_en_ff;
+assign tapc_tdo = tdo_out_ff;
+
+//------------------------------------------------------------------------------
+// TAPC Data Registers
+//------------------------------------------------------------------------------
+//
+ // Registers:
+ // - BYPASS register
+ // - IDCODE register
+ // - BUILD ID register
+
+// BYPASS register
+//------------------------------------------------------------------------------
+// 1-bit mandatory IEEE 1149.1 compliant register
+
+scr1_tapc_shift_reg #(
+ .SCR1_WIDTH (SCR1_TAP_DR_BYPASS_WIDTH),
+ .SCR1_RESET_VALUE (SCR1_TAP_DR_BYPASS_WIDTH'(0))
+) i_bypass_reg (
+ .clk (tapc_tck ),
+ .rst_n (tapc_trst_n ),
+ .rst_n_sync (trst_n_int ),
+ .fsm_dr_select (dr_bypass_sel ),
+ .fsm_dr_capture (tap_fsm_dr_capture_ff),
+ .fsm_dr_shift (tap_fsm_dr_shift_ff ),
+ .din_serial (tapc_tdi ),
+ .din_parallel (1'b0 ),
+ .dout_serial (dr_bypass_tdo ),
+ .dout_parallel ( )
+);
+
+// IDCODE register
+//------------------------------------------------------------------------------
+// Holds the Device ID value (mandatory IEEE 1149.1 compliant register)
+
+scr1_tapc_shift_reg #(
+ .SCR1_WIDTH (SCR1_TAP_DR_IDCODE_WIDTH),
+ .SCR1_RESET_VALUE (SCR1_TAP_DR_IDCODE_WIDTH'(0))
+) i_tap_idcode_reg (
+ .clk (tapc_tck ),
+ .rst_n (tapc_trst_n ),
+ .rst_n_sync (trst_n_int ),
+ .fsm_dr_select (dr_idcode_sel ),
+ .fsm_dr_capture (tap_fsm_dr_capture_ff ),
+ .fsm_dr_shift (tap_fsm_dr_shift_ff ),
+ .din_serial (tapc_tdi ),
+ .din_parallel (soc2tapc_fuse_idcode_i),
+ .dout_serial (dr_idcode_tdo ),
+ .dout_parallel ( )
+);
+
+// BUILD ID register
+//------------------------------------------------------------------------------
+// Holds the BUILD ID value
+
+scr1_tapc_shift_reg #(
+ .SCR1_WIDTH (SCR1_TAP_DR_BLD_ID_WIDTH),
+ .SCR1_RESET_VALUE (SCR1_TAP_DR_BLD_ID_WIDTH'(0))
+) i_tap_dr_bld_id_reg (
+ .clk (tapc_tck ),
+ .rst_n (tapc_trst_n ),
+ .rst_n_sync (trst_n_int ),
+ .fsm_dr_select (dr_bld_id_sel ),
+ .fsm_dr_capture (tap_fsm_dr_capture_ff),
+ .fsm_dr_shift (tap_fsm_dr_shift_ff ),
+ .din_serial (tapc_tdi ),
+ .din_parallel (SCR1_TAP_BLD_ID_VALUE),
+ .dout_serial (dr_bld_id_tdo ),
+ .dout_parallel ( )
+);
+
+//------------------------------------------------------------------------------
+// DMI/SCU scan-chains signals
+//------------------------------------------------------------------------------
+
+assign tapc2tapcsync_ch_tdi_o = tapc_tdi;
+assign tapc2tapcsync_ch_capture_o = tap_fsm_dr_capture_ff;
+assign tapc2tapcsync_ch_shift_o = tap_fsm_dr_shift_ff;
+assign tapc2tapcsync_ch_update_o = tap_fsm_dr_update_ff;
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+// X checks
+SCR1_SVA_TAPC_XCHECK : assert property (
+ @(posedge tapc_tck) disable iff (~tapc_trst_n)
+ !$isunknown({tapc_tms, tapc_tdi})
+) else $error("TAPC error: unknown values");
+
+SCR1_SVA_TAPC_XCHECK_NEGCLK : assert property (
+ @(negedge tapc_tck) disable iff (tap_fsm_ff != SCR1_TAP_STATE_DR_SHIFT)
+ !$isunknown({tapcsync2tapc_ch_tdo_i})
+) else $error("TAPC @negedge error: unknown values");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_tapc
+
+`endif // SCR1_DBG_EN
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_tapc_shift_reg.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_tapc_shift_reg.sv
new file mode 100644
index 0000000..a577bcc
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_tapc_shift_reg.sv
@@ -0,0 +1,112 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_tapc_shift_reg.sv>
+/// @brief TAPC shift register. Parameterized implementation of JTAG TAPC's Shift Register.
+///
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+module scr1_tapc_shift_reg #(
+ parameter int unsigned SCR1_WIDTH = 8, // Register width, bits
+ parameter logic [SCR1_WIDTH-1:0] SCR1_RESET_VALUE = '0 // Register's value after reset
+) (
+ input logic clk, // Clock
+ input logic rst_n, // Async reset
+ input logic rst_n_sync, // Sync reset
+ // TAP FSM's control signals:
+ input logic fsm_dr_select, // - for this DR selection (operation enabling);
+ input logic fsm_dr_capture, // - to capture parallel input's data into shift register;
+ input logic fsm_dr_shift, // - to enable data shifting;
+ // Inputs:
+ input logic din_serial, // - serial (shift_reg[msb/SCR1_WIDTH]);
+ input logic [SCR1_WIDTH-1:0] din_parallel, // - parallel (shift register's input).
+ // Outputs:
+ output logic dout_serial, // - serial (shift_reg[0]);
+ output logic [SCR1_WIDTH-1:0] dout_parallel // - parallel (shift register's output).
+);
+
+//-------------------------------------------------------------------------------
+// Local signals declaration
+//-------------------------------------------------------------------------------
+logic [SCR1_WIDTH-1:0] shift_reg;
+
+//-------------------------------------------------------------------------------
+// Shift register
+//-------------------------------------------------------------------------------
+generate
+ if (SCR1_WIDTH > 1)
+ begin : dr_shift_reg
+
+ always_ff @(posedge clk, negedge rst_n)
+ begin
+ if (~rst_n) begin
+ shift_reg <= SCR1_RESET_VALUE;
+ end
+ else if (~rst_n_sync) begin
+ shift_reg <= SCR1_RESET_VALUE;
+ end
+ else if (fsm_dr_select & fsm_dr_capture) begin
+ shift_reg <= din_parallel;
+ end
+ else if (fsm_dr_select & fsm_dr_shift) begin
+ shift_reg <= {din_serial, shift_reg[SCR1_WIDTH-1:1]};
+ end
+ end
+
+ end
+ else begin : dr_shift_reg
+
+ always_ff @(posedge clk, negedge rst_n)
+ begin
+ if (~rst_n) begin
+ shift_reg <= SCR1_RESET_VALUE;
+ end
+ else if (~rst_n_sync) begin
+ shift_reg <= SCR1_RESET_VALUE;
+ end
+ else if (fsm_dr_select & fsm_dr_capture) begin
+ shift_reg <= din_parallel;
+ end
+ else if (fsm_dr_select & fsm_dr_shift) begin
+ shift_reg <= din_serial;
+ end
+ end
+
+ end
+endgenerate
+
+//-------------------------------------------------------------------------------
+// Parallel output
+//-------------------------------------------------------------------------------
+assign dout_parallel = shift_reg;
+
+//-------------------------------------------------------------------------------
+// Serial output
+//-------------------------------------------------------------------------------
+assign dout_serial = shift_reg[0];
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+// X checks
+SCR1_SVA_TAPC_SHIFTREG_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown({
+ rst_n_sync,
+ fsm_dr_select,
+ fsm_dr_capture,
+ fsm_dr_shift,
+ din_serial,
+ din_parallel
+ })
+) else begin
+ $error("TAPC Shift Reg error: unknown values");
+end
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_tapc_shift_reg
+
+`endif // SCR1_DBG_EN
diff --git a/verilog/rtl/syntacore_scr1/src/core/scr1_tapc_synchronizer.sv b/verilog/rtl/syntacore_scr1/src/core/scr1_tapc_synchronizer.sv
new file mode 100644
index 0000000..0d94705
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/core/scr1_tapc_synchronizer.sv
@@ -0,0 +1,183 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_tapc_synchronizer.sv>
+/// @brief TAPC clock domain crossing synchronizer
+///
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+`include "scr1_tapc.svh"
+`include "scr1_dm.svh"
+
+module scr1_tapc_synchronizer (
+ // System common signals
+ input logic pwrup_rst_n, // Power-Up Reset
+ input logic dm_rst_n, // Debug Module Reset
+ input logic clk, // System Clock (SysCLK)
+
+ // JTAG common signals
+ input logic tapc_trst_n, // JTAG Test Reset (TRSTn)
+ input logic tapc_tck, // JTAG Test Clock (TCK)
+
+
+ // DMI/SCU scan-chains
+ input logic tapc2tapcsync_scu_ch_sel_i, // SCU Chain Select input (TCK domain)
+ output logic tapcsync2scu_ch_sel_o, // SCU Chain Select output (SysCLK domain)
+ input logic tapc2tapcsync_dmi_ch_sel_i, // DMI Chain Select input (TCK domain)
+ output logic tapcsync2dmi_ch_sel_o, // DMI Chain Select output (SysCLK domain)
+
+ input logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc2tapcsync_ch_id_i, // DMI/SCU Chain Identifier input (TCK domain)
+ output logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapcsync2core_ch_id_o, // DMI/SCU Chain Identifier output (SysCLK domain)
+
+ input logic tapc2tapcsync_ch_capture_i, // DMI/SCU Chain Capture input (TCK domain)
+ output logic tapcsync2core_ch_capture_o, // DMI/SCU Chain Capture output (SysCLK domain)
+
+ input logic tapc2tapcsync_ch_shift_i, // DMI/SCU Chain Shift input (TCK domain)
+ output logic tapcsync2core_ch_shift_o, // DMI/SCU Chain Shift output (SysCLK domain)
+
+ input logic tapc2tapcsync_ch_update_i, // DMI/SCU Chain Update input (TCK domain)
+ output logic tapcsync2core_ch_update_o, // DMI/SCU Chain Update output (SysCLK domain)
+
+ input logic tapc2tapcsync_ch_tdi_i, // DMI/SCU Chain TDI input (TCK domain)
+ output logic tapcsync2core_ch_tdi_o, // DMI/SCU Chain TDI output (SysCLK domain)
+
+ output logic tapc2tapcsync_ch_tdo_i, // DMI/SCU Chain TDO output (TCK domain)
+ input logic tapcsync2core_ch_tdo_o // DMI/SCU Chain TDO input (SysCLK domain)
+);
+
+//-------------------------------------------------------------------------------
+// Local signals declaration
+//-------------------------------------------------------------------------------
+
+logic tck_divpos;
+logic tck_divneg;
+logic tck_rise_load;
+logic tck_rise_reset;
+logic tck_fall_load;
+logic tck_fall_reset;
+logic [3:0] tck_divpos_sync;
+logic [3:0] tck_divneg_sync;
+logic [2:0] dmi_ch_capture_sync;
+logic [2:0] dmi_ch_shift_sync;
+logic [2:0] dmi_ch_tdi_sync;
+
+//-------------------------------------------------------------------------------
+// Logic
+//-------------------------------------------------------------------------------
+
+always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tck_divpos <= 1'b0;
+ end else begin
+ tck_divpos <= ~tck_divpos;
+ end
+end
+
+always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ tck_divneg <= 1'b0;
+ end else begin
+ tck_divneg <= ~tck_divneg;
+ end
+end
+
+always_ff @(posedge clk, negedge pwrup_rst_n) begin
+ if (~pwrup_rst_n) begin
+ tck_divpos_sync <= 4'd0;
+ tck_divneg_sync <= 4'd0;
+ end else begin
+ tck_divpos_sync <= {tck_divpos_sync[2:0], tck_divpos};
+ tck_divneg_sync <= {tck_divneg_sync[2:0], tck_divneg};
+ end
+end
+
+assign tck_rise_load = tck_divpos_sync[2] ^ tck_divpos_sync[1];
+assign tck_rise_reset = tck_divpos_sync[3] ^ tck_divpos_sync[2];
+assign tck_fall_load = tck_divneg_sync[2] ^ tck_divneg_sync[1];
+assign tck_fall_reset = tck_divneg_sync[3] ^ tck_divneg_sync[2];
+
+always_ff @(posedge clk, negedge pwrup_rst_n) begin
+ if (~pwrup_rst_n) begin
+ tapcsync2core_ch_update_o <= '0;
+ end else begin
+ if (tck_fall_load) begin
+ tapcsync2core_ch_update_o <= tapc2tapcsync_ch_update_i;
+ end else if (tck_fall_reset) begin
+ tapcsync2core_ch_update_o <= '0;
+ end
+ end
+end
+
+always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
+ if (~tapc_trst_n) begin
+ dmi_ch_capture_sync[0] <= '0;
+ dmi_ch_shift_sync[0] <= '0;
+ end else begin
+ dmi_ch_capture_sync[0] <= tapc2tapcsync_ch_capture_i;
+ dmi_ch_shift_sync[0] <= tapc2tapcsync_ch_shift_i;
+ end
+end
+
+always_ff @(posedge clk, negedge pwrup_rst_n) begin
+ if (~pwrup_rst_n) begin
+ dmi_ch_capture_sync[2:1] <= '0;
+ dmi_ch_shift_sync[2:1] <= '0;
+ end else begin
+ dmi_ch_capture_sync[2:1] <= {dmi_ch_capture_sync[1], dmi_ch_capture_sync[0]};
+ dmi_ch_shift_sync[2:1] <= {dmi_ch_shift_sync[1], dmi_ch_shift_sync[0]};
+ end
+end
+
+always_ff @(posedge clk, negedge pwrup_rst_n) begin
+ if (~pwrup_rst_n) begin
+ dmi_ch_tdi_sync <= '0;
+ end else begin
+ dmi_ch_tdi_sync <= {dmi_ch_tdi_sync[1:0], tapc2tapcsync_ch_tdi_i};
+ end
+end
+
+always_ff @(posedge clk, negedge pwrup_rst_n) begin
+ if (~pwrup_rst_n) begin
+ tapcsync2core_ch_capture_o <= '0;
+ tapcsync2core_ch_shift_o <= '0;
+ tapcsync2core_ch_tdi_o <= '0;
+ end else begin
+ if (tck_rise_load) begin
+ tapcsync2core_ch_capture_o <= dmi_ch_capture_sync[2];
+ tapcsync2core_ch_shift_o <= dmi_ch_shift_sync[2];
+ tapcsync2core_ch_tdi_o <= dmi_ch_tdi_sync[2];
+ end else if (tck_rise_reset) begin
+ tapcsync2core_ch_capture_o <= '0;
+ tapcsync2core_ch_shift_o <= '0;
+ tapcsync2core_ch_tdi_o <= '0;
+ end
+ end
+end
+
+always_ff @(posedge clk, negedge dm_rst_n) begin
+ if (~dm_rst_n) begin
+ tapcsync2dmi_ch_sel_o <= '0;
+ tapcsync2core_ch_id_o <= '0;
+ end else begin
+ if (tck_rise_load) begin
+ tapcsync2dmi_ch_sel_o <= tapc2tapcsync_dmi_ch_sel_i;
+ tapcsync2core_ch_id_o <= tapc2tapcsync_ch_id_i;
+ end
+ end
+end
+
+always_ff @(posedge clk, negedge pwrup_rst_n) begin
+ if (~pwrup_rst_n) begin
+ tapcsync2scu_ch_sel_o <= '0;
+ end else begin
+ if (tck_rise_load) begin
+ tapcsync2scu_ch_sel_o <= tapc2tapcsync_scu_ch_sel_i;
+ end
+ end
+end
+
+assign tapc2tapcsync_ch_tdo_i = tapcsync2core_ch_tdo_o;
+
+endmodule : scr1_tapc_synchronizer
+
+`endif // SCR1_DBG_EN
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_ahb.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_ahb.svh
new file mode 100644
index 0000000..54cd4e1
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_ahb.svh
@@ -0,0 +1,59 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_ahb.svh>
+/// @brief AHB header file
+///
+
+`ifndef SCR1_AHB_SVH
+`define SCR1_AHB_SVH
+
+`include "scr1_arch_description.svh"
+
+parameter SCR1_AHB_WIDTH = 32;
+
+// Encoding for HTRANS signal
+parameter logic [1:0] SCR1_HTRANS_IDLE = 2'b00;
+parameter logic [1:0] SCR1_HTRANS_NONSEQ = 2'b10;
+`ifdef SCR1_XPROP_EN
+parameter logic [1:0] SCR1_HTRANS_ERR = 'x;
+`else // SCR1_XPROP_EN
+parameter logic [1:0] SCR1_HTRANS_ERR = '0;
+`endif // SCR1_XPROP_EN
+
+// Encoding for HBURST signal
+parameter logic [2:0] SCR1_HBURST_SINGLE = 3'b000;
+`ifdef SCR1_XPROP_EN
+parameter logic [2:0] SCR1_HBURST_ERR = 'x;
+`else // SCR1_XPROP_EN
+parameter logic [1:0] SCR1_HBURST_ERR = '0;
+`endif // SCR1_XPROP_EN
+
+// Encoding for HSIZE signal
+parameter logic [2:0] SCR1_HSIZE_8B = 3'b000;
+parameter logic [2:0] SCR1_HSIZE_16B = 3'b001;
+parameter logic [2:0] SCR1_HSIZE_32B = 3'b010;
+`ifdef SCR1_XPROP_EN
+parameter logic [2:0] SCR1_HSIZE_ERR = 'x;
+`else // SCR1_XPROP_EN
+parameter logic [1:0] SCR1_HSIZE_ERR = '0;
+`endif // SCR1_XPROP_EN
+
+// Encoding HPROT signal
+// HPROT[0] : 0 - instr; 1 - data
+// HPROT[1] : 0 - user; 1 - privilege
+// HPROT[2] : 0 - not buffer; 1 - buffer
+// HPROT[3] : 0 - cacheable; 1 - cacheable
+parameter SCR1_HPROT_DATA = 0;
+parameter SCR1_HPROT_PRV = 1;
+parameter SCR1_HPROT_BUF = 2;
+parameter SCR1_HPROT_CACHE = 3;
+
+// Encoding HRESP signal
+parameter logic SCR1_HRESP_OKAY = 1'b0;
+parameter logic SCR1_HRESP_ERROR = 1'b1;
+`ifdef SCR1_XPROP_EN
+parameter logic SCR1_HRESP_ERR = 1'bx;
+`else // SCR1_XPROP_EN
+parameter logic SCR1_HRESP_ERR = 1'b0;
+`endif // SCR1_XPROP_EN
+
+`endif // SCR1_AHB_SVH
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_arch_description.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_arch_description.svh
new file mode 100644
index 0000000..7c8b532
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_arch_description.svh
@@ -0,0 +1,215 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_arch_description.svh>
+/// @brief Architecture description file
+///
+
+`ifndef SCR1_ARCH_DESCRIPTION_SVH
+`define SCR1_ARCH_DESCRIPTION_SVH
+
+
+//------------------------------------------------------------------------------
+// CORE FUNDAMENTAL PARAMETERS
+//------------------------------------------------------------------------------
+
+// SCR1 core identifiers
+`define SCR1_MIMPID 32'h21051400
+`define SCR1_MVENDORID 32'h00000000
+
+// Width of main registers and buses
+`define SCR1_XLEN 32
+`define SCR1_IMEM_AWIDTH `SCR1_XLEN
+`define SCR1_IMEM_DWIDTH `SCR1_XLEN
+`define SCR1_DMEM_AWIDTH `SCR1_XLEN
+`define SCR1_DMEM_DWIDTH `SCR1_XLEN
+
+// TAP IDCODE
+`define SCR1_TAP_IDCODE 'hDEB11001
+
+
+`ifdef SCR1_ARCH_CUSTOM
+//------------------------------------------------------------------------------
+// INCLUDE SCR1_ARCH_CUSTOM.SVH
+//------------------------------------------------------------------------------
+
+// The external file scr1_arch_custom.svh is used for the open SCR1-SDK project,
+// and can also be used for any custom projects.
+
+// The file sets:
+// - target platform (FPGA/ASIC), which affects the choice of logical constructs;
+// - device build ID;
+// - address constants;
+// - could enables configuration parameters.
+
+// Possible targets:
+// `define SCR1_TRGT_FPGA_INTEL // target platform is Intel FPGAs
+// `define SCR1_TRGT_FPGA_INTEL_MAX10 // target platform is Intel MAX 10 FPGAs (used in the SCR1-SDK project)
+// `define SCR1_TRGT_FPGA_INTEL_ARRIAV // target platform is Intel Arria V FPGAs (used in the SCR1-SDK project)
+// `define SCR1_TRGT_FPGA_XILINX // target platform is Xilinx FPGAs (used in the SCR1-SDK project)
+// `define SCR1_TRGT_ASIC // target platform is ASIC
+// `define SCR1_TRGT_SIMULATION // target is simulation (enable simulation code)
+
+ `include "scr1_arch_custom.svh"
+
+`endif // SCR1_ARCH_CUSTOM
+
+
+//------------------------------------------------------------------------------
+// RECOMMENDED CORE ARCHITECTURE CONFIGURATIONS
+//------------------------------------------------------------------------------
+
+// Uncomment one of these defines to set the recommended configuration:
+
+//`define SCR1_CFG_RV32IMC_MAX
+//`define SCR1_CFG_RV32IC_BASE
+//`define SCR1_CFG_RV32EC_MIN
+
+// If all defines are commented, custom configuration will be used (see below)
+
+//------------------------------------------------------------------------------
+// READ-ONLY: settings for recommended configurations
+`ifdef SCR1_CFG_RV32IMC_MAX
+ `define SCR1_RVI_EXT
+ `define SCR1_RVM_EXT
+ `define SCR1_RVC_EXT
+ parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 26;
+ `define SCR1_MTVEC_MODE_EN
+ `define SCR1_FAST_MUL
+ `define SCR1_MPRF_RST_EN
+ `define SCR1_MCOUNTEN_EN
+ `define SCR1_DBG_EN
+ `define SCR1_TDU_EN
+ parameter int unsigned SCR1_TDU_TRIG_NUM = 4;
+ `define SCR1_TDU_ICOUNT_EN
+ `define SCR1_IPIC_EN
+ `define SCR1_IPIC_SYNC_EN
+ `define SCR1_TCM_EN
+`elsif SCR1_CFG_RV32IC_BASE
+ `define SCR1_RVI_EXT
+ `define SCR1_RVC_EXT
+ parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 16;
+ `define SCR1_MTVEC_MODE_EN
+ `define SCR1_NO_DEC_STAGE
+ `define SCR1_MPRF_RST_EN
+ `define SCR1_MCOUNTEN_EN
+ `define SCR1_DBG_EN
+ `define SCR1_TDU_EN
+ parameter int unsigned SCR1_TDU_TRIG_NUM = 2;
+ `define SCR1_TDU_ICOUNT_EN
+ `define SCR1_IPIC_EN
+ `define SCR1_IPIC_SYNC_EN
+ `define SCR1_TCM_EN
+`elsif SCR1_CFG_RV32EC_MIN
+ `define SCR1_RVE_EXT
+ `define SCR1_RVC_EXT
+ parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 0;
+ `define SCR1_NO_DEC_STAGE
+ `define SCR1_NO_EXE_STAGE
+ `define SCR1_TCM_EN
+
+`else // begin custom configuration section
+
+
+//------------------------------------------------------------------------------
+// CUSTOM CORE ARCHITECTURE CONFIGURATION
+//------------------------------------------------------------------------------
+
+// To fine-tune custom configuration, you can change the values in this section.
+// Make sure that the defines of the recommended configurations are commented,
+// otherwise this section will be inactive.
+
+// RISC-V ISA options
+//`define SCR1_RVE_EXT // enable RV32E base integer instruction set, otherwise RV32I will be used
+`define SCR1_RVM_EXT // enable standard extension "M" for integer hardware multiplier and divider
+`define SCR1_RVC_EXT // enable standard extension "C" for compressed instructions
+parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 26; // number of writable high-order bits in MTVEC.base field
+ // legal values are 0 to 26
+ // read-only bits are hardwired to reset value
+`define SCR1_MTVEC_MODE_EN // enable writable MTVEC.mode field to allow vectored irq mode, otherwise only direct mode is possible
+
+`ifndef SCR1_RVE_EXT
+ `define SCR1_RVI_EXT // RV32E base integer instruction set if SCR1_RVE_EXT is not enabled
+`endif // ~SCR1_RVE_EXT
+
+// Core pipeline options (power-performance-area optimization)
+`define SCR1_NO_DEC_STAGE // disable register between IFU and IDU
+`define SCR1_NO_EXE_STAGE // disable register between IDU and EXU
+`define SCR1_NEW_PC_REG // enable register in IFU for New_PC value
+`define SCR1_FAST_MUL // enable fast one-cycle multiplication, otherwise multiplication takes 32 cycles
+`define SCR1_CLKCTRL_EN // enable global clock gating
+`define SCR1_MPRF_RST_EN // enable reset for MPRF
+`define SCR1_MCOUNTEN_EN // enable custom MCOUNTEN CSR for counter control
+
+// Uncore options
+`define SCR1_DBG_EN // enable Debug Subsystem (TAPC, DM, SCU, HDU)
+`define SCR1_TDU_EN // enable Trigger Debug Unit (hardware breakpoints)
+parameter int unsigned SCR1_TDU_TRIG_NUM = 2; // number of hardware triggers
+`define SCR1_TDU_ICOUNT_EN // enable hardware triggers on instruction counter
+`define SCR1_IPIC_EN // enable Integrated Programmable Interrupt Controller
+`define SCR1_IPIC_SYNC_EN // enable IPIC synchronizer
+`define SCR1_TCM_EN // enable Tightly-Coupled Memory
+
+`endif // end custom configuration section
+
+
+//------------------------------------------------------------------------------
+// CORE INTEGRATION OPTIONS
+//------------------------------------------------------------------------------
+
+// Bypasses on AXI/AHB bridge I/O
+`define SCR1_IMEM_AHB_IN_BP // bypass instruction memory AHB bridge input register
+`define SCR1_IMEM_AHB_OUT_BP // bypass instruction memory AHB bridge output register
+`define SCR1_DMEM_AHB_IN_BP // bypass data memory AHB bridge input register
+`define SCR1_DMEM_AHB_OUT_BP // bypass data memory AHB bridge output register
+`define SCR1_IMEM_AXI_REQ_BP // bypass instruction memory AXI bridge request register
+`define SCR1_IMEM_AXI_RESP_BP // bypass instruction memory AXI bridge response register
+`define SCR1_DMEM_AXI_REQ_BP // bypass data memory AXI bridge request register
+`define SCR1_DMEM_AXI_RESP_BP // bypass data memory AXI bridge response register
+
+`ifndef SCR1_ARCH_CUSTOM
+// Default address constants (if scr1_arch_custom.svh is not used)
+parameter bit [`SCR1_XLEN-1:0] SCR1_ARCH_RST_VECTOR = 'h200; // Reset vector value (start address after reset)
+parameter bit [`SCR1_XLEN-1:0] SCR1_ARCH_MTVEC_BASE = 'h1C0; // MTVEC.base field reset value, or constant value for MTVEC.base bits that are hardwired
+
+parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TCM_ADDR_MASK = 'hFFFF0000; // TCM mask and size; size in bytes is two's complement of the mask value
+parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TCM_ADDR_PATTERN = 'h00480000; // TCM address match pattern
+
+parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TIMER_ADDR_MASK = 'hFFFFFFE0; // Timer mask
+parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TIMER_ADDR_PATTERN = 'h00490000; // Timer address match pattern
+
+// Device build ID
+ `define SCR1_ARCH_BUILD_ID `SCR1_MIMPID
+
+`endif // SCR1_ARCH_CUSTOM
+
+
+//------------------------------------------------------------------------------
+// TARGET-SPECIFIC OPTIONS
+//------------------------------------------------------------------------------
+
+// RAM-based MPRF can be used for Intel FPGAs only
+`ifdef SCR1_TRGT_FPGA_INTEL
+ `define SCR1_MPRF_RAM // implements MPRF with dedicated RAM blocks
+`endif
+
+// EXU_STAGE_BYPASS and MPRF_RST_EN must be disabled for RAM-based MPRF
+`ifdef SCR1_MPRF_RAM
+ `undef SCR1_NO_EXE_STAGE
+ `undef SCR1_MPRF_RST_EN
+`endif
+
+
+//------------------------------------------------------------------------------
+// SIMULATION OPTIONS
+//------------------------------------------------------------------------------
+
+//`define SCR1_TRGT_SIMULATION // enable simulation code (automatically defined by root makefile)
+//`define SCR1_TRACE_LOG_EN // enable tracelog
+//`define SCR1_XPROP_EN // enable X-propagation
+
+// Addresses used in testbench
+localparam [`SCR1_XLEN-1:0] SCR1_SIM_EXIT_ADDR = 32'h0000_00F8;
+localparam [`SCR1_XLEN-1:0] SCR1_SIM_PRINT_ADDR = 32'hF000_0000;
+localparam [`SCR1_XLEN-1:0] SCR1_SIM_EXT_IRQ_ADDR = 32'hF000_0100;
+localparam [`SCR1_XLEN-1:0] SCR1_SIM_SOFT_IRQ_ADDR = 32'hF000_0200;
+
+`endif // SCR1_ARCH_DESCRIPTION_SVH
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_arch_types.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_arch_types.svh
new file mode 100644
index 0000000..62f1037
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_arch_types.svh
@@ -0,0 +1,72 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_arch_types.svh>
+/// @brief Pipeline types description file
+///
+
+`ifndef SCR1_ARCH_TYPES_SVH
+`define SCR1_ARCH_TYPES_SVH
+
+`include "scr1_arch_description.svh"
+
+//-------------------------------------------------------------------------------
+// MPRF and CSR parameters
+//-------------------------------------------------------------------------------
+
+`ifdef SCR1_RVE_EXT
+ `define SCR1_MPRF_AWIDTH 4
+ `define SCR1_MPRF_SIZE 16
+`else // SCR1_RVE_EXT
+ `define SCR1_MPRF_AWIDTH 5
+ `define SCR1_MPRF_SIZE 32
+`endif // SCR1_RVE_EXT
+
+typedef logic [`SCR1_XLEN-1:0] type_scr1_mprf_v;
+typedef logic [`SCR1_XLEN-1:0] type_scr1_pc_v;
+
+parameter int unsigned SCR1_CSR_ADDR_WIDTH = 12;
+parameter int unsigned SCR1_CSR_MTVEC_BASE_ZERO_BITS = 6;
+parameter int unsigned SCR1_CSR_MTVEC_BASE_VAL_BITS = `SCR1_XLEN-SCR1_CSR_MTVEC_BASE_ZERO_BITS;
+parameter bit [`SCR1_XLEN-1:SCR1_CSR_MTVEC_BASE_ZERO_BITS] SCR1_CSR_MTVEC_BASE_WR_RST_VAL =
+ SCR1_CSR_MTVEC_BASE_VAL_BITS'(SCR1_ARCH_MTVEC_BASE >> SCR1_CSR_MTVEC_BASE_ZERO_BITS);
+parameter int unsigned SCR1_CSR_MTVEC_BASE_RO_BITS = (`SCR1_XLEN-(SCR1_CSR_MTVEC_BASE_ZERO_BITS+SCR1_MTVEC_BASE_WR_BITS));
+
+`define SCR1_MTVAL_ILLEGAL_INSTR_EN
+
+//-------------------------------------------------------------------------------
+// Exception and IRQ codes
+//-------------------------------------------------------------------------------
+parameter int unsigned SCR1_EXC_CODE_WIDTH_E = 4;
+
+// Exceptions
+typedef enum logic [SCR1_EXC_CODE_WIDTH_E-1:0] {
+ SCR1_EXC_CODE_INSTR_MISALIGN = 4'd0, // from EXU
+ SCR1_EXC_CODE_INSTR_ACCESS_FAULT = 4'd1, // from IFU
+ SCR1_EXC_CODE_ILLEGAL_INSTR = 4'd2, // from IDU or CSR
+ SCR1_EXC_CODE_BREAKPOINT = 4'd3, // from IDU or BRKM
+ SCR1_EXC_CODE_LD_ADDR_MISALIGN = 4'd4, // from LSU
+ SCR1_EXC_CODE_LD_ACCESS_FAULT = 4'd5, // from LSU
+ SCR1_EXC_CODE_ST_ADDR_MISALIGN = 4'd6, // from LSU
+ SCR1_EXC_CODE_ST_ACCESS_FAULT = 4'd7, // from LSU
+ SCR1_EXC_CODE_ECALL_M = 4'd11 // from IDU
+} type_scr1_exc_code_e;
+
+// IRQs, reset
+parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_IRQ_M_SOFTWARE = 4'd3;
+parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_IRQ_M_TIMER = 4'd7;
+parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_IRQ_M_EXTERNAL = 4'd11;
+parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_RESET = 4'd0;
+
+//-------------------------------------------------------------------------------
+// Operand width for BRKM
+//-------------------------------------------------------------------------------
+typedef enum logic [1:0] {
+ SCR1_OP_WIDTH_BYTE = 2'b00,
+ SCR1_OP_WIDTH_HALF = 2'b01,
+ SCR1_OP_WIDTH_WORD = 2'b10
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_OP_WIDTH_ERROR = 'x
+`endif // SCR1_XPROP_EN
+} type_scr1_op_width_e;
+
+`endif //SCR1_ARCH_TYPES_SVH
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_csr.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_csr.svh
new file mode 100644
index 0000000..18dcafb
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_csr.svh
@@ -0,0 +1,196 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_csr.svh>
+/// @brief CSR mapping/description file
+///
+
+`ifndef SCR1_CSR_SVH
+`define SCR1_CSR_SVH
+
+`include "scr1_arch_description.svh"
+`include "scr1_arch_types.svh"
+`include "scr1_ipic.svh"
+
+`ifdef SCR1_RVE_EXT
+`define SCR1_CSR_REDUCED_CNT
+`endif // SCR1_RVE_EXT
+
+`ifdef SCR1_CSR_REDUCED_CNT
+`undef SCR1_MCOUNTEN_EN
+`endif // SCR1_CSR_REDUCED_CNT
+
+//-------------------------------------------------------------------------------
+// CSR addresses (standard)
+//-------------------------------------------------------------------------------
+
+// Machine Information Registers (read-only)
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MVENDORID = 'hF11;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MARCHID = 'hF12;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MIMPID = 'hF13;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MHARTID = 'hF14;
+
+// Machine Trap Setup (read-write)
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MSTATUS = 'h300;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MISA = 'h301;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MIE = 'h304;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MTVEC = 'h305;
+
+// Machine Trap Handling (read-write)
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MSCRATCH = 'h340;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MEPC = 'h341;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCAUSE = 'h342;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MTVAL = 'h343;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MIP = 'h344;
+
+// Machine Counters/Timers (read-write)
+`ifndef SCR1_CSR_REDUCED_CNT
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCYCLE = 'hB00;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MINSTRET = 'hB02;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCYCLEH = 'hB80;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MINSTRETH = 'hB82;
+`endif // SCR1_CSR_REDUCED_CNT
+
+// Shadow Counters/Timers (read-only)
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TIME = 'hC01;
+`ifndef SCR1_CSR_REDUCED_CNT
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_CYCLE = 'hC00;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_INSTRET = 'hC02;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TIMEH = 'hC81;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_CYCLEH = 'hC80;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_INSTRETH = 'hC82;
+`endif // SCR1_CSR_REDUCED_CNT
+
+`ifdef SCR1_DBG_EN
+//parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_DBGC_SCRATCH = 'h7C8;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_HDU_MBASE = 'h7B0;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_HDU_MSPAN = 'h004; // must be power of 2
+`endif // SCR1_DBG_EN
+
+//-------------------------------------------------------------------------------
+// CSR addresses (non-standard)
+//-------------------------------------------------------------------------------
+`ifdef SCR1_MCOUNTEN_EN
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCOUNTEN = 'h7E0;
+`endif // SCR1_MCOUNTEN_EN
+
+`ifdef SCR1_TDU_EN
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_MBASE = 'h7A0;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_MSPAN = 'h008; // must be power of 2
+`endif // SCR1_TDU_EN
+
+`ifdef SCR1_IPIC_EN
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_BASE = 'hBF0;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_CISV = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_CISV );
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_CICSR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_CICSR);
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_IPR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_IPR );
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_ISVR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_ISVR );
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_EOI = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_EOI );
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_SOI = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_SOI );
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_IDX = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_IDX );
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_ICSR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_ICSR );
+`endif // SCR1_IPIC_EN
+
+
+//-------------------------------------------------------------------------------
+// CSR definitions
+//-------------------------------------------------------------------------------
+
+// General
+parameter bit [`SCR1_XLEN-1:0] SCR1_RST_VECTOR = SCR1_ARCH_RST_VECTOR;
+
+// Reset values TBD
+parameter bit SCR1_CSR_MIE_MSIE_RST_VAL = 1'b0;
+parameter bit SCR1_CSR_MIE_MTIE_RST_VAL = 1'b0;
+parameter bit SCR1_CSR_MIE_MEIE_RST_VAL = 1'b0;
+
+parameter bit SCR1_CSR_MIP_MSIP_RST_VAL = 1'b0;
+parameter bit SCR1_CSR_MIP_MTIP_RST_VAL = 1'b0;
+parameter bit SCR1_CSR_MIP_MEIP_RST_VAL = 1'b0;
+
+parameter bit SCR1_CSR_MSTATUS_MIE_RST_VAL = 1'b0;
+parameter bit SCR1_CSR_MSTATUS_MPIE_RST_VAL = 1'b1;
+
+// MISA
+`define SCR1_RVC_ENC `SCR1_XLEN'h0004
+`define SCR1_RVE_ENC `SCR1_XLEN'h0010
+`define SCR1_RVI_ENC `SCR1_XLEN'h0100
+`define SCR1_RVM_ENC `SCR1_XLEN'h1000
+parameter bit [1:0] SCR1_MISA_MXL_32 = 2'd1;
+parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MISA = (SCR1_MISA_MXL_32 << (`SCR1_XLEN-2))
+`ifndef SCR1_RVE_EXT
+ | `SCR1_RVI_ENC
+`else // SCR1_RVE_EXT
+ | `SCR1_RVE_ENC
+`endif // SCR1_RVE_EXT
+`ifdef SCR1_RVC_EXT
+ | `SCR1_RVC_ENC
+`endif // SCR1_RVC_EXT
+`ifdef SCR1_RVM_EXT
+ | `SCR1_RVM_ENC
+`endif // SCR1_RVM_EXT
+ ;
+
+// MVENDORID
+parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MVENDORID = `SCR1_MVENDORID;
+
+// MARCHID
+parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MARCHID = `SCR1_XLEN'd8;
+
+// MIMPID
+parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MIMPID = `SCR1_MIMPID;
+
+// MSTATUS
+parameter bit [1:0] SCR1_CSR_MSTATUS_MPP = 2'b11;
+parameter int unsigned SCR1_CSR_MSTATUS_MIE_OFFSET = 3;
+parameter int unsigned SCR1_CSR_MSTATUS_MPIE_OFFSET = 7;
+parameter int unsigned SCR1_CSR_MSTATUS_MPP_OFFSET = 11;
+
+// MTVEC
+// bits [5:0] are always zero
+parameter bit [`SCR1_XLEN-1:SCR1_CSR_MTVEC_BASE_ZERO_BITS] SCR1_CSR_MTVEC_BASE_RST_VAL = SCR1_CSR_MTVEC_BASE_WR_RST_VAL;
+
+parameter bit SCR1_CSR_MTVEC_MODE_DIRECT = 1'b0;
+`ifdef SCR1_MTVEC_MODE_EN
+parameter bit SCR1_CSR_MTVEC_MODE_VECTORED = 1'b1;
+`endif // SCR1_MTVEC_MODE_EN
+
+// MIE, MIP
+parameter int unsigned SCR1_CSR_MIE_MSIE_OFFSET = 3;
+parameter int unsigned SCR1_CSR_MIE_MTIE_OFFSET = 7;
+parameter int unsigned SCR1_CSR_MIE_MEIE_OFFSET = 11;
+
+`ifdef SCR1_MCOUNTEN_EN
+// MCOUNTEN
+parameter int unsigned SCR1_CSR_MCOUNTEN_CY_OFFSET = 0;
+parameter int unsigned SCR1_CSR_MCOUNTEN_IR_OFFSET = 2;
+`endif // SCR1_MCOUNTEN_EN
+
+// MCAUSE
+typedef logic [`SCR1_XLEN-2:0] type_scr1_csr_mcause_ec_v;
+
+// MCYCLE, MINSTRET
+`ifdef SCR1_CSR_REDUCED_CNT
+parameter int unsigned SCR1_CSR_COUNTERS_WIDTH = 32;
+`else // ~SCR1_CSR_REDUCED_CNT
+parameter int unsigned SCR1_CSR_COUNTERS_WIDTH = 64;
+`endif // ~SCR1_CSR_REDUCED_CNT
+
+// HPM
+parameter bit [6:0] SCR1_CSR_ADDR_HPMCOUNTER_MASK = 7'b1100000;
+parameter bit [6:0] SCR1_CSR_ADDR_HPMCOUNTERH_MASK = 7'b1100100;
+parameter bit [6:0] SCR1_CSR_ADDR_MHPMCOUNTER_MASK = 7'b1011000;
+parameter bit [6:0] SCR1_CSR_ADDR_MHPMCOUNTERH_MASK = 7'b1011100;
+parameter bit [6:0] SCR1_CSR_ADDR_MHPMEVENT_MASK = 7'b0011001;
+
+//-------------------------------------------------------------------------------
+// Types declaration
+//-------------------------------------------------------------------------------
+typedef enum logic {
+ SCR1_CSR_RESP_OK,
+ SCR1_CSR_RESP_ER
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_CSR_RESP_ERROR = 'x
+`endif // SCR1_XPROP_EN
+} type_scr1_csr_resp_e;
+
+`endif // SCR1_CSR_SVH
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_dm.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_dm.svh
new file mode 100644
index 0000000..0d4b0d9
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_dm.svh
@@ -0,0 +1,141 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_dm.svh>
+/// @brief Debug Module header file
+///
+
+`ifndef SCR1_INCLUDE_DM_DEFS
+`define SCR1_INCLUDE_DM_DEFS
+
+`include "scr1_arch_description.svh"
+`include "scr1_hdu.svh"
+`include "scr1_csr.svh"
+
+parameter SCR1_DBG_DMI_ADDR_WIDTH = 6'd7;
+parameter SCR1_DBG_DMI_DATA_WIDTH = 6'd32;
+parameter SCR1_DBG_DMI_OP_WIDTH = 2'd2;
+
+parameter SCR1_DBG_DMI_CH_ID_WIDTH = 2'd2;
+parameter SCR1_DBG_DMI_DR_DTMCS_WIDTH = 6'd32;
+parameter SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH = SCR1_DBG_DMI_OP_WIDTH +
+ SCR1_DBG_DMI_DATA_WIDTH +
+ SCR1_DBG_DMI_ADDR_WIDTH;
+
+// Debug Module addresses
+parameter SCR1_DBG_DATA0 = 7'h4;
+parameter SCR1_DBG_DATA1 = 7'h5;
+parameter SCR1_DBG_DMCONTROL = 7'h10;
+parameter SCR1_DBG_DMSTATUS = 7'h11;
+parameter SCR1_DBG_HARTINFO = 7'h12;
+parameter SCR1_DBG_ABSTRACTCS = 7'h16;
+parameter SCR1_DBG_COMMAND = 7'h17;
+parameter SCR1_DBG_ABSTRACTAUTO = 7'h18;
+parameter SCR1_DBG_PROGBUF0 = 7'h20;
+parameter SCR1_DBG_PROGBUF1 = 7'h21;
+parameter SCR1_DBG_PROGBUF2 = 7'h22;
+parameter SCR1_DBG_PROGBUF3 = 7'h23;
+parameter SCR1_DBG_PROGBUF4 = 7'h24;
+parameter SCR1_DBG_PROGBUF5 = 7'h25;
+parameter SCR1_DBG_HALTSUM0 = 7'h40;
+
+// DMCONTROL
+parameter SCR1_DBG_DMCONTROL_HALTREQ = 5'd31;
+parameter SCR1_DBG_DMCONTROL_RESUMEREQ = 5'd30;
+parameter SCR1_DBG_DMCONTROL_HARTRESET = 5'd29;
+parameter SCR1_DBG_DMCONTROL_ACKHAVERESET = 5'd28;
+parameter SCR1_DBG_DMCONTROL_RESERVEDB = 5'd27;
+parameter SCR1_DBG_DMCONTROL_HASEL = 5'd26;
+parameter SCR1_DBG_DMCONTROL_HARTSELLO_HI = 5'd25;
+parameter SCR1_DBG_DMCONTROL_HARTSELLO_LO = 5'd16;
+parameter SCR1_DBG_DMCONTROL_HARTSELHI_HI = 5'd15;
+parameter SCR1_DBG_DMCONTROL_HARTSELHI_LO = 5'd6;
+parameter SCR1_DBG_DMCONTROL_RESERVEDA_HI = 5'd5;
+parameter SCR1_DBG_DMCONTROL_RESERVEDA_LO = 5'd2;
+parameter SCR1_DBG_DMCONTROL_NDMRESET = 5'd1;
+parameter SCR1_DBG_DMCONTROL_DMACTIVE = 5'd0;
+
+// DMSTATUS
+parameter SCR1_DBG_DMSTATUS_RESERVEDC_HI = 5'd31;
+parameter SCR1_DBG_DMSTATUS_RESERVEDC_LO = 5'd23;
+parameter SCR1_DBG_DMSTATUS_IMPEBREAK = 5'd22;
+parameter SCR1_DBG_DMSTATUS_RESERVEDB_HI = 5'd21;
+parameter SCR1_DBG_DMSTATUS_RESERVEDB_LO = 5'd20;
+parameter SCR1_DBG_DMSTATUS_ALLHAVERESET = 5'd19;
+parameter SCR1_DBG_DMSTATUS_ANYHAVERESET = 5'd18;
+parameter SCR1_DBG_DMSTATUS_ALLRESUMEACK = 5'd17;
+parameter SCR1_DBG_DMSTATUS_ANYRESUMEACK = 5'd16;
+parameter SCR1_DBG_DMSTATUS_ALLNONEXISTENT = 5'd15;
+parameter SCR1_DBG_DMSTATUS_ANYNONEXISTENT = 5'd14;
+parameter SCR1_DBG_DMSTATUS_ALLUNAVAIL = 5'd13;
+parameter SCR1_DBG_DMSTATUS_ANYUNAVAIL = 5'd12;
+parameter SCR1_DBG_DMSTATUS_ALLRUNNING = 5'd11;
+parameter SCR1_DBG_DMSTATUS_ANYRUNNING = 5'd10;
+parameter SCR1_DBG_DMSTATUS_ALLHALTED = 5'd9;
+parameter SCR1_DBG_DMSTATUS_ANYHALTED = 5'd8;
+parameter SCR1_DBG_DMSTATUS_AUTHENTICATED = 5'd7;
+parameter SCR1_DBG_DMSTATUS_AUTHBUSY = 5'd6;
+parameter SCR1_DBG_DMSTATUS_RESERVEDA = 5'd5;
+parameter SCR1_DBG_DMSTATUS_DEVTREEVALID = 5'd4;
+parameter SCR1_DBG_DMSTATUS_VERSION_HI = 5'd3;
+parameter SCR1_DBG_DMSTATUS_VERSION_LO = 5'd0;
+
+// COMMANDS
+parameter SCR1_DBG_COMMAND_TYPE_HI = 5'd31;
+parameter SCR1_DBG_COMMAND_TYPE_LO = 5'd24;
+parameter SCR1_DBG_COMMAND_TYPE_WDTH = SCR1_DBG_COMMAND_TYPE_HI
+ - SCR1_DBG_COMMAND_TYPE_LO;
+
+parameter SCR1_DBG_COMMAND_ACCESSREG_RESERVEDB = 5'd23;
+parameter SCR1_DBG_COMMAND_ACCESSREG_SIZE_HI = 5'd22;
+parameter SCR1_DBG_COMMAND_ACCESSREG_SIZE_LO = 5'd20;
+parameter SCR1_DBG_COMMAND_ACCESSREG_SIZE_WDTH = SCR1_DBG_COMMAND_ACCESSREG_SIZE_HI
+ - SCR1_DBG_COMMAND_ACCESSREG_SIZE_LO;
+parameter SCR1_DBG_COMMAND_ACCESSREG_RESERVEDA = 5'd19;
+parameter SCR1_DBG_COMMAND_ACCESSREG_POSTEXEC = 5'd18;
+parameter SCR1_DBG_COMMAND_ACCESSREG_TRANSFER = 5'd17;
+parameter SCR1_DBG_COMMAND_ACCESSREG_WRITE = 5'd16;
+parameter SCR1_DBG_COMMAND_ACCESSREG_REGNO_HI = 5'd15;
+parameter SCR1_DBG_COMMAND_ACCESSREG_REGNO_LO = 5'd0;
+
+parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMVIRTUAL = 5'd23;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_HI = 5'd22;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_LO = 5'd20;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMPOSTINC = 5'd19;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_HI = 5'd18;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_LO = 5'd17;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_WRITE = 5'd16;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_HI = 5'd13;
+parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_LO = 5'd0;
+
+// ABSTRACTCS
+parameter SCR1_DBG_ABSTRACTCS_RESERVEDD_HI = 5'd31;
+parameter SCR1_DBG_ABSTRACTCS_RESERVEDD_LO = 5'd29;
+parameter SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_HI = 5'd28;
+parameter SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_LO = 5'd24;
+parameter SCR1_DBG_ABSTRACTCS_RESERVEDC_HI = 5'd23;
+parameter SCR1_DBG_ABSTRACTCS_RESERVEDC_LO = 5'd13;
+parameter SCR1_DBG_ABSTRACTCS_BUSY = 5'd12;
+parameter SCR1_DBG_ABSTRACTCS_RESERVEDB = 5'd11;
+parameter SCR1_DBG_ABSTRACTCS_CMDERR_HI = 5'd10;
+parameter SCR1_DBG_ABSTRACTCS_CMDERR_LO = 5'd8;
+parameter SCR1_DBG_ABSTRACTCS_CMDERR_WDTH = SCR1_DBG_ABSTRACTCS_CMDERR_HI
+ - SCR1_DBG_ABSTRACTCS_CMDERR_LO;
+parameter SCR1_DBG_ABSTRACTCS_RESERVEDA_HI = 5'd7;
+parameter SCR1_DBG_ABSTRACTCS_RESERVEDA_LO = 5'd4;
+parameter SCR1_DBG_ABSTRACTCS_DATACOUNT_HI = 5'd3;
+parameter SCR1_DBG_ABSTRACTCS_DATACOUNT_LO = 5'd0;
+
+// HARTINFO
+parameter SCR1_DBG_HARTINFO_RESERVEDB_HI = 5'd31;
+parameter SCR1_DBG_HARTINFO_RESERVEDB_LO = 5'd24;
+parameter SCR1_DBG_HARTINFO_NSCRATCH_HI = 5'd23;
+parameter SCR1_DBG_HARTINFO_NSCRATCH_LO = 5'd20;
+parameter SCR1_DBG_HARTINFO_RESERVEDA_HI = 5'd19;
+parameter SCR1_DBG_HARTINFO_RESERVEDA_LO = 5'd17;
+parameter SCR1_DBG_HARTINFO_DATAACCESS = 5'd16;
+parameter SCR1_DBG_HARTINFO_DATASIZE_HI = 5'd15;
+parameter SCR1_DBG_HARTINFO_DATASIZE_LO = 5'd12;
+parameter SCR1_DBG_HARTINFO_DATAADDR_HI = 5'd11;
+parameter SCR1_DBG_HARTINFO_DATAADDR_LO = 5'd0;
+
+
+`endif // SCR1_INCLUDE_DM_DEFS
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_hdu.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_hdu.svh
new file mode 100644
index 0000000..c3a503f
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_hdu.svh
@@ -0,0 +1,163 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_pipe_hdu.svh>
+/// @brief HART Debug Unit definitions file
+///
+
+`ifndef SCR1_INCLUDE_HDU_DEFS
+`define SCR1_INCLUDE_HDU_DEFS
+
+`include "scr1_arch_description.svh"
+`include "scr1_csr.svh"
+
+`ifdef SCR1_MMU_EN
+ `define SCR1_HDU_FEATURE_MPRVEN
+`endif // SCR1_MMU_EN
+
+//==============================================================================
+// Parameters
+//==============================================================================
+//localparam int unsigned SCR1_HDU_DEBUGCSR_BASE_ADDR = 12'h7B0;
+localparam int unsigned SCR1_HDU_DEBUGCSR_ADDR_SPAN = SCR1_CSR_ADDR_HDU_MSPAN;
+localparam int unsigned SCR1_HDU_DEBUGCSR_ADDR_WIDTH = $clog2(SCR1_HDU_DEBUGCSR_ADDR_SPAN);
+localparam bit [3:0] SCR1_HDU_DEBUGCSR_DCSR_XDEBUGVER = 4'h4;
+localparam int unsigned SCR1_HDU_PBUF_ADDR_SPAN = 8;
+localparam int unsigned SCR1_HDU_PBUF_ADDR_WIDTH = $clog2(SCR1_HDU_PBUF_ADDR_SPAN);
+localparam int unsigned SCR1_HDU_DATA_REG_WIDTH = 32;
+localparam int unsigned SCR1_HDU_CORE_INSTR_WIDTH = 32;
+
+
+//==============================================================================
+// Types
+//==============================================================================
+
+// HART Debug States:
+typedef enum logic [1:0] {
+ SCR1_HDU_DBGSTATE_RESET = 2'b00,
+ SCR1_HDU_DBGSTATE_RUN = 2'b01,
+ SCR1_HDU_DBGSTATE_DHALTED = 2'b10,
+ SCR1_HDU_DBGSTATE_DRUN = 2'b11
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_HDU_DBGSTATE_XXX = 'X
+`endif // SCR1_XPROP_EN
+} type_scr1_hdu_dbgstates_e;
+
+typedef enum logic [1:0] {
+ SCR1_HDU_PBUFSTATE_IDLE = 2'b00,
+ SCR1_HDU_PBUFSTATE_FETCH = 2'b01,
+ SCR1_HDU_PBUFSTATE_EXCINJECT = 2'b10,
+ SCR1_HDU_PBUFSTATE_WAIT4END = 2'b11
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_HDU_PBUFSTATE_XXX = 'X
+`endif // SCR1_XPROP_EN
+} type_scr1_hdu_pbufstates_e;
+
+typedef enum logic {
+ SCR1_HDU_HARTCMD_RESUME = 1'b0,
+ SCR1_HDU_HARTCMD_HALT = 1'b1
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_HDU_HARTCMD_XXX = 1'bX
+`endif // SCR1_XPROP_EN
+} type_scr1_hdu_hart_command_e;
+
+typedef enum logic {
+ SCR1_HDU_FETCH_SRC_NORMAL = 1'b0,
+ SCR1_HDU_FETCH_SRC_PBUF = 1'b1
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_HDU_FETCH_SRC_XXX = 1'bX
+`endif // SCR1_XPROP_EN
+} type_scr1_hdu_fetch_src_e;
+
+typedef struct packed {
+ //logic reset_n;
+ logic except;
+ logic ebreak;
+ type_scr1_hdu_dbgstates_e dbg_state;
+} type_scr1_hdu_hartstatus_s;
+
+// Debug Mode Redirection control:
+typedef struct packed {
+ logic sstep; // Single Step
+ logic ebreak; // Redirection after EBREAK execution
+} type_scr1_hdu_redirect_s;
+
+typedef struct packed {
+ logic irq_dsbl;
+ type_scr1_hdu_fetch_src_e fetch_src;
+ logic pc_advmt_dsbl;
+ logic hwbrkpt_dsbl;
+ type_scr1_hdu_redirect_s redirect;
+} type_scr1_hdu_runctrl_s;
+
+// HART Halt Status:
+typedef enum logic [2:0] {
+ SCR1_HDU_HALTCAUSE_NONE = 3'b000,
+ SCR1_HDU_HALTCAUSE_EBREAK = 3'b001,
+ SCR1_HDU_HALTCAUSE_TMREQ = 3'b010,
+ SCR1_HDU_HALTCAUSE_DMREQ = 3'b011,
+ SCR1_HDU_HALTCAUSE_SSTEP = 3'b100,
+ SCR1_HDU_HALTCAUSE_RSTEXIT = 3'b101
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_HDU_HALTCAUSE_XXX = 'X
+`endif // SCR1_XPROP_EN
+} type_scr1_hdu_haltcause_e;
+
+typedef struct packed {
+ logic except;
+ type_scr1_hdu_haltcause_e cause;
+} type_scr1_hdu_haltstatus_s;
+
+
+// Debug CSR map
+localparam SCR1_HDU_DBGCSR_OFFS_DCSR = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd0 );
+localparam SCR1_HDU_DBGCSR_OFFS_DPC = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd1 );
+localparam SCR1_HDU_DBGCSR_OFFS_DSCRATCH0 = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd2 );
+localparam SCR1_HDU_DBGCSR_OFFS_DSCRATCH1 = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd3 );
+
+localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DCSR = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DCSR;
+localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DPC = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DPC;
+localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DSCRATCH0 = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DSCRATCH0;
+localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DSCRATCH1 = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DSCRATCH1;
+
+// Debug CSRs :: DCSR
+typedef enum int {
+ SCR1_HDU_DCSR_PRV_BIT_R = 0,
+ SCR1_HDU_DCSR_PRV_BIT_L = 1,
+ SCR1_HDU_DCSR_STEP_BIT = 2,
+ SCR1_HDU_DCSR_RSRV0_BIT_R = 3,
+ SCR1_HDU_DCSR_RSRV0_BIT_L = 5,
+ SCR1_HDU_DCSR_CAUSE_BIT_R = 6,
+ SCR1_HDU_DCSR_CAUSE_BIT_L = 8,
+ SCR1_HDU_DCSR_RSRV1_BIT_R = 9,
+ SCR1_HDU_DCSR_RSRV1_BIT_L = 10,
+ SCR1_HDU_DCSR_STEPIE_BIT = 11,
+ SCR1_HDU_DCSR_RSRV2_BIT_R = 12,
+ SCR1_HDU_DCSR_RSRV2_BIT_L = 14,
+ SCR1_HDU_DCSR_EBREAKM_BIT = 15,
+ SCR1_HDU_DCSR_RSRV3_BIT_R = 16,
+ SCR1_HDU_DCSR_RSRV3_BIT_L = 27,
+ SCR1_HDU_DCSR_XDEBUGVER_BIT_R = 28,
+ SCR1_HDU_DCSR_XDEBUGVER_BIT_L = 31
+} type_scr1_hdu_dcsr_bits_e;
+
+//localparam int unsigned SCR1_HDU_DEBUGCSR_DCSR_PRV_WIDTH = SCR1_HDU_DCSR_PRV_BIT_L-SCR1_HDU_DCSR_PRV_BIT_R+1;
+
+typedef struct packed {
+ logic [SCR1_HDU_DCSR_XDEBUGVER_BIT_L-SCR1_HDU_DCSR_XDEBUGVER_BIT_R:0] xdebugver;
+ logic [SCR1_HDU_DCSR_RSRV3_BIT_L-SCR1_HDU_DCSR_RSRV3_BIT_R:0] rsrv3;
+ logic ebreakm;
+ logic [SCR1_HDU_DCSR_RSRV2_BIT_L-SCR1_HDU_DCSR_RSRV2_BIT_R:0] rsrv2;
+ logic stepie;
+ logic [SCR1_HDU_DCSR_RSRV1_BIT_L-SCR1_HDU_DCSR_RSRV1_BIT_R:0] rsrv1;
+ logic [SCR1_HDU_DCSR_CAUSE_BIT_L-SCR1_HDU_DCSR_CAUSE_BIT_R:0] cause;
+ logic [SCR1_HDU_DCSR_RSRV0_BIT_L-SCR1_HDU_DCSR_RSRV0_BIT_R:0] rsrv0;
+ logic step;
+ logic [SCR1_HDU_DCSR_PRV_BIT_L-SCR1_HDU_DCSR_PRV_BIT_R:0] prv;
+} type_scr1_hdu_dcsr_s;
+
+
+`endif // SCR1_INCLUDE_HDU_DEFS
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_ipic.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_ipic.svh
new file mode 100644
index 0000000..4a42dc3
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_ipic.svh
@@ -0,0 +1,58 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_ipic.svh>
+/// @brief IPIC header file
+///
+
+`ifndef SCR1_IPIC_SVH
+`define SCR1_IPIC_SVH
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_IPIC_EN
+//-------------------------------------------------------------------------------
+// Parameters declaration
+//-------------------------------------------------------------------------------
+parameter SCR1_IRQ_VECT_NUM = 16; // must be power of 2 in the current implementation
+parameter SCR1_IRQ_VECT_WIDTH = $clog2(SCR1_IRQ_VECT_NUM+1);
+parameter SCR1_IRQ_LINES_NUM = SCR1_IRQ_VECT_NUM;
+parameter SCR1_IRQ_LINES_WIDTH = $clog2(SCR1_IRQ_LINES_NUM);
+parameter logic [SCR1_IRQ_VECT_WIDTH-1:0] SCR1_IRQ_VOID_VECT_NUM = SCR1_IRQ_VECT_WIDTH'(SCR1_IRQ_VECT_NUM);
+parameter SCR1_IRQ_IDX_WIDTH = $clog2(SCR1_IRQ_VECT_NUM);
+
+// Address decoding parameters
+parameter logic [2:0] SCR1_IPIC_CISV = 3'h0; // RO
+parameter logic [2:0] SCR1_IPIC_CICSR = 3'h1; // {IP, IE}
+parameter logic [2:0] SCR1_IPIC_IPR = 3'h2; // RW1C
+parameter logic [2:0] SCR1_IPIC_ISVR = 3'h3; // RO
+parameter logic [2:0] SCR1_IPIC_EOI = 3'h4; // RZW
+parameter logic [2:0] SCR1_IPIC_SOI = 3'h5; // RZW
+parameter logic [2:0] SCR1_IPIC_IDX = 3'h6; // RW
+parameter logic [2:0] SCR1_IPIC_ICSR = 3'h7; // RW
+
+parameter SCR1_IPIC_ICSR_IP = 0;
+parameter SCR1_IPIC_ICSR_IE = 1;
+parameter SCR1_IPIC_ICSR_IM = 2;
+parameter SCR1_IPIC_ICSR_INV = 3;
+parameter SCR1_IPIC_ICSR_IS = 4;
+parameter SCR1_IPIC_ICSR_PRV_LSB = 8;
+parameter SCR1_IPIC_ICSR_PRV_MSB = 9;
+parameter SCR1_IPIC_ICSR_LN_LSB = 12;
+parameter SCR1_IPIC_ICSR_LN_MSB = SCR1_IPIC_ICSR_LN_LSB
+ + SCR1_IRQ_LINES_WIDTH;
+
+parameter logic [1:0] SCR1_IPIC_PRV_M = 2'b11;
+
+//-------------------------------------------------------------------------------
+// Types declaration
+//-------------------------------------------------------------------------------
+typedef enum logic {
+ SCR1_CSR2IPIC_RD,
+ SCR1_CSR2IPIC_WR
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_CSR2IPIC_ERROR = 'x
+`endif // SCR1_XPROP_EN
+} type_scr1_csr2ipic_wr_e;
+
+`endif // SCR1_IPIC_EN
+`endif // SCR1_IPIC_SVH
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_memif.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_memif.svh
new file mode 100644
index 0000000..7235d1d
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_memif.svh
@@ -0,0 +1,49 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_memif.svh>
+/// @brief Memory interface definitions file
+///
+
+`ifndef SCR1_MEMIF_SVH
+`define SCR1_MEMIF_SVH
+
+`include "scr1_arch_description.svh"
+
+//-------------------------------------------------------------------------------
+// Memory command enum
+//-------------------------------------------------------------------------------
+typedef enum logic {
+ SCR1_MEM_CMD_RD = 1'b0,
+ SCR1_MEM_CMD_WR = 1'b1
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_MEM_CMD_ERROR = 'x
+`endif // SCR1_XPROP_EN
+} type_scr1_mem_cmd_e;
+
+//-------------------------------------------------------------------------------
+// Memory data width enum
+//-------------------------------------------------------------------------------
+typedef enum logic[1:0] {
+ SCR1_MEM_WIDTH_BYTE = 2'b00,
+ SCR1_MEM_WIDTH_HWORD = 2'b01,
+ SCR1_MEM_WIDTH_WORD = 2'b10
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_MEM_WIDTH_ERROR = 'x
+`endif // SCR1_XPROP_EN
+} type_scr1_mem_width_e;
+
+//-------------------------------------------------------------------------------
+// Memory response enum
+//-------------------------------------------------------------------------------
+typedef enum logic[1:0] {
+ SCR1_MEM_RESP_NOTRDY = 2'b00,
+ SCR1_MEM_RESP_RDY_OK = 2'b01,
+ SCR1_MEM_RESP_RDY_ER = 2'b10
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_MEM_RESP_ERROR = 'x
+`endif // SCR1_XPROP_EN
+} type_scr1_mem_resp_e;
+
+`endif // SCR1_MEMIF_SVH
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_riscv_isa_decoding.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_riscv_isa_decoding.svh
new file mode 100644
index 0000000..e143d89
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_riscv_isa_decoding.svh
@@ -0,0 +1,185 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_riscv_isa_decoding.svh>
+/// @brief RISC-V ISA definitions file
+///
+
+`ifndef SCR1_RISCV_ISA_DECODING_SVH
+`define SCR1_RISCV_ISA_DECODING_SVH
+
+`include "scr1_arch_description.svh"
+`include "scr1_arch_types.svh"
+
+//-------------------------------------------------------------------------------
+// Instruction types
+//-------------------------------------------------------------------------------
+typedef enum logic [1:0] {
+ SCR1_INSTR_RVC0 = 2'b00,
+ SCR1_INSTR_RVC1 = 2'b01,
+ SCR1_INSTR_RVC2 = 2'b10,
+ SCR1_INSTR_RVI = 2'b11
+} type_scr1_instr_type_e;
+
+//-------------------------------------------------------------------------------
+// RV32I opcodes (bits 6:2)
+//-------------------------------------------------------------------------------
+typedef enum logic [6:2] {
+ SCR1_OPCODE_LOAD = 5'b00000,
+ SCR1_OPCODE_MISC_MEM = 5'b00011,
+ SCR1_OPCODE_OP_IMM = 5'b00100,
+ SCR1_OPCODE_AUIPC = 5'b00101,
+ SCR1_OPCODE_STORE = 5'b01000,
+ SCR1_OPCODE_OP = 5'b01100,
+ SCR1_OPCODE_LUI = 5'b01101,
+ SCR1_OPCODE_BRANCH = 5'b11000,
+ SCR1_OPCODE_JALR = 5'b11001,
+ SCR1_OPCODE_JAL = 5'b11011,
+ SCR1_OPCODE_SYSTEM = 5'b11100
+} type_scr1_rvi_opcode_e;
+
+
+//-------------------------------------------------------------------------------
+// IALU main operands
+//-------------------------------------------------------------------------------
+localparam SCR1_IALU_OP_ALL_NUM_E = 2;
+localparam SCR1_IALU_OP_WIDTH_E = $clog2(SCR1_IALU_OP_ALL_NUM_E);
+typedef enum logic [SCR1_IALU_OP_WIDTH_E-1:0] {
+ SCR1_IALU_OP_REG_IMM, // op1 = rs1; op2 = imm
+ SCR1_IALU_OP_REG_REG // op1 = rs1; op2 = rs2
+} type_scr1_ialu_op_sel_e;
+
+//-------------------------------------------------------------------------------
+// IALU main commands
+//-------------------------------------------------------------------------------
+`ifdef SCR1_RVM_EXT
+localparam SCR1_IALU_CMD_ALL_NUM_E = 23;
+`else // ~SCR1_RVM_EXT
+localparam SCR1_IALU_CMD_ALL_NUM_E = 15;
+`endif // ~SCR1_RVM_EXT
+localparam SCR1_IALU_CMD_WIDTH_E = $clog2(SCR1_IALU_CMD_ALL_NUM_E);
+typedef enum logic [SCR1_IALU_CMD_WIDTH_E-1:0] {
+ SCR1_IALU_CMD_NONE = '0, // IALU disable
+ SCR1_IALU_CMD_AND, // op1 & op2
+ SCR1_IALU_CMD_OR, // op1 | op2
+ SCR1_IALU_CMD_XOR, // op1 ^ op2
+ SCR1_IALU_CMD_ADD, // op1 + op2
+ SCR1_IALU_CMD_SUB, // op1 - op2
+ SCR1_IALU_CMD_SUB_LT, // op1 < op2
+ SCR1_IALU_CMD_SUB_LTU, // op1 u< op2
+ SCR1_IALU_CMD_SUB_EQ, // op1 = op2
+ SCR1_IALU_CMD_SUB_NE, // op1 != op2
+ SCR1_IALU_CMD_SUB_GE, // op1 >= op2
+ SCR1_IALU_CMD_SUB_GEU, // op1 u>= op2
+ SCR1_IALU_CMD_SLL, // op1 << op2
+ SCR1_IALU_CMD_SRL, // op1 >> op2
+ SCR1_IALU_CMD_SRA // op1 >>> op2
+`ifdef SCR1_RVM_EXT
+ ,
+ SCR1_IALU_CMD_MUL, // low(unsig(op1) * unsig(op2))
+ SCR1_IALU_CMD_MULHU, // high(unsig(op1) * unsig(op2))
+ SCR1_IALU_CMD_MULHSU, // high(op1 * unsig(op2))
+ SCR1_IALU_CMD_MULH, // high(op1 * op2)
+ SCR1_IALU_CMD_DIV, // op1 / op2
+ SCR1_IALU_CMD_DIVU, // op1 u/ op2
+ SCR1_IALU_CMD_REM, // op1 % op2
+ SCR1_IALU_CMD_REMU // op1 u% op2
+`endif // SCR1_RVM_EXT
+} type_scr1_ialu_cmd_sel_e;
+
+//-------------------------------------------------------------------------------
+// IALU SUM2 operands (result is JUMP/BRANCH target, LOAD/STORE address)
+//-------------------------------------------------------------------------------
+localparam SCR1_SUM2_OP_ALL_NUM_E = 2;
+localparam SCR1_SUM2_OP_WIDTH_E = $clog2(SCR1_SUM2_OP_ALL_NUM_E);
+typedef enum logic [SCR1_SUM2_OP_WIDTH_E-1:0] {
+ SCR1_SUM2_OP_PC_IMM, // op1 = curr_pc; op2 = imm (AUIPC, target new_pc for JAL and branches)
+ SCR1_SUM2_OP_REG_IMM // op1 = rs1; op2 = imm (target new_pc for JALR, LOAD/STORE address)
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_SUM2_OP_ERROR = 'x
+`endif // SCR1_XPROP_EN
+} type_scr1_ialu_sum2_op_sel_e;
+
+//-------------------------------------------------------------------------------
+// LSU commands
+//-------------------------------------------------------------------------------
+localparam SCR1_LSU_CMD_ALL_NUM_E = 9;
+localparam SCR1_LSU_CMD_WIDTH_E = $clog2(SCR1_LSU_CMD_ALL_NUM_E);
+typedef enum logic [SCR1_LSU_CMD_WIDTH_E-1:0] {
+ SCR1_LSU_CMD_NONE = '0,
+ SCR1_LSU_CMD_LB,
+ SCR1_LSU_CMD_LH,
+ SCR1_LSU_CMD_LW,
+ SCR1_LSU_CMD_LBU,
+ SCR1_LSU_CMD_LHU,
+ SCR1_LSU_CMD_SB,
+ SCR1_LSU_CMD_SH,
+ SCR1_LSU_CMD_SW
+} type_scr1_lsu_cmd_sel_e;
+
+//-------------------------------------------------------------------------------
+// CSR operands
+//-------------------------------------------------------------------------------
+localparam SCR1_CSR_OP_ALL_NUM_E = 2;
+localparam SCR1_CSR_OP_WIDTH_E = $clog2(SCR1_CSR_OP_ALL_NUM_E);
+typedef enum logic [SCR1_CSR_OP_WIDTH_E-1:0] {
+ SCR1_CSR_OP_IMM,
+ SCR1_CSR_OP_REG
+} type_scr1_csr_op_sel_e;
+
+//-------------------------------------------------------------------------------
+// CSR commands
+//-------------------------------------------------------------------------------
+localparam SCR1_CSR_CMD_ALL_NUM_E = 4;
+localparam SCR1_CSR_CMD_WIDTH_E = $clog2(SCR1_CSR_CMD_ALL_NUM_E);
+typedef enum logic [SCR1_CSR_CMD_WIDTH_E-1:0] {
+ SCR1_CSR_CMD_NONE = '0,
+ SCR1_CSR_CMD_WRITE,
+ SCR1_CSR_CMD_SET,
+ SCR1_CSR_CMD_CLEAR
+} type_scr1_csr_cmd_sel_e;
+
+//-------------------------------------------------------------------------------
+// MPRF rd writeback source
+//-------------------------------------------------------------------------------
+localparam SCR1_RD_WB_ALL_NUM_E = 7;
+localparam SCR1_RD_WB_WIDTH_E = $clog2(SCR1_RD_WB_ALL_NUM_E);
+typedef enum logic [SCR1_RD_WB_WIDTH_E-1:0] {
+ SCR1_RD_WB_NONE = '0,
+ SCR1_RD_WB_IALU, // IALU main result
+ SCR1_RD_WB_SUM2, // IALU SUM2 result (AUIPC)
+ SCR1_RD_WB_IMM, // LUI
+ SCR1_RD_WB_INC_PC, // JAL(R)
+ SCR1_RD_WB_LSU, // Load from DMEM
+ SCR1_RD_WB_CSR // Read CSR
+} type_scr1_rd_wb_sel_e;
+
+//-------------------------------------------------------------------------------
+// IDU to EXU full command structure
+//-------------------------------------------------------------------------------
+localparam SCR1_GPR_FIELD_WIDTH = 5;
+
+typedef struct packed {
+ logic instr_rvc; // used with a different meaning for IFU access fault exception
+ type_scr1_ialu_op_sel_e ialu_op;
+ type_scr1_ialu_cmd_sel_e ialu_cmd;
+ type_scr1_ialu_sum2_op_sel_e sum2_op;
+ type_scr1_lsu_cmd_sel_e lsu_cmd;
+ type_scr1_csr_op_sel_e csr_op;
+ type_scr1_csr_cmd_sel_e csr_cmd;
+ type_scr1_rd_wb_sel_e rd_wb_sel;
+ logic jump_req;
+ logic branch_req;
+ logic mret_req;
+ logic fencei_req;
+ logic wfi_req;
+ logic [SCR1_GPR_FIELD_WIDTH-1:0] rs1_addr; // also used as zimm for CSRRxI instructions
+ logic [SCR1_GPR_FIELD_WIDTH-1:0] rs2_addr;
+ logic [SCR1_GPR_FIELD_WIDTH-1:0] rd_addr;
+ logic [`SCR1_XLEN-1:0] imm; // used as {funct3, CSR address} for CSR instructions
+ // used as instruction field for illegal instruction exception
+ logic exc_req;
+ type_scr1_exc_code_e exc_code;
+} type_scr1_exu_cmd_s;
+
+`endif // SCR1_RISCV_ISA_DECODING_SVH
+
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_scu.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_scu.svh
new file mode 100644
index 0000000..ab19386
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_scu.svh
@@ -0,0 +1,84 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_scu.svh>
+/// @brief SCU header file
+///
+
+`ifndef SCR1_INCLUDE_SCU_DEFS
+`define SCR1_INCLUDE_SCU_DEFS
+
+//`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+
+//==============================================================================
+// Parameters
+//==============================================================================
+localparam int unsigned SCR1_SCU_DR_SYSCTRL_OP_WIDTH = 2;
+localparam int unsigned SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH = 2;
+localparam int unsigned SCR1_SCU_DR_SYSCTRL_DATA_WIDTH = 4;
+
+//==============================================================================
+// Types
+//==============================================================================
+typedef enum logic [SCR1_SCU_DR_SYSCTRL_OP_WIDTH-1:0] {
+ SCR1_SCU_SYSCTRL_OP_WRITE = 2'h0,
+ SCR1_SCU_SYSCTRL_OP_READ = 2'h1,
+ SCR1_SCU_SYSCTRL_OP_SETBITS = 2'h2,
+ SCR1_SCU_SYSCTRL_OP_CLRBITS = 2'h3
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_SCU_SYSCTRL_OP_XXX = 'X
+`endif // SCR1_XPROP_EN
+} type_scr1_scu_sysctrl_op_e;
+
+typedef enum logic [SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH-1:0] {
+ SCR1_SCU_SYSCTRL_ADDR_CONTROL = 2'h0,
+ SCR1_SCU_SYSCTRL_ADDR_MODE = 2'h1,
+ SCR1_SCU_SYSCTRL_ADDR_STATUS = 2'h2,
+ SCR1_SCU_SYSCTRL_ADDR_STICKY = 2'h3
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_SCU_SYSCTRL_ADDR_XXX = 'X
+`endif // SCR1_XPROP_EN
+} type_scr1_scu_sysctrl_addr_e;
+
+typedef struct packed {
+ logic [SCR1_SCU_DR_SYSCTRL_DATA_WIDTH-1:0] data;
+ logic [SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH-1:0] addr;
+ logic [SCR1_SCU_DR_SYSCTRL_OP_WIDTH-1:0] op;
+} type_scr1_scu_sysctrl_dr_s;
+
+typedef enum int unsigned {
+ SCR1_SCU_DR_SYSCTRL_OP_BIT_R = 'h0,
+ SCR1_SCU_DR_SYSCTRL_OP_BIT_L = SCR1_SCU_DR_SYSCTRL_OP_WIDTH-1,
+ SCR1_SCU_DR_SYSCTRL_ADDR_BIT_R = SCR1_SCU_DR_SYSCTRL_OP_WIDTH,
+ SCR1_SCU_DR_SYSCTRL_ADDR_BIT_L = SCR1_SCU_DR_SYSCTRL_OP_WIDTH +
+ SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH - 1,
+ SCR1_SCU_DR_SYSCTRL_DATA_BIT_R = SCR1_SCU_DR_SYSCTRL_OP_WIDTH +
+ SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH,
+ SCR1_SCU_DR_SYSCTRL_DATA_BIT_L = SCR1_SCU_DR_SYSCTRL_OP_WIDTH +
+ SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH +
+ SCR1_SCU_DR_SYSCTRL_DATA_WIDTH - 1
+} type_scr1_scu_sysctrl_dr_bits_e;
+
+typedef struct packed {
+ logic [1:0] rsrv;
+ logic core_reset;
+ logic sys_reset;
+} type_scr1_scu_sysctrl_control_reg_s;
+
+typedef struct packed {
+ logic [1:0] rsrv;
+ logic hdu_rst_bhv;
+ logic dm_rst_bhv;
+} type_scr1_scu_sysctrl_mode_reg_s;
+
+typedef struct packed {
+ logic hdu_reset;
+ logic dm_reset;
+ logic core_reset;
+ logic sys_reset;
+} type_scr1_scu_sysctrl_status_reg_s;
+
+`endif // SCR1_DBG_EN
+`endif // SCR1_INCLUDE_SCU_DEFS
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_search_ms1.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_search_ms1.svh
new file mode 100644
index 0000000..fc516ba
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_search_ms1.svh
@@ -0,0 +1,94 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_search_ms1.svh>
+/// @brief Most significant one search function
+///
+
+`ifndef SCR1_SEARCH_MS1_SVH
+`define SCR1_SEARCH_MS1_SVH
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+typedef struct {
+ logic vd;
+ logic idx;
+} type_scr1_search_one_2_s;
+
+typedef struct {
+ logic vd;
+ logic [4:0] idx;
+} type_scr1_search_one_32_s;
+
+//-------------------------------------------------------------------------------
+// Leading Zeros Count Function
+//-------------------------------------------------------------------------------
+function automatic type_scr1_search_one_2_s scr1_lead_zeros_cnt_2(
+ input logic [1:0] din
+);
+ type_scr1_search_one_2_s tmp;
+begin
+ tmp.vd = |din;
+ tmp.idx = ~din[1];
+ return tmp;
+end
+endfunction : scr1_lead_zeros_cnt_2
+
+function automatic logic [4:0] scr1_lead_zeros_cnt_32(
+ input logic [31:0] din
+);
+begin
+ logic [15:0] stage1_vd;
+ logic [7:0] stage2_vd;
+ logic [3:0] stage3_vd;
+ logic [1:0] stage4_vd;
+
+ logic stage1_idx [15:0];
+ logic [1:0] stage2_idx [7:0];
+ logic [2:0] stage3_idx [3:0];
+ logic [3:0] stage4_idx [1:0];
+ type_scr1_search_one_32_s tmp;
+ logic [4:0] res;
+
+ // Stage 1
+ for (int unsigned i=0; i<16; ++i) begin
+ type_scr1_search_one_2_s tmp;
+ tmp = scr1_lead_zeros_cnt_2(din[(i+1)*2-1-:2]);
+ stage1_vd[i] = tmp.vd;
+ stage1_idx[i] = tmp.idx;
+ end
+
+ // Stage 2
+ for (int unsigned i=0; i<8; ++i) begin
+ type_scr1_search_one_2_s tmp;
+ tmp = scr1_lead_zeros_cnt_2(stage1_vd[(i+1)*2-1-:2]);
+ stage2_vd[i] = tmp.vd;
+ stage2_idx[i] = (tmp.idx) ? {tmp.idx, stage1_idx[2*i]} : {tmp.idx, stage1_idx[2*i+1]};
+ end
+
+ // Stage 3
+ for (int unsigned i=0; i<4; ++i) begin
+ type_scr1_search_one_2_s tmp;
+ tmp = scr1_lead_zeros_cnt_2(stage2_vd[(i+1)*2-1-:2]);
+ stage3_vd[i] = tmp.vd;
+ stage3_idx[i] = (tmp.idx) ? {tmp.idx, stage2_idx[2*i]} : {tmp.idx, stage2_idx[2*i+1]};
+ end
+
+ // Stage 4
+ for (int unsigned i=0; i<2; ++i) begin
+ type_scr1_search_one_2_s tmp;
+ tmp = scr1_lead_zeros_cnt_2(stage3_vd[(i+1)*2-1-:2]);
+ stage4_vd[i] = tmp.vd;
+ stage4_idx[i] = (tmp.idx) ? {tmp.idx, stage3_idx[2*i]} : {tmp.idx, stage3_idx[2*i+1]};
+ end
+
+ // Stage 5
+ tmp.vd = |stage4_vd;
+ tmp.idx = (stage4_vd[1]) ? {1'b0, stage4_idx[1]} : {1'b1, stage4_idx[0]};
+
+ res = tmp.idx;
+
+ return res;
+end
+endfunction : scr1_lead_zeros_cnt_32
+
+`endif // SCR1_SEARCH_MS1_SVH
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_tapc.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_tapc.svh
new file mode 100644
index 0000000..e96ea44
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_tapc.svh
@@ -0,0 +1,66 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_tapc.svh>
+/// @brief TAPC header file
+///
+
+`ifndef SCR1_INCLUDE_TAPC_DEFS
+`define SCR1_INCLUDE_TAPC_DEFS
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_DBG_EN
+
+//==============================================================================
+// Parameters
+//==============================================================================
+localparam int unsigned SCR1_TAP_STATE_WIDTH = 4;
+localparam int unsigned SCR1_TAP_INSTRUCTION_WIDTH = 5;
+localparam int unsigned SCR1_TAP_DR_IDCODE_WIDTH = 32;
+localparam int unsigned SCR1_TAP_DR_BLD_ID_WIDTH = 32;
+localparam int unsigned SCR1_TAP_DR_BYPASS_WIDTH = 1;
+//localparam bit [SCR1_TAP_DR_IDCODE_WIDTH-1:0] SCR1_TAP_IDCODE_RISCV_SC = `SCR1_TAP_IDCODE;
+localparam bit [SCR1_TAP_DR_BLD_ID_WIDTH-1:0] SCR1_TAP_BLD_ID_VALUE = `SCR1_MIMPID;
+
+//==============================================================================
+// Types
+//==============================================================================
+typedef enum logic [SCR1_TAP_STATE_WIDTH-1:0] {
+ SCR1_TAP_STATE_RESET,
+ SCR1_TAP_STATE_IDLE,
+ SCR1_TAP_STATE_DR_SEL_SCAN,
+ SCR1_TAP_STATE_DR_CAPTURE,
+ SCR1_TAP_STATE_DR_SHIFT,
+ SCR1_TAP_STATE_DR_EXIT1,
+ SCR1_TAP_STATE_DR_PAUSE,
+ SCR1_TAP_STATE_DR_EXIT2,
+ SCR1_TAP_STATE_DR_UPDATE,
+ SCR1_TAP_STATE_IR_SEL_SCAN,
+ SCR1_TAP_STATE_IR_CAPTURE,
+ SCR1_TAP_STATE_IR_SHIFT,
+ SCR1_TAP_STATE_IR_EXIT1,
+ SCR1_TAP_STATE_IR_PAUSE,
+ SCR1_TAP_STATE_IR_EXIT2,
+ SCR1_TAP_STATE_IR_UPDATE
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_TAP_STATE_XXX = 'X
+`endif // SCR1_XPROP_EN
+} type_scr1_tap_state_e;
+
+typedef enum logic [SCR1_TAP_INSTRUCTION_WIDTH - 1:0] {
+ SCR1_TAP_INSTR_IDCODE = 5'h01,
+ SCR1_TAP_INSTR_BLD_ID = 5'h04,
+ SCR1_TAP_INSTR_SCU_ACCESS = 5'h09,
+
+ SCR1_TAP_INSTR_DTMCS = 5'h10,
+ SCR1_TAP_INSTR_DMI_ACCESS = 5'h11,
+
+ SCR1_TAP_INSTR_BYPASS = 5'h1F
+`ifdef SCR1_XPROP_EN
+ ,
+ SCR1_TAP_INSTR_XXX = 'X
+`endif // SCR1_XPROP_EN
+} type_scr1_tap_instr_e;
+
+`endif // SCR1_DBG_EN
+`endif // SCR1_INCLUDE_TAPC_DEFS
diff --git a/verilog/rtl/syntacore_scr1/src/includes/scr1_tdu.svh b/verilog/rtl/syntacore_scr1/src/includes/scr1_tdu.svh
new file mode 100644
index 0000000..79382cf
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/includes/scr1_tdu.svh
@@ -0,0 +1,121 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_tdu.svh>
+/// @brief Trigger Debug Module header
+///
+
+`ifndef SCR1_INCLUDE_TDU_DEFS
+`define SCR1_INCLUDE_TDU_DEFS
+
+//`include "scr1_arch_description.svh"
+
+`ifdef SCR1_TDU_EN
+//`include "scr1_csr.svh"
+
+`include "scr1_arch_description.svh"
+//`include "scr1_arch_types.svh"
+`include "scr1_csr.svh"
+
+parameter int unsigned SCR1_TDU_MTRIG_NUM = SCR1_TDU_TRIG_NUM;
+`ifdef SCR1_TDU_ICOUNT_EN
+parameter int unsigned SCR1_TDU_ALLTRIG_NUM = SCR1_TDU_MTRIG_NUM + 1'b1;
+`else
+parameter int unsigned SCR1_TDU_ALLTRIG_NUM = SCR1_TDU_MTRIG_NUM;
+`endif
+
+parameter int unsigned SCR1_TDU_ADDR_W = `SCR1_XLEN;
+parameter int unsigned SCR1_TDU_DATA_W = `SCR1_XLEN;
+
+// Register map
+parameter SCR1_CSR_ADDR_TDU_OFFS_W = 3;
+parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TSELECT = 'h0;
+parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TDATA1 = 'h1;
+parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TDATA2 = 'h2;
+parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TINFO = 'h4;
+
+
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TSELECT = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TSELECT;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TDATA1 = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TDATA1;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TDATA2 = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TDATA2;
+parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TINFO = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TINFO;
+
+// TDATA1
+parameter int unsigned SCR1_TDU_TDATA1_TYPE_HI = `SCR1_XLEN-1;
+parameter int unsigned SCR1_TDU_TDATA1_TYPE_LO = `SCR1_XLEN-4;
+parameter int unsigned SCR1_TDU_TDATA1_DMODE = `SCR1_XLEN-5;
+
+// TDATA1: constant bits values
+parameter bit SCR1_TDU_TDATA1_DMODE_VAL = 1'b0;
+
+// MCONTROL: bits number
+parameter int unsigned SCR1_TDU_MCONTROL_MASKMAX_HI = `SCR1_XLEN-6;
+parameter int unsigned SCR1_TDU_MCONTROL_MASKMAX_LO = `SCR1_XLEN-11;
+parameter int unsigned SCR1_TDU_MCONTROL_RESERVEDB_HI = `SCR1_XLEN-12;
+parameter int unsigned SCR1_TDU_MCONTROL_RESERVEDB_LO = 21;
+parameter int unsigned SCR1_TDU_MCONTROL_HIT = 20;
+parameter int unsigned SCR1_TDU_MCONTROL_SELECT = 19;
+parameter int unsigned SCR1_TDU_MCONTROL_TIMING = 18;
+parameter int unsigned SCR1_TDU_MCONTROL_ACTION_HI = 17;
+parameter int unsigned SCR1_TDU_MCONTROL_ACTION_LO = 12;
+parameter int unsigned SCR1_TDU_MCONTROL_CHAIN = 11;
+parameter int unsigned SCR1_TDU_MCONTROL_MATCH_HI = 10;
+parameter int unsigned SCR1_TDU_MCONTROL_MATCH_LO = 7;
+parameter int unsigned SCR1_TDU_MCONTROL_M = 6;
+parameter int unsigned SCR1_TDU_MCONTROL_RESERVEDA = 5;
+parameter int unsigned SCR1_TDU_MCONTROL_S = 4;
+parameter int unsigned SCR1_TDU_MCONTROL_U = 3;
+parameter int unsigned SCR1_TDU_MCONTROL_EXECUTE = 2;
+parameter int unsigned SCR1_TDU_MCONTROL_STORE = 1;
+parameter int unsigned SCR1_TDU_MCONTROL_LOAD = 0;
+
+// MCONTROL: constant bits values
+parameter bit [SCR1_TDU_TDATA1_TYPE_HI-SCR1_TDU_TDATA1_TYPE_LO:0]
+ SCR1_TDU_MCONTROL_TYPE_VAL = 2'd2;
+
+parameter bit SCR1_TDU_MCONTROL_SELECT_VAL = 1'b0;
+parameter bit SCR1_TDU_MCONTROL_TIMING_VAL = 1'b0;
+
+parameter bit [SCR1_TDU_MCONTROL_MASKMAX_HI-SCR1_TDU_MCONTROL_MASKMAX_LO:0]
+ SCR1_TDU_MCONTROL_MASKMAX_VAL = 1'b0;
+
+parameter bit SCR1_TDU_MCONTROL_RESERVEDA_VAL = 1'b0;
+
+// ICOUNT: bits number
+parameter int unsigned SCR1_TDU_ICOUNT_DMODE = `SCR1_XLEN-5;
+parameter int unsigned SCR1_TDU_ICOUNT_RESERVEDB_HI = `SCR1_XLEN-6;
+parameter int unsigned SCR1_TDU_ICOUNT_RESERVEDB_LO = 25;
+parameter int unsigned SCR1_TDU_ICOUNT_HIT = 24;
+parameter int unsigned SCR1_TDU_ICOUNT_COUNT_HI = 23;
+parameter int unsigned SCR1_TDU_ICOUNT_COUNT_LO = 10;
+parameter int unsigned SCR1_TDU_ICOUNT_M = 9;
+parameter int unsigned SCR1_TDU_ICOUNT_RESERVEDA = 8;
+parameter int unsigned SCR1_TDU_ICOUNT_S = 7;
+parameter int unsigned SCR1_TDU_ICOUNT_U = 6;
+parameter int unsigned SCR1_TDU_ICOUNT_ACTION_HI = 5;
+parameter int unsigned SCR1_TDU_ICOUNT_ACTION_LO = 0;
+
+// ICOUNT: constant bits values
+parameter bit [SCR1_TDU_TDATA1_TYPE_HI-SCR1_TDU_TDATA1_TYPE_LO:0]
+ SCR1_TDU_ICOUNT_TYPE_VAL = 2'd3;
+
+parameter bit [SCR1_TDU_ICOUNT_RESERVEDB_HI-SCR1_TDU_ICOUNT_RESERVEDB_LO:0]
+ SCR1_TDU_ICOUNT_RESERVEDB_VAL = 1'b0;
+
+parameter bit SCR1_TDU_ICOUNT_RESERVEDA_VAL = 1'b0;
+
+// CPU pipeline monitors
+typedef struct packed {
+ logic vd;
+ logic req;
+ logic [`SCR1_XLEN-1:0] addr;
+} type_scr1_brkm_instr_mon_s;
+
+typedef struct packed {
+ logic vd;
+ logic load;
+ logic store;
+ logic [`SCR1_XLEN-1:0] addr;
+} type_scr1_brkm_lsu_mon_s;
+
+`endif // SCR1_TDU_EN
+
+`endif // SCR1_INCLUDE_TDU_DEFS
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_dmem_ahb.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_dmem_ahb.sv
new file mode 100644
index 0000000..1a413d5
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_dmem_ahb.sv
@@ -0,0 +1,466 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_dmem_ahb.sv>
+/// @brief Data memory AHB bridge
+///
+
+`include "scr1_ahb.svh"
+`include "scr1_memif.svh"
+
+module scr1_dmem_ahb (
+ // Control Signals
+ input logic rst_n,
+ input logic clk,
+
+ // Core Interface
+ output logic dmem_req_ack,
+ input logic dmem_req,
+ input type_scr1_mem_cmd_e dmem_cmd,
+ input type_scr1_mem_width_e dmem_width,
+ input logic [SCR1_AHB_WIDTH-1:0] dmem_addr,
+ input logic [SCR1_AHB_WIDTH-1:0] dmem_wdata,
+ output logic [SCR1_AHB_WIDTH-1:0] dmem_rdata,
+ output type_scr1_mem_resp_e dmem_resp,
+
+ // AHB Interface
+ output logic [3:0] hprot,
+ output logic [2:0] hburst,
+ output logic [2:0] hsize,
+ output logic [1:0] htrans,
+ output logic hmastlock,
+ output logic [SCR1_AHB_WIDTH-1:0] haddr,
+ output logic hwrite,
+ output logic [SCR1_AHB_WIDTH-1:0] hwdata,
+ input logic hready,
+ input logic [SCR1_AHB_WIDTH-1:0] hrdata,
+ input logic hresp
+
+);
+
+//-------------------------------------------------------------------------------
+// Local Parameters
+//-------------------------------------------------------------------------------
+`ifndef SCR1_DMEM_AHB_OUT_BP
+localparam SCR1_FIFO_WIDTH = 2;
+localparam SCR1_FIFO_CNT_WIDTH = $clog2(SCR1_FIFO_WIDTH+1);
+`endif // SCR1_DMEM_AHB_OUT_BP
+
+//-------------------------------------------------------------------------------
+// Local type declaration
+//-------------------------------------------------------------------------------
+typedef enum logic {
+ SCR1_FSM_ADDR = 1'b0,
+ SCR1_FSM_DATA = 1'b1,
+ SCR1_FSM_ERR = 1'bx
+} type_scr1_fsm_e;
+
+typedef struct packed {
+ logic hwrite;
+ logic [2:0] hwidth;
+ logic [SCR1_AHB_WIDTH-1:0] haddr;
+ logic [SCR1_AHB_WIDTH-1:0] hwdata;
+} type_scr1_req_fifo_s;
+
+typedef struct packed {
+ logic hwrite;
+ logic [2:0] hwidth;
+ logic [1:0] haddr;
+ logic [SCR1_AHB_WIDTH-1:0] hwdata;
+} type_scr1_data_fifo_s;
+
+typedef struct packed {
+ logic hresp;
+ logic [2:0] hwidth;
+ logic [1:0] haddr;
+ logic [SCR1_AHB_WIDTH-1:0] hrdata;
+} type_scr1_resp_fifo_s;
+
+//-------------------------------------------------------------------------------
+// Local functions
+//-------------------------------------------------------------------------------
+function automatic logic [2:0] scr1_conv_mem2ahb_width (
+ input type_scr1_mem_width_e dmem_width
+);
+ logic [2:0] tmp;
+begin
+ case (dmem_width)
+ SCR1_MEM_WIDTH_BYTE : begin
+ tmp = SCR1_HSIZE_8B;
+ end
+ SCR1_MEM_WIDTH_HWORD : begin
+ tmp = SCR1_HSIZE_16B;
+ end
+ SCR1_MEM_WIDTH_WORD : begin
+ tmp = SCR1_HSIZE_32B;
+ end
+ default : begin
+ tmp = SCR1_HSIZE_ERR;
+ end
+ endcase
+ return tmp;
+end
+endfunction : scr1_conv_mem2ahb_width
+
+function automatic logic[SCR1_AHB_WIDTH-1:0] scr1_conv_mem2ahb_wdata (
+ input logic [1:0] dmem_addr,
+ input type_scr1_mem_width_e dmem_width,
+ input logic [SCR1_AHB_WIDTH-1:0] dmem_wdata
+);
+ logic [SCR1_AHB_WIDTH-1:0] tmp;
+begin
+ tmp = 'x;
+ case (dmem_width)
+ SCR1_MEM_WIDTH_BYTE : begin
+ case (dmem_addr)
+ 2'b00 : begin
+ tmp[7:0] = dmem_wdata[7:0];
+ end
+ 2'b01 : begin
+ tmp[15:8] = dmem_wdata[7:0];
+ end
+ 2'b10 : begin
+ tmp[23:16] = dmem_wdata[7:0];
+ end
+ 2'b11 : begin
+ tmp[31:24] = dmem_wdata[7:0];
+ end
+ default : begin
+ end
+ endcase
+ end
+ SCR1_MEM_WIDTH_HWORD : begin
+ case (dmem_addr[1])
+ 1'b0 : begin
+ tmp[15:0] = dmem_wdata[15:0];
+ end
+ 1'b1 : begin
+ tmp[31:16] = dmem_wdata[15:0];
+ end
+ default : begin
+ end
+ endcase
+ end
+ SCR1_MEM_WIDTH_WORD : begin
+ tmp = dmem_wdata;
+ end
+ default : begin
+ end
+ endcase
+ return tmp;
+end
+endfunction : scr1_conv_mem2ahb_wdata
+
+function automatic logic[SCR1_AHB_WIDTH-1:0] scr1_conv_ahb2mem_rdata (
+ input logic [2:0] hwidth,
+ input logic [1:0] haddr,
+ input logic [SCR1_AHB_WIDTH-1:0] hrdata
+);
+ logic [SCR1_AHB_WIDTH-1:0] tmp;
+begin
+ tmp = 'x;
+ case (hwidth)
+ SCR1_HSIZE_8B : begin
+ case (haddr)
+ 2'b00 : tmp[7:0] = hrdata[7:0];
+ 2'b01 : tmp[7:0] = hrdata[15:8];
+ 2'b10 : tmp[7:0] = hrdata[23:16];
+ 2'b11 : tmp[7:0] = hrdata[31:24];
+ default : begin
+ end
+ endcase
+ end
+ SCR1_HSIZE_16B : begin
+ case (haddr[1])
+ 1'b0 : tmp[15:0] = hrdata[15:0];
+ 1'b1 : tmp[15:0] = hrdata[31:16];
+ default : begin
+ end
+ endcase
+ end
+ SCR1_HSIZE_32B : begin
+ tmp = hrdata;
+ end
+ default : begin
+ end
+ endcase
+ return tmp;
+end
+endfunction : scr1_conv_ahb2mem_rdata
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+type_scr1_fsm_e fsm;
+logic req_fifo_rd;
+logic req_fifo_wr;
+logic req_fifo_up;
+`ifdef SCR1_DMEM_AHB_OUT_BP
+type_scr1_req_fifo_s req_fifo_new;
+type_scr1_req_fifo_s req_fifo_r;
+type_scr1_req_fifo_s [0:0] req_fifo;
+`else // SCR1_DMEM_AHB_OUT_BP
+type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo;
+type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo_new;
+logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt;
+logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt_new;
+`endif // SCR1_DMEM_AHB_OUT_BP
+logic req_fifo_empty;
+logic req_fifo_full;
+
+type_scr1_data_fifo_s data_fifo;
+type_scr1_resp_fifo_s resp_fifo;
+logic resp_fifo_hready;
+
+//-------------------------------------------------------------------------------
+// Interface to Core
+//-------------------------------------------------------------------------------
+assign dmem_req_ack = ~req_fifo_full;
+assign req_fifo_wr = ~req_fifo_full & dmem_req;
+
+assign dmem_rdata = scr1_conv_ahb2mem_rdata(resp_fifo.hwidth, resp_fifo.haddr, resp_fifo.hrdata);
+
+assign dmem_resp = (resp_fifo_hready)
+ ? (resp_fifo.hresp == SCR1_HRESP_OKAY)
+ ? SCR1_MEM_RESP_RDY_OK
+ : SCR1_MEM_RESP_RDY_ER
+ : SCR1_MEM_RESP_NOTRDY ;
+
+//-------------------------------------------------------------------------------
+// REQ_FIFO
+//-------------------------------------------------------------------------------
+`ifdef SCR1_DMEM_AHB_OUT_BP
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ req_fifo_full <= 1'b0;
+ end else begin
+ if (~req_fifo_full) begin
+ req_fifo_full <= dmem_req & ~req_fifo_rd;
+ end else begin
+ req_fifo_full <= ~req_fifo_rd;
+ end
+ end
+end
+assign req_fifo_empty = ~(req_fifo_full | dmem_req);
+
+assign req_fifo_up = ~req_fifo_rd & req_fifo_wr;
+always_ff @(posedge clk) begin
+ if (req_fifo_up) begin
+ req_fifo_r <= req_fifo_new;
+ end
+end
+
+assign req_fifo_new.hwrite = dmem_req ? (dmem_cmd == SCR1_MEM_CMD_WR) : 1'b0;
+assign req_fifo_new.hwidth = dmem_req ? scr1_conv_mem2ahb_width(dmem_width) : '0;
+assign req_fifo_new.haddr = dmem_req ? dmem_addr : '0;
+assign req_fifo_new.hwdata = (dmem_req & (dmem_cmd == SCR1_MEM_CMD_WR))
+ ? scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata)
+ : '0;
+assign req_fifo[0] = (req_fifo_full) ? req_fifo_r: req_fifo_new;
+
+`else // SCR1_DMEM_AHB_OUT_BP
+always_comb begin
+ req_fifo_up = 1'b0;
+ req_fifo_cnt_new = req_fifo_cnt;
+ req_fifo_new = req_fifo;
+ case ({req_fifo_rd, req_fifo_wr})
+ 2'b00 : begin
+ // nothing todo
+ end
+ 2'b01: begin
+ // FIFO write
+ req_fifo_up = 1'b1;
+ req_fifo_new[req_fifo_cnt].hwrite = (dmem_cmd == SCR1_MEM_CMD_WR);
+ req_fifo_new[req_fifo_cnt].hwidth = scr1_conv_mem2ahb_width(dmem_width);
+ req_fifo_new[req_fifo_cnt].haddr = dmem_addr;
+ req_fifo_new[req_fifo_cnt].hwdata = scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata);
+ req_fifo_cnt_new = req_fifo_cnt + 1'b1;
+ end
+ 2'b10 : begin
+ // FIFO read
+ req_fifo_up = 1'b1;
+ req_fifo_new[0] = req_fifo_new[1];
+ req_fifo_new[1].hwrite = 1'b0;
+ req_fifo_new[1].hwidth = SCR1_HSIZE_32B;
+ req_fifo_new[1].haddr = 'x;
+ req_fifo_new[1].hwdata = 'x;
+ req_fifo_cnt_new = req_fifo_cnt - 1'b1;
+ end
+ 2'b11 : begin
+ // Read and Write FIFO. It is possible only when fifo_cnt = 1
+ req_fifo_up = 1'b1;
+ req_fifo_new[0].hwrite = (dmem_cmd == SCR1_MEM_CMD_WR);
+ req_fifo_new[0].hwidth = scr1_conv_mem2ahb_width(dmem_width);
+ req_fifo_new[0].haddr = dmem_addr;
+ req_fifo_new[0].hwdata = scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata);
+ end
+ default : begin
+ req_fifo_up = 'x;
+ req_fifo_cnt_new = 'x;
+ req_fifo_new = 'x;
+ end
+ endcase
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ req_fifo_cnt <= '0;
+ end else begin
+ if (req_fifo_up) begin
+ req_fifo_cnt <= req_fifo_cnt_new;
+ end
+ end
+end
+assign req_fifo_full = (req_fifo_cnt == SCR1_FIFO_WIDTH);
+assign req_fifo_empty = ~(|req_fifo_cnt);
+
+always_ff @(posedge clk) begin
+ if (req_fifo_up) begin
+ req_fifo <= req_fifo_new;
+ end
+end
+`endif // SCR1_DMEM_AHB_OUT_BP
+//-------------------------------------------------------------------------------
+// FSM
+//-------------------------------------------------------------------------------
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ fsm <= SCR1_FSM_ADDR;
+ end else begin
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (hready) begin
+ fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ if (hready) begin
+ if (hresp == SCR1_HRESP_OKAY) begin
+ fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
+ end else begin
+ fsm <= SCR1_FSM_ADDR;
+ end
+ end
+ end
+ default : begin
+ fsm <= SCR1_FSM_ERR;
+ end
+ endcase
+ end
+end
+
+always_comb begin
+ req_fifo_rd = 1'b0;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (hready) begin
+ req_fifo_rd = ~req_fifo_empty;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ if (hready) begin
+ req_fifo_rd = ~req_fifo_empty & (hresp == SCR1_HRESP_OKAY);
+ end
+ end
+ default : begin
+ req_fifo_rd = 1'bx;
+ end
+ endcase
+end
+
+//-------------------------------------------------------------------------------
+// FIFO data
+//-------------------------------------------------------------------------------
+always_ff @(posedge clk) begin
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (~req_fifo_empty) begin
+ data_fifo.hwrite <= req_fifo[0].hwrite;
+ data_fifo.hwidth <= req_fifo[0].hwidth;
+ data_fifo.haddr <= req_fifo[0].haddr[1:0];
+ data_fifo.hwdata <= req_fifo[0].hwdata;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ if (hready) begin
+ if (hresp == SCR1_HRESP_OKAY) begin
+ if (~req_fifo_empty) begin
+ data_fifo.hwrite <= req_fifo[0].hwrite;
+ data_fifo.hwidth <= req_fifo[0].hwidth;
+ data_fifo.haddr <= req_fifo[0].haddr[1:0];
+ data_fifo.hwdata <= req_fifo[0].hwdata;
+ end
+ end
+ end
+ end
+ default : begin
+ end
+ endcase
+end
+
+//-------------------------------------------------------------------------------
+// FIFO response
+//-------------------------------------------------------------------------------
+`ifdef SCR1_DMEM_AHB_IN_BP
+assign resp_fifo_hready = (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
+assign resp_fifo.hresp = hresp;
+assign resp_fifo.hwidth = data_fifo.hwidth;
+assign resp_fifo.haddr = data_fifo.haddr;
+assign resp_fifo.hrdata = hrdata;
+`else // SCR1_DMEM_AHB_IN_BP
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ resp_fifo_hready <= 1'b0;
+ end else begin
+ resp_fifo_hready <= (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
+ end
+end
+
+always_ff @(posedge clk) begin
+ if (hready & (fsm == SCR1_FSM_DATA)) begin
+ resp_fifo.hresp <= hresp;
+ resp_fifo.hwidth <= data_fifo.hwidth;
+ resp_fifo.haddr <= data_fifo.haddr;
+ resp_fifo.hrdata <= hrdata;
+ end
+end
+`endif // SCR1_DMEM_AHB_IN_BP
+
+//-------------------------------------------------------------------------------
+// Interface to AHB
+//-------------------------------------------------------------------------------
+assign hprot[SCR1_HPROT_DATA] = 1'b1;
+assign hprot[SCR1_HPROT_PRV] = 1'b0;
+assign hprot[SCR1_HPROT_BUF] = 1'b0;
+assign hprot[SCR1_HPROT_CACHE] = 1'b0;
+
+assign hburst = SCR1_HBURST_SINGLE;
+assign hsize = req_fifo[0].hwidth;
+assign hmastlock = 1'b0;
+
+always_comb begin
+ htrans = SCR1_HTRANS_IDLE;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (~req_fifo_empty) begin
+ htrans = SCR1_HTRANS_NONSEQ;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ if (hready) begin
+ if (hresp == SCR1_HRESP_OKAY) begin
+ if (~req_fifo_empty) begin
+ htrans = SCR1_HTRANS_NONSEQ;
+ end
+ end
+ end
+ end
+ default : begin
+ htrans = SCR1_HTRANS_ERR;
+ end
+ endcase
+end
+
+assign haddr = req_fifo[0].haddr;
+assign hwrite = req_fifo[0].hwrite;
+assign hwdata = data_fifo.hwdata;
+
+endmodule : scr1_dmem_ahb
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_dmem_router.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_dmem_router.sv
new file mode 100644
index 0000000..afef729
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_dmem_router.sv
@@ -0,0 +1,278 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_dmem_router.sv>
+/// @brief Data memory router
+///
+`include "scr1_memif.svh"
+`include "scr1_arch_description.svh"
+
+module scr1_dmem_router
+#(
+ parameter SCR1_PORT1_ADDR_MASK = `SCR1_DMEM_AWIDTH'hFFFF0000,
+ parameter SCR1_PORT1_ADDR_PATTERN = `SCR1_DMEM_AWIDTH'h00010000,
+ parameter SCR1_PORT2_ADDR_MASK = `SCR1_DMEM_AWIDTH'hFFFF0000,
+ parameter SCR1_PORT2_ADDR_PATTERN = `SCR1_DMEM_AWIDTH'h00020000
+)
+(
+ // Control signals
+ input logic rst_n,
+ input logic clk,
+
+ // Core interface
+ output logic dmem_req_ack,
+ input logic dmem_req,
+ input type_scr1_mem_cmd_e dmem_cmd,
+ input type_scr1_mem_width_e dmem_width,
+ input logic [`SCR1_DMEM_AWIDTH-1:0] dmem_addr,
+ input logic [`SCR1_DMEM_DWIDTH-1:0] dmem_wdata,
+ output logic [`SCR1_DMEM_DWIDTH-1:0] dmem_rdata,
+ output type_scr1_mem_resp_e dmem_resp,
+
+ // PORT0 interface
+ input logic port0_req_ack,
+ output logic port0_req,
+ output type_scr1_mem_cmd_e port0_cmd,
+ output type_scr1_mem_width_e port0_width,
+ output logic [`SCR1_DMEM_AWIDTH-1:0] port0_addr,
+ output logic [`SCR1_DMEM_DWIDTH-1:0] port0_wdata,
+ input logic [`SCR1_DMEM_DWIDTH-1:0] port0_rdata,
+ input type_scr1_mem_resp_e port0_resp,
+
+ // PORT1 interface
+ input logic port1_req_ack,
+ output logic port1_req,
+ output type_scr1_mem_cmd_e port1_cmd,
+ output type_scr1_mem_width_e port1_width,
+ output logic [`SCR1_DMEM_AWIDTH-1:0] port1_addr,
+ output logic [`SCR1_DMEM_DWIDTH-1:0] port1_wdata,
+ input logic [`SCR1_DMEM_DWIDTH-1:0] port1_rdata,
+ input type_scr1_mem_resp_e port1_resp,
+
+ // PORT2 interface
+ input logic port2_req_ack,
+ output logic port2_req,
+ output type_scr1_mem_cmd_e port2_cmd,
+ output type_scr1_mem_width_e port2_width,
+ output logic [`SCR1_DMEM_AWIDTH-1:0] port2_addr,
+ output logic [`SCR1_DMEM_DWIDTH-1:0] port2_wdata,
+ input logic [`SCR1_DMEM_DWIDTH-1:0] port2_rdata,
+ input type_scr1_mem_resp_e port2_resp
+);
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+typedef enum logic {
+ SCR1_FSM_ADDR,
+ SCR1_FSM_DATA
+} type_scr1_fsm_e;
+
+typedef enum logic [1:0] {
+ SCR1_SEL_PORT0,
+ SCR1_SEL_PORT1,
+ SCR1_SEL_PORT2
+} type_scr1_sel_e;
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+type_scr1_fsm_e fsm;
+type_scr1_sel_e port_sel;
+type_scr1_sel_e port_sel_r;
+logic [`SCR1_DMEM_DWIDTH-1:0] sel_rdata;
+type_scr1_mem_resp_e sel_resp;
+logic sel_req_ack;
+
+//-------------------------------------------------------------------------------
+// FSM
+//-------------------------------------------------------------------------------
+always_comb begin
+ port_sel = SCR1_SEL_PORT0;
+ if ((dmem_addr & SCR1_PORT1_ADDR_MASK) == SCR1_PORT1_ADDR_PATTERN) begin
+ port_sel = SCR1_SEL_PORT1;
+ end else if ((dmem_addr & SCR1_PORT2_ADDR_MASK) == SCR1_PORT2_ADDR_PATTERN) begin
+ port_sel = SCR1_SEL_PORT2;
+ end
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ fsm <= SCR1_FSM_ADDR;
+ port_sel_r <= SCR1_SEL_PORT0;
+ end else begin
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (dmem_req & sel_req_ack) begin
+ fsm <= SCR1_FSM_DATA;
+ port_sel_r <= port_sel;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ case (sel_resp)
+ SCR1_MEM_RESP_RDY_OK : begin
+ if (dmem_req & sel_req_ack) begin
+ fsm <= SCR1_FSM_DATA;
+ port_sel_r <= port_sel;
+ end else begin
+ fsm <= SCR1_FSM_ADDR;
+ end
+ end
+ SCR1_MEM_RESP_RDY_ER : begin
+ fsm <= SCR1_FSM_ADDR;
+ end
+ default : begin
+ end
+ endcase
+ end
+ default : begin
+ end
+ endcase
+ end
+end
+
+always_comb begin
+ if ((fsm == SCR1_FSM_ADDR) | ((fsm == SCR1_FSM_DATA) & (sel_resp == SCR1_MEM_RESP_RDY_OK))) begin
+ case (port_sel)
+ SCR1_SEL_PORT0 : sel_req_ack = port0_req_ack;
+ SCR1_SEL_PORT1 : sel_req_ack = port1_req_ack;
+ SCR1_SEL_PORT2 : sel_req_ack = port2_req_ack;
+ default : sel_req_ack = 1'b0;
+ endcase
+ end else begin
+ sel_req_ack = 1'b0;
+ end
+end
+
+always_comb begin
+ case (port_sel_r)
+ SCR1_SEL_PORT0 : begin
+ sel_rdata = port0_rdata;
+ sel_resp = port0_resp;
+ end
+ SCR1_SEL_PORT1 : begin
+ sel_rdata = port1_rdata;
+ sel_resp = port1_resp;
+ end
+ SCR1_SEL_PORT2 : begin
+ sel_rdata = port2_rdata;
+ sel_resp = port2_resp;
+ end
+ default : begin
+ sel_rdata = '0;
+ sel_resp = SCR1_MEM_RESP_RDY_ER;
+ end
+ endcase
+end
+
+//-------------------------------------------------------------------------------
+// Interface to core
+//-------------------------------------------------------------------------------
+assign dmem_req_ack = sel_req_ack;
+assign dmem_rdata = sel_rdata;
+assign dmem_resp = sel_resp;
+
+//-------------------------------------------------------------------------------
+// Interface to PORT0
+//-------------------------------------------------------------------------------
+always_comb begin
+ port0_req = 1'b0;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ port0_req = dmem_req & (port_sel == SCR1_SEL_PORT0);
+ end
+ SCR1_FSM_DATA : begin
+ if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
+ port0_req = dmem_req & (port_sel == SCR1_SEL_PORT0);
+ end
+ end
+ default : begin
+ end
+ endcase
+end
+
+`ifdef SCR1_XPROP_EN
+assign port0_cmd = (port_sel == SCR1_SEL_PORT0) ? dmem_cmd : SCR1_MEM_CMD_ERROR;
+assign port0_width = (port_sel == SCR1_SEL_PORT0) ? dmem_width : SCR1_MEM_WIDTH_ERROR;
+assign port0_addr = (port_sel == SCR1_SEL_PORT0) ? dmem_addr : 'x;
+assign port0_wdata = (port_sel == SCR1_SEL_PORT0) ? dmem_wdata : 'x;
+`else // SCR1_XPROP_EN
+assign port0_cmd = dmem_cmd ;
+assign port0_width = dmem_width;
+assign port0_addr = dmem_addr ;
+assign port0_wdata = dmem_wdata;
+`endif // SCR1_XPROP_EN
+
+//-------------------------------------------------------------------------------
+// Interface to PORT1
+//-------------------------------------------------------------------------------
+always_comb begin
+ port1_req = 1'b0;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ port1_req = dmem_req & (port_sel == SCR1_SEL_PORT1);
+ end
+ SCR1_FSM_DATA : begin
+ if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
+ port1_req = dmem_req & (port_sel == SCR1_SEL_PORT1);
+ end
+ end
+ default : begin
+ end
+ endcase
+end
+
+`ifdef SCR1_XPROP_EN
+assign port1_cmd = (port_sel == SCR1_SEL_PORT1) ? dmem_cmd : SCR1_MEM_CMD_ERROR;
+assign port1_width = (port_sel == SCR1_SEL_PORT1) ? dmem_width : SCR1_MEM_WIDTH_ERROR;
+assign port1_addr = (port_sel == SCR1_SEL_PORT1) ? dmem_addr : 'x;
+assign port1_wdata = (port_sel == SCR1_SEL_PORT1) ? dmem_wdata : 'x;
+`else // SCR1_XPROP_EN
+assign port1_cmd = dmem_cmd ;
+assign port1_width = dmem_width;
+assign port1_addr = dmem_addr ;
+assign port1_wdata = dmem_wdata;
+`endif // SCR1_XPROP_EN
+
+//-------------------------------------------------------------------------------
+// Interface to PORT2
+//-------------------------------------------------------------------------------
+always_comb begin
+ port2_req = 1'b0;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ port2_req = dmem_req & (port_sel == SCR1_SEL_PORT2);
+ end
+ SCR1_FSM_DATA : begin
+ if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
+ port2_req = dmem_req & (port_sel == SCR1_SEL_PORT2);
+ end
+ end
+ default : begin
+ end
+ endcase
+end
+
+`ifdef SCR1_XPROP_EN
+assign port2_cmd = (port_sel == SCR1_SEL_PORT2) ? dmem_cmd : SCR1_MEM_CMD_ERROR;
+assign port2_width = (port_sel == SCR1_SEL_PORT2) ? dmem_width : SCR1_MEM_WIDTH_ERROR;
+assign port2_addr = (port_sel == SCR1_SEL_PORT2) ? dmem_addr : 'x;
+assign port2_wdata = (port_sel == SCR1_SEL_PORT2) ? dmem_wdata : 'x;
+`else // SCR1_XPROP_EN
+assign port2_cmd = dmem_cmd ;
+assign port2_width = dmem_width;
+assign port2_addr = dmem_addr ;
+assign port2_wdata = dmem_wdata;
+`endif // SCR1_XPROP_EN
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+SCR1_SVA_DMEM_RT_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ dmem_req |-> !$isunknown({port_sel, dmem_cmd, dmem_width})
+ ) else $error("DMEM router Error: unknown values");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_dmem_router
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_dp_memory.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_dp_memory.sv
new file mode 100644
index 0000000..971591d
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_dp_memory.sv
@@ -0,0 +1,111 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_dp_memory.sv>
+/// @brief Dual-port synchronous memory with byte enable inputs
+///
+
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_TCM_EN
+module scr1_dp_memory
+#(
+ parameter SCR1_WIDTH = 32,
+ parameter SCR1_SIZE = `SCR1_IMEM_AWIDTH'h00010000,
+ parameter SCR1_NBYTES = SCR1_WIDTH / 8
+)
+(
+ input logic clk,
+ // Port A
+ input logic rena,
+ input logic [$clog2(SCR1_SIZE)-1:2] addra,
+ output logic [SCR1_WIDTH-1:0] qa,
+ // Port B
+ input logic renb,
+ input logic wenb,
+ input logic [SCR1_NBYTES-1:0] webb,
+ input logic [$clog2(SCR1_SIZE)-1:2] addrb,
+ input logic [SCR1_WIDTH-1:0] datab,
+ output logic [SCR1_WIDTH-1:0] qb
+);
+
+`ifdef SCR1_TRGT_FPGA_INTEL
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+ `ifdef SCR1_TRGT_FPGA_INTEL_MAX10
+(* ramstyle = "M9K" *) logic [SCR1_NBYTES-1:0][7:0] memory_array [0:(SCR1_SIZE/SCR1_NBYTES)-1];
+ `elsif SCR1_TRGT_FPGA_INTEL_ARRIAV
+(* ramstyle = "M10K" *) logic [SCR1_NBYTES-1:0][7:0] memory_array [0:(SCR1_SIZE/SCR1_NBYTES)-1];
+ `endif
+logic [3:0] wenbb;
+//-------------------------------------------------------------------------------
+// Port B memory behavioral description
+//-------------------------------------------------------------------------------
+assign wenbb = {4{wenb}} & webb;
+always_ff @(posedge clk) begin
+ if (wenb) begin
+ if (wenbb[0]) begin
+ memory_array[addrb][0] <= datab[0+:8];
+ end
+ if (wenbb[1]) begin
+ memory_array[addrb][1] <= datab[8+:8];
+ end
+ if (wenbb[2]) begin
+ memory_array[addrb][2] <= datab[16+:8];
+ end
+ if (wenbb[3]) begin
+ memory_array[addrb][3] <= datab[24+:8];
+ end
+ end
+ qb <= memory_array[addrb];
+end
+//-------------------------------------------------------------------------------
+// Port A memory behavioral description
+//-------------------------------------------------------------------------------
+always_ff @(posedge clk) begin
+ qa <= memory_array[addra];
+end
+
+`else // SCR1_TRGT_FPGA_INTEL
+
+// CASE: OTHERS - SCR1_TRGT_FPGA_XILINX, SIMULATION, ASIC etc
+
+localparam int unsigned RAM_SIZE_WORDS = SCR1_SIZE/SCR1_NBYTES;
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+ `ifdef SCR1_TRGT_FPGA_XILINX
+(* ram_style = "block" *) logic [SCR1_WIDTH-1:0] ram_block [RAM_SIZE_WORDS-1:0];
+ `else // ASIC or SIMULATION
+logic [SCR1_WIDTH-1:0] ram_block [RAM_SIZE_WORDS-1:0];
+ `endif
+//-------------------------------------------------------------------------------
+// Port A memory behavioral description
+//-------------------------------------------------------------------------------
+always_ff @(posedge clk) begin
+ if (rena) begin
+ qa <= ram_block[addra];
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Port B memory behavioral description
+//-------------------------------------------------------------------------------
+always_ff @(posedge clk) begin
+ if (wenb) begin
+ for (int i=0; i<SCR1_NBYTES; i++) begin
+ if (webb[i]) begin
+ ram_block[addrb][i*8 +: 8] <= datab[i*8 +: 8];
+ end
+ end
+ end
+ if (renb) begin
+ qb <= ram_block[addrb];
+ end
+end
+
+`endif // SCR1_TRGT_FPGA_INTEL
+
+endmodule : scr1_dp_memory
+
+`endif // SCR1_TCM_EN
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_imem_ahb.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_imem_ahb.sv
new file mode 100644
index 0000000..e749f9d
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_imem_ahb.sv
@@ -0,0 +1,319 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_imem_ahb.sv>
+/// @brief Instruction memory AHB bridge
+///
+
+`include "scr1_ahb.svh"
+`include "scr1_memif.svh"
+
+module scr1_imem_ahb (
+ // Control Signals
+ input logic rst_n,
+ input logic clk,
+
+ // Core Interface
+ output logic imem_req_ack,
+ input logic imem_req,
+ input logic [SCR1_AHB_WIDTH-1:0] imem_addr,
+ output logic [SCR1_AHB_WIDTH-1:0] imem_rdata,
+ output type_scr1_mem_resp_e imem_resp,
+
+ // AHB Interface
+ output logic [3:0] hprot,
+ output logic [2:0] hburst,
+ output logic [2:0] hsize,
+ output logic [1:0] htrans,
+ output logic hmastlock,
+ output logic [SCR1_AHB_WIDTH-1:0] haddr,
+ input logic hready,
+ input logic [SCR1_AHB_WIDTH-1:0] hrdata,
+ input logic hresp
+
+);
+
+//-------------------------------------------------------------------------------
+// Local parameters declaration
+//-------------------------------------------------------------------------------
+`ifndef SCR1_IMEM_AHB_OUT_BP
+localparam SCR1_FIFO_WIDTH = 2;
+localparam SCR1_FIFO_CNT_WIDTH = $clog2(SCR1_FIFO_WIDTH+1);
+`endif // SCR1_IMEM_AHB_OUT_BP
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+typedef enum logic {
+ SCR1_FSM_ADDR = 1'b0,
+ SCR1_FSM_DATA = 1'b1,
+ SCR1_FSM_ERR = 1'bx
+} type_scr1_fsm_e;
+
+typedef struct packed {
+ logic [SCR1_AHB_WIDTH-1:0] haddr;
+} type_scr1_req_fifo_s;
+
+typedef struct packed {
+ logic hresp;
+ logic [SCR1_AHB_WIDTH-1:0] hrdata;
+} type_scr1_resp_fifo_s;
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+type_scr1_fsm_e fsm;
+logic req_fifo_rd;
+logic req_fifo_wr;
+logic req_fifo_up;
+`ifdef SCR1_IMEM_AHB_OUT_BP
+type_scr1_req_fifo_s req_fifo_r;
+type_scr1_req_fifo_s [0:0] req_fifo;
+`else // SCR1_IMEM_AHB_OUT_BP
+type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo;
+type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo_new;
+logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt;
+logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt_new;
+`endif // SCR1_IMEM_AHB_OUT_BP
+logic req_fifo_empty;
+logic req_fifo_full;
+
+type_scr1_resp_fifo_s resp_fifo;
+logic resp_fifo_hready;
+
+//-------------------------------------------------------------------------------
+// Interface to Core
+//-------------------------------------------------------------------------------
+assign imem_req_ack = ~req_fifo_full;
+assign req_fifo_wr = ~req_fifo_full & imem_req;
+
+assign imem_rdata = resp_fifo.hrdata;
+
+assign imem_resp = (resp_fifo_hready)
+ ? (resp_fifo.hresp == SCR1_HRESP_OKAY)
+ ? SCR1_MEM_RESP_RDY_OK
+ : SCR1_MEM_RESP_RDY_ER
+ : SCR1_MEM_RESP_NOTRDY;
+
+//-------------------------------------------------------------------------------
+// REQ_FIFO
+//-------------------------------------------------------------------------------
+`ifdef SCR1_IMEM_AHB_OUT_BP
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ req_fifo_full <= 1'b0;
+ end else begin
+ if (~req_fifo_full) begin
+ req_fifo_full <= imem_req & ~req_fifo_rd;
+ end else begin
+ req_fifo_full <= ~req_fifo_rd;
+ end
+ end
+end
+assign req_fifo_empty = ~(req_fifo_full | imem_req);
+
+assign req_fifo_up = ~req_fifo_rd & req_fifo_wr;
+always_ff @(posedge clk) begin
+ if (req_fifo_up) begin
+ req_fifo_r.haddr <= imem_addr;
+ end
+end
+
+assign req_fifo[0] = (req_fifo_full) ? req_fifo_r : imem_addr;
+
+`else // SCR1_IMEM_AHB_OUT_BP
+always_comb begin
+ req_fifo_up = 1'b0;
+ req_fifo_cnt_new = req_fifo_cnt;
+ req_fifo_new = req_fifo;
+ case ({req_fifo_rd, req_fifo_wr})
+ 2'b00 : begin
+ // nothing todo
+ end
+ 2'b01: begin
+ // FIFO write
+ req_fifo_up = 1'b1;
+ req_fifo_new[req_fifo_cnt].haddr = imem_addr;
+ req_fifo_cnt_new = req_fifo_cnt + 1'b1;
+ end
+ 2'b10 : begin
+ // FIFO read
+ req_fifo_up = 1'b1;
+ req_fifo_new[0] = req_fifo_new[1];
+ req_fifo_new[1].haddr = 'x;
+ req_fifo_cnt_new = req_fifo_cnt - 1'b1;
+ end
+ 2'b11 : begin
+ // Read and Write FIFO. It is possible only when fifo_cnt = 1
+ req_fifo_up = 1'b1;
+ req_fifo_new[0].haddr = imem_addr;
+ end
+ default : begin
+ req_fifo_up = 'x;
+ req_fifo_cnt_new = 'x;
+ req_fifo_new = 'x;
+ end
+ endcase
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ req_fifo_cnt <= '0;
+ end else begin
+ if (req_fifo_up) begin
+ req_fifo_cnt <= req_fifo_cnt_new;
+ end
+ end
+end
+assign req_fifo_full = (req_fifo_cnt == SCR1_FIFO_WIDTH);
+assign req_fifo_empty = ~(|req_fifo_cnt);
+
+always_ff @(posedge clk) begin
+ if (req_fifo_up) begin
+ req_fifo <= req_fifo_new;
+ end
+end
+`endif // SCR1_IMEM_AHB_OUT_BP
+
+//-------------------------------------------------------------------------------
+// FSM
+//-------------------------------------------------------------------------------
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ fsm <= SCR1_FSM_ADDR;
+ end else begin
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (hready) begin
+ fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ if (hready) begin
+ if (hresp == SCR1_HRESP_OKAY) begin
+ fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
+ end else begin
+ fsm <= SCR1_FSM_ADDR;
+ end
+ end
+ end
+ default : begin
+ fsm <= SCR1_FSM_ERR;
+ end
+ endcase
+ end
+end
+
+always_comb begin
+ req_fifo_rd = 1'b0;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (hready) begin
+ req_fifo_rd = ~req_fifo_empty;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ if (hready) begin
+ req_fifo_rd = ~req_fifo_empty & (hresp == SCR1_HRESP_OKAY);
+ end
+ end
+ default : begin
+ req_fifo_rd = 1'bx;
+ end
+ endcase
+end
+
+//-------------------------------------------------------------------------------
+// FIFO response
+//-------------------------------------------------------------------------------
+`ifdef SCR1_IMEM_AHB_IN_BP
+assign resp_fifo_hready = (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
+assign resp_fifo.hresp = hresp;
+assign resp_fifo.hrdata = hrdata;
+`else // SCR1_IMEM_AHB_IN_BP
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ resp_fifo_hready <= 1'b0;
+ end else begin
+ resp_fifo_hready <= (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
+ end
+end
+
+always_ff @(posedge clk) begin
+ if (hready & (fsm == SCR1_FSM_DATA)) begin
+ resp_fifo.hresp <= hresp;
+ resp_fifo.hrdata <= hrdata;
+ end
+end
+`endif // SCR1_IMEM_AHB_IN_BP
+
+//-------------------------------------------------------------------------------
+// Interface to AHB
+//-------------------------------------------------------------------------------
+assign hprot[SCR1_HPROT_DATA] = 1'b0;
+assign hprot[SCR1_HPROT_PRV] = 1'b0;
+assign hprot[SCR1_HPROT_BUF] = 1'b0;
+assign hprot[SCR1_HPROT_CACHE] = 1'b0;
+
+assign hburst = SCR1_HBURST_SINGLE;
+assign hsize = SCR1_HSIZE_32B;
+assign hmastlock = 1'b0;
+
+always_comb begin
+ htrans = SCR1_HTRANS_IDLE;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (~req_fifo_empty) begin
+ htrans = SCR1_HTRANS_NONSEQ;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ if (hready) begin
+ if (hresp == SCR1_HRESP_OKAY) begin
+ if (~req_fifo_empty) begin
+ htrans = SCR1_HTRANS_NONSEQ;
+ end
+ end
+ end
+ end
+ default : begin
+ htrans = SCR1_HTRANS_ERR;
+ end
+ endcase
+end
+
+assign haddr = req_fifo[0].haddr;
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+// Check Core interface
+SCR1_SVA_IMEM_AHB_BRIDGE_REQ_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(imem_req)
+ ) else $error("IMEM AHB bridge Error: imem_req has unknown values");
+
+SCR1_IMEM_AHB_BRIDGE_ADDR_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ imem_req |-> !$isunknown(imem_addr)
+ ) else $error("IMEM AHB bridge Error: imem_addr has unknown values");
+
+SCR1_IMEM_AHB_BRIDGE_ADDR_ALLIGN : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ imem_req |-> (imem_addr[1:0] == '0)
+ ) else $error("IMEM AHB bridge Error: imem_addr has unalign values");
+
+// Check AHB interface
+SCR1_IMEM_AHB_BRIDGE_HREADY_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(hready)
+ ) else $error("IMEM AHB bridge Error: hready has unknown values");
+
+SCR1_IMEM_AHB_BRIDGE_HRESP_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ !$isunknown(hresp)
+ ) else $error("IMEM AHB bridge Error: hresp has unknown values");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_imem_ahb
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_imem_router.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_imem_router.sv
new file mode 100644
index 0000000..dd76f25
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_imem_router.sv
@@ -0,0 +1,185 @@
+/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
+/// @file <scr1_imem_router.sv>
+/// @brief Instruction memory router
+///
+`include "scr1_memif.svh"
+`include "scr1_arch_description.svh"
+
+module scr1_imem_router
+#(
+ parameter SCR1_ADDR_MASK = `SCR1_IMEM_AWIDTH'hFFFF0000,
+ parameter SCR1_ADDR_PATTERN = `SCR1_IMEM_AWIDTH'h00010000
+)
+(
+ // Control signals
+ input logic rst_n,
+ input logic clk,
+
+ // Core interface
+ output logic imem_req_ack,
+ input logic imem_req,
+ input type_scr1_mem_cmd_e imem_cmd,
+ input logic [`SCR1_IMEM_AWIDTH-1:0] imem_addr,
+ output logic [`SCR1_IMEM_DWIDTH-1:0] imem_rdata,
+ output type_scr1_mem_resp_e imem_resp,
+
+ // PORT0 interface
+ input logic port0_req_ack,
+ output logic port0_req,
+ output type_scr1_mem_cmd_e port0_cmd,
+ output logic [`SCR1_IMEM_AWIDTH-1:0] port0_addr,
+ input logic [`SCR1_IMEM_DWIDTH-1:0] port0_rdata,
+ input type_scr1_mem_resp_e port0_resp,
+
+ // PORT1 interface
+ input logic port1_req_ack,
+ output logic port1_req,
+ output type_scr1_mem_cmd_e port1_cmd,
+ output logic [`SCR1_IMEM_AWIDTH-1:0] port1_addr,
+ input logic [`SCR1_IMEM_DWIDTH-1:0] port1_rdata,
+ input type_scr1_mem_resp_e port1_resp
+);
+
+//-------------------------------------------------------------------------------
+// Local types declaration
+//-------------------------------------------------------------------------------
+typedef enum logic {
+ SCR1_FSM_ADDR,
+ SCR1_FSM_DATA
+} type_scr1_fsm_e;
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+type_scr1_fsm_e fsm;
+logic port_sel;
+logic port_sel_r;
+logic [`SCR1_IMEM_DWIDTH-1:0] sel_rdata;
+type_scr1_mem_resp_e sel_resp;
+logic sel_req_ack;
+
+//-------------------------------------------------------------------------------
+// FSM
+//-------------------------------------------------------------------------------
+assign port_sel = ((imem_addr & SCR1_ADDR_MASK) == SCR1_ADDR_PATTERN);
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ fsm <= SCR1_FSM_ADDR;
+ port_sel_r <= 1'b0;
+ end else begin
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ if (imem_req & sel_req_ack) begin
+ fsm <= SCR1_FSM_DATA;
+ port_sel_r <= port_sel;
+ end
+ end
+ SCR1_FSM_DATA : begin
+ case (sel_resp)
+ SCR1_MEM_RESP_RDY_OK : begin
+ if (imem_req & sel_req_ack) begin
+ fsm <= SCR1_FSM_DATA;
+ port_sel_r <= port_sel;
+ end else begin
+ fsm <= SCR1_FSM_ADDR;
+ end
+ end
+ SCR1_MEM_RESP_RDY_ER : begin
+ fsm <= SCR1_FSM_ADDR;
+ end
+ default : begin
+ end
+ endcase
+ end
+ default : begin
+ end
+ endcase
+ end
+end
+
+always_comb begin
+ if ((fsm == SCR1_FSM_ADDR) | ((fsm == SCR1_FSM_DATA) & (sel_resp == SCR1_MEM_RESP_RDY_OK))) begin
+ sel_req_ack = (port_sel) ? port1_req_ack : port0_req_ack;
+ end else begin
+ sel_req_ack = 1'b0;
+ end
+end
+
+assign sel_rdata = (port_sel_r) ? port1_rdata : port0_rdata;
+assign sel_resp = (port_sel_r) ? port1_resp : port0_resp;
+
+//-------------------------------------------------------------------------------
+// Interface to core
+//-------------------------------------------------------------------------------
+assign imem_req_ack = sel_req_ack;
+assign imem_rdata = sel_rdata;
+assign imem_resp = sel_resp;
+
+//-------------------------------------------------------------------------------
+// Interface to PORT0
+//-------------------------------------------------------------------------------
+always_comb begin
+ port0_req = 1'b0;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ port0_req = imem_req & ~port_sel;
+ end
+ SCR1_FSM_DATA : begin
+ if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
+ port0_req = imem_req & ~port_sel;
+ end
+ end
+ default : begin
+ end
+ endcase
+end
+
+`ifdef SCR1_XPROP_EN
+assign port0_cmd = (~port_sel) ? imem_cmd : SCR1_MEM_CMD_ERROR;
+assign port0_addr = (~port_sel) ? imem_addr : 'x;
+`else // SCR1_XPROP_EN
+assign port0_cmd = imem_cmd ;
+assign port0_addr = imem_addr;
+`endif // SCR1_XPROP_EN
+
+//-------------------------------------------------------------------------------
+// Interface to PORT1
+//-------------------------------------------------------------------------------
+always_comb begin
+ port1_req = 1'b0;
+ case (fsm)
+ SCR1_FSM_ADDR : begin
+ port1_req = imem_req & port_sel;
+ end
+ SCR1_FSM_DATA : begin
+ if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
+ port1_req = imem_req & port_sel;
+ end
+ end
+ default : begin
+ end
+ endcase
+end
+
+`ifdef SCR1_XPROP_EN
+assign port1_cmd = (port_sel) ? imem_cmd : SCR1_MEM_CMD_ERROR;
+assign port1_addr = (port_sel) ? imem_addr : 'x;
+`else // SCR1_XPROP_EN
+assign port1_cmd = imem_cmd ;
+assign port1_addr = imem_addr;
+`endif // SCR1_XPROP_EN
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+SCR1_SVA_IMEM_RT_XCHECK : assert property (
+ @(negedge clk) disable iff (~rst_n)
+ imem_req |-> !$isunknown({port_sel, imem_cmd})
+ ) else $error("IMEM router Error: unknown values");
+
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_imem_router
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_mem_axi.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_mem_axi.sv
new file mode 100644
index 0000000..406494d
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_mem_axi.sv
@@ -0,0 +1,363 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_mem_axi.sv>
+/// @brief Memory AXI bridge
+///
+
+`include "scr1_memif.svh"
+`include "scr1_arch_description.svh"
+
+module scr1_mem_axi
+#(
+ parameter SCR1_REQ_BUF_SIZE = 2, // Power of 2 value
+ parameter SCR1_AXI_IDWIDTH = 4,
+ parameter SCR1_ADDR_WIDTH = 32,
+ parameter SCR1_AXI_REQ_BP = 1,
+ parameter SCR1_AXI_RESP_BP = 1
+)
+(
+ // Clock and Reset
+ input logic clk,
+ input logic rst_n,
+ input logic axi_reinit,
+ // Core Interface
+ output logic core_idle,
+ output logic core_req_ack,
+ input logic core_req,
+ input type_scr1_mem_cmd_e core_cmd,
+ input type_scr1_mem_width_e core_width,
+ input logic [SCR1_ADDR_WIDTH-1:0] core_addr,
+ input logic [31:0] core_wdata,
+ output logic [31:0] core_rdata,
+ output type_scr1_mem_resp_e core_resp,
+
+ // AXI
+ output logic [SCR1_AXI_IDWIDTH-1:0] awid,
+ output logic [SCR1_ADDR_WIDTH-1:0] awaddr,
+ output logic [ 7:0] awlen,
+ output logic [ 2:0] awsize,
+ output logic [ 1:0] awburst,
+ output logic awlock,
+ output logic [ 3:0] awcache,
+ output logic [ 2:0] awprot,
+ output logic [ 3:0] awregion,
+ output logic [ 3:0] awuser,
+ output logic [ 3:0] awqos,
+ output logic awvalid,
+ input logic awready,
+ output logic [31:0] wdata,
+ output logic [3:0] wstrb,
+ output logic wlast,
+ output logic [3:0] wuser,
+ output logic wvalid,
+ input logic wready,
+ input logic [SCR1_AXI_IDWIDTH-1:0] bid,
+ input logic [ 1:0] bresp,
+ input logic bvalid,
+ input logic [ 3:0] buser,
+ output logic bready,
+ output logic [SCR1_AXI_IDWIDTH-1:0] arid,
+ output logic [SCR1_ADDR_WIDTH-1:0] araddr,
+ output logic [ 7:0] arlen,
+ output logic [ 2:0] arsize,
+ output logic [ 1:0] arburst,
+ output logic arlock,
+ output logic [ 3:0] arcache,
+ output logic [ 2:0] arprot,
+ output logic [ 3:0] arregion,
+ output logic [ 3:0] aruser,
+ output logic [ 3:0] arqos,
+ output logic arvalid,
+ input logic arready,
+ input logic [SCR1_AXI_IDWIDTH-1:0] rid,
+ input logic [31:0] rdata,
+ input logic [ 1:0] rresp,
+ input logic rlast,
+ input logic [ 3:0] ruser,
+ input logic rvalid,
+ output logic rready
+);
+
+
+// Local functions
+function automatic logic [2:0] width2axsize (
+ input type_scr1_mem_width_e width );
+ logic [2:0] axsize;
+begin
+ case (width)
+ SCR1_MEM_WIDTH_BYTE : axsize = 3'b000;
+ SCR1_MEM_WIDTH_HWORD: axsize = 3'b001;
+ SCR1_MEM_WIDTH_WORD : axsize = 3'b010;
+ default: axsize = 'x;
+ endcase
+
+ return axsize;
+end
+endfunction: width2axsize
+
+typedef struct packed {
+ type_scr1_mem_width_e axi_width;
+ logic [SCR1_ADDR_WIDTH-1:0] axi_addr;
+ logic [31:0] axi_wdata;
+} type_scr1_request_s;
+
+typedef struct packed {
+ logic req_write;
+ logic req_addr;
+ logic req_data;
+ logic req_resp;
+} type_scr1_req_status_s;
+
+
+type_scr1_request_s [SCR1_REQ_BUF_SIZE-1:0] req_fifo;
+type_scr1_req_status_s [SCR1_REQ_BUF_SIZE-1:0] req_status;
+type_scr1_req_status_s [SCR1_REQ_BUF_SIZE-1:0] req_status_new;
+logic [SCR1_REQ_BUF_SIZE-1:0] req_status_en;
+logic [$clog2(SCR1_REQ_BUF_SIZE)-1:0] req_aval_ptr;
+logic [$clog2(SCR1_REQ_BUF_SIZE)-1:0] req_proc_ptr;
+logic [$clog2(SCR1_REQ_BUF_SIZE)-1:0] req_done_ptr;
+logic rresp_err;
+logic [31:0] rcvd_rdata;
+type_scr1_mem_resp_e rcvd_resp;
+logic force_read;
+logic force_write;
+
+
+
+assign core_req_ack = ~axi_reinit &
+ ~req_status[req_aval_ptr].req_resp &
+ core_resp!=SCR1_MEM_RESP_RDY_ER;
+
+
+assign rready = ~req_status[req_done_ptr].req_write;
+assign bready = req_status[req_done_ptr].req_write;
+
+
+assign force_read = bit'(SCR1_AXI_REQ_BP) & core_req & core_req_ack & req_aval_ptr==req_proc_ptr & core_cmd==SCR1_MEM_CMD_RD;
+assign force_write = bit'(SCR1_AXI_REQ_BP) & core_req & core_req_ack & req_aval_ptr==req_proc_ptr & core_cmd==SCR1_MEM_CMD_WR;
+
+
+always_comb begin: idle_status
+ core_idle = 1'b1;
+ for (int unsigned i=0; i<SCR1_REQ_BUF_SIZE; ++i) begin
+ core_idle &= req_status[i].req_resp==1'b0;
+ end
+end
+
+always_ff @(posedge clk) begin
+ if (core_req & core_req_ack) begin
+ req_fifo[req_aval_ptr].axi_width <= core_width;
+ req_fifo[req_aval_ptr].axi_addr <= core_addr;
+ req_fifo[req_aval_ptr].axi_wdata <= core_wdata;
+ end
+end
+
+// Request Status Queue
+// It is used for holding control info of processing requests
+
+// Combinational logic of Request Status Queue
+always_comb begin
+ // Default
+ req_status_en = '0; // No update
+ req_status_new = req_status; // Hold request info
+
+ // Update status on new core request
+ if( core_req & core_req_ack ) begin
+ req_status_en[req_aval_ptr] = 1'd1;
+
+ req_status_new[req_aval_ptr].req_resp = 1'd1;
+ req_status_new[req_aval_ptr].req_write = core_cmd == SCR1_MEM_CMD_WR;
+
+ req_status_new[req_aval_ptr].req_addr = ~( (force_read & arready) |
+ (force_write & awready) );
+
+ req_status_new[req_aval_ptr].req_data = ~( (force_write & wready & awlen == 8'd0) |
+ (~force_write & core_cmd == SCR1_MEM_CMD_RD) );
+ end
+
+ // Update status on AXI address phase
+ if ( (awvalid & awready) | (arvalid & arready) ) begin
+ req_status_en[req_proc_ptr] = 1'd1;
+ req_status_new[req_proc_ptr].req_addr = 1'd0;
+ end
+
+ // Update status on AXI data phase
+ if ( wvalid & wready & wlast ) begin
+ req_status_en[req_proc_ptr] = 1'd1;
+ req_status_new[req_proc_ptr].req_data = 1'd0;
+ end
+
+ // Update status when AXI finish transaction
+ if ( (bvalid & bready) | (rvalid & rready & rlast) ) begin
+ req_status_en[req_done_ptr] = 1'd1;
+ req_status_new[req_done_ptr].req_resp = 1'd0;
+ end
+end
+
+// Request Status Queue register
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ req_status <= '0;
+ end else begin
+ for (int unsigned i = 0; i < SCR1_REQ_BUF_SIZE; ++i) begin
+ if ( req_status_en[i] ) begin
+ req_status[i] <= req_status_new[i];
+ end
+ end
+ end
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) req_aval_ptr <= '0;
+ else if (core_req & core_req_ack) req_aval_ptr <= req_aval_ptr + 1'b1;
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ req_proc_ptr <= '0;
+ end else begin
+ if (( awvalid & awready & wvalid & wready & wlast) |
+ (~force_write & ~req_status[req_proc_ptr].req_data & awvalid & awready ) |
+ (~force_write & ~req_status[req_proc_ptr].req_addr & wvalid & wready & wlast) |
+ ( ~req_status[req_proc_ptr].req_data & arvalid & arready ) ) begin
+
+ req_proc_ptr <= req_proc_ptr + 1'b1;
+ end
+ end
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ req_done_ptr <= '0;
+ end else begin
+ if ((bvalid & bready | rvalid & rready & rlast) & req_status[req_done_ptr].req_resp) begin
+
+ req_done_ptr <= req_done_ptr + 1'b1;
+ end
+ end
+end
+
+
+
+assign arvalid = req_status[req_proc_ptr].req_addr & ~req_status[req_proc_ptr].req_write | force_read;
+assign awvalid = req_status[req_proc_ptr].req_addr & req_status[req_proc_ptr].req_write | force_write;
+assign wvalid = req_status[req_proc_ptr].req_data & req_status[req_proc_ptr].req_write | force_write;
+
+assign araddr = (~force_read )? req_fifo[req_proc_ptr].axi_addr : core_addr;
+assign awaddr = (~force_write)? req_fifo[req_proc_ptr].axi_addr : core_addr;
+
+always_comb begin
+ if (bvalid & bready & req_status[req_done_ptr].req_resp) begin
+ rcvd_resp = (bresp==2'b00)? SCR1_MEM_RESP_RDY_OK :
+ SCR1_MEM_RESP_RDY_ER;
+ end else begin
+ if (rvalid & rready & rlast & req_status[req_done_ptr].req_resp) begin
+ rcvd_resp = (rresp==2'b00)? SCR1_MEM_RESP_RDY_OK :
+ SCR1_MEM_RESP_RDY_ER;
+ end else begin
+ rcvd_resp = SCR1_MEM_RESP_NOTRDY;
+ end
+ end
+end
+
+
+
+
+// Write data signals adaptation
+always_comb begin
+ if (force_write)
+ case (core_width)
+ SCR1_MEM_WIDTH_BYTE : wstrb = 4'h1 << core_addr[1:0];
+ SCR1_MEM_WIDTH_HWORD: wstrb = 4'h3 << core_addr[1:0];
+ SCR1_MEM_WIDTH_WORD : wstrb = 4'hf << core_addr[1:0];
+ default: wstrb = 'x;
+ endcase
+ else
+ case (req_fifo[req_proc_ptr].axi_width)
+ SCR1_MEM_WIDTH_BYTE : wstrb = 4'h1 << req_fifo[req_proc_ptr].axi_addr[1:0];
+ SCR1_MEM_WIDTH_HWORD: wstrb = 4'h3 << req_fifo[req_proc_ptr].axi_addr[1:0];
+ SCR1_MEM_WIDTH_WORD : wstrb = 4'hf << req_fifo[req_proc_ptr].axi_addr[1:0];
+ default: wstrb = 'x;
+ endcase
+end
+
+
+
+assign wdata = (force_write)? core_wdata << (8* core_addr[1:0]) :
+ req_fifo[req_proc_ptr].axi_wdata << (8* req_fifo[req_proc_ptr].axi_addr[1:0]);
+
+
+// Read data adaptation
+always_comb begin
+ case (req_fifo[req_done_ptr].axi_width)
+ SCR1_MEM_WIDTH_BYTE : rcvd_rdata = rdata >> (8*req_fifo[req_done_ptr].axi_addr[1:0]);
+ SCR1_MEM_WIDTH_HWORD: rcvd_rdata = rdata >> (8*req_fifo[req_done_ptr].axi_addr[1:0]);
+ SCR1_MEM_WIDTH_WORD : rcvd_rdata = rdata >> (8*req_fifo[req_done_ptr].axi_addr[1:0]);
+ default: rcvd_rdata = 'x;
+ endcase
+end
+
+
+generate
+ if (SCR1_AXI_RESP_BP == 1) begin : axi_resp_bp
+ assign core_rdata = (rvalid & rready & rlast) ? rcvd_rdata : '0;
+ assign core_resp = (axi_reinit) ? SCR1_MEM_RESP_NOTRDY : rcvd_resp;
+ end else begin : axi_resp_no_bp
+ always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) core_resp <= SCR1_MEM_RESP_NOTRDY;
+ else core_resp <= (axi_reinit) ? SCR1_MEM_RESP_NOTRDY : rcvd_resp;
+ end
+ always_ff @(posedge clk) begin
+ if (rvalid & rready & rlast) core_rdata <= rcvd_rdata;
+ end
+ end
+endgenerate
+
+
+
+// AXI interface assignments
+assign awid = SCR1_AXI_IDWIDTH'(1);
+assign awlen = 8'd0;
+assign awsize = (force_write) ? width2axsize(core_width) : width2axsize(req_fifo[req_proc_ptr].axi_width);
+assign awburst = 2'd1;
+assign awcache = 4'd2;
+assign awlock = '0;
+assign awprot = '0;
+assign awregion = '0;
+assign awuser = '0;
+assign awqos = '0;
+
+assign arid = SCR1_AXI_IDWIDTH'(0);
+assign arlen = 8'd0;
+assign arsize = (force_read) ? width2axsize(core_width) : width2axsize(req_fifo[req_proc_ptr].axi_width);
+assign arburst = 2'd1;
+assign arcache = 4'd2;
+assign arprot = '0;
+assign arregion = '0;
+assign arlock = '0;
+assign arqos = '0;
+assign aruser = '0;
+
+assign wlast = 1'd1;
+assign wuser = '0;
+
+
+`ifdef SCR1_TRGT_SIMULATION
+//-------------------------------------------------------------------------------
+// Assertion
+//-------------------------------------------------------------------------------
+
+// X checks
+SCR1_SVA_AXI_X_CHECK0 : assert property (@(negedge clk) disable iff (~rst_n) !$isunknown({core_req, awready, wready, bvalid, arready, rvalid}) )
+ else $error("AXI bridge: X state on input");
+SCR1_SVA_AXI_X_CHECK1 : assert property (@(negedge clk) disable iff (~rst_n) core_req |->
+ !$isunknown({core_cmd, core_width, core_addr}) )
+ else $error("AXI bridge: X state on input");
+SCR1_SVA_AXI_X_CHECK2 : assert property (@(negedge clk) disable iff (~rst_n) bvalid |->
+ !$isunknown({bid, bresp}) )
+ else $error("AXI bridge: X state on input");
+SCR1_SVA_AXI_X_CHECK3 : assert property (@(negedge clk) disable iff (~rst_n) rvalid |->
+ !$isunknown({rid, rresp}) )
+ else $error("AXI bridge: X state on input");
+`endif // SCR1_TRGT_SIMULATION
+
+endmodule : scr1_mem_axi
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_tcm.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_tcm.sv
new file mode 100644
index 0000000..97376cf
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_tcm.sv
@@ -0,0 +1,131 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_tcm.sv>
+/// @brief Tightly-Coupled Memory (TCM)
+///
+
+`include "scr1_memif.svh"
+`include "scr1_arch_description.svh"
+
+`ifdef SCR1_TCM_EN
+module scr1_tcm
+#(
+ parameter SCR1_TCM_SIZE = `SCR1_IMEM_AWIDTH'h00010000
+)
+(
+ // Control signals
+ input logic clk,
+ input logic rst_n,
+
+ // Core instruction interface
+ output logic imem_req_ack,
+ input logic imem_req,
+ input logic [`SCR1_IMEM_AWIDTH-1:0] imem_addr,
+ output logic [`SCR1_IMEM_DWIDTH-1:0] imem_rdata,
+ output type_scr1_mem_resp_e imem_resp,
+
+ // Core data interface
+ output logic dmem_req_ack,
+ input logic dmem_req,
+ input type_scr1_mem_cmd_e dmem_cmd,
+ input type_scr1_mem_width_e dmem_width,
+ input logic [`SCR1_DMEM_AWIDTH-1:0] dmem_addr,
+ input logic [`SCR1_DMEM_DWIDTH-1:0] dmem_wdata,
+ output logic [`SCR1_DMEM_DWIDTH-1:0] dmem_rdata,
+ output type_scr1_mem_resp_e dmem_resp
+);
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+logic imem_req_en;
+logic dmem_req_en;
+logic imem_rd;
+logic dmem_rd;
+logic dmem_wr;
+logic [`SCR1_DMEM_DWIDTH-1:0] dmem_writedata;
+logic [`SCR1_DMEM_DWIDTH-1:0] dmem_rdata_local;
+logic [3:0] dmem_byteen;
+logic [1:0] dmem_rdata_shift_reg;
+//-------------------------------------------------------------------------------
+// Core interface
+//-------------------------------------------------------------------------------
+assign imem_req_en = (imem_resp == SCR1_MEM_RESP_RDY_OK) ^ imem_req;
+assign dmem_req_en = (dmem_resp == SCR1_MEM_RESP_RDY_OK) ^ dmem_req;
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ imem_resp <= SCR1_MEM_RESP_NOTRDY;
+ end else if (imem_req_en) begin
+ imem_resp <= imem_req ? SCR1_MEM_RESP_RDY_OK : SCR1_MEM_RESP_NOTRDY;
+ end
+end
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ dmem_resp <= SCR1_MEM_RESP_NOTRDY;
+ end else if (dmem_req_en) begin
+ dmem_resp <= dmem_req ? SCR1_MEM_RESP_RDY_OK : SCR1_MEM_RESP_NOTRDY;
+ end
+end
+
+assign imem_req_ack = 1'b1;
+assign dmem_req_ack = 1'b1;
+//-------------------------------------------------------------------------------
+// Memory data composing
+//-------------------------------------------------------------------------------
+assign imem_rd = imem_req;
+assign dmem_rd = dmem_req & (dmem_cmd == SCR1_MEM_CMD_RD);
+assign dmem_wr = dmem_req & (dmem_cmd == SCR1_MEM_CMD_WR);
+
+always_comb begin
+ dmem_writedata = dmem_wdata;
+ dmem_byteen = 4'b1111;
+ case ( dmem_width )
+ SCR1_MEM_WIDTH_BYTE : begin
+ dmem_writedata = {(`SCR1_DMEM_DWIDTH / 8){dmem_wdata[7:0]}};
+ dmem_byteen = 4'b0001 << dmem_addr[1:0];
+ end
+ SCR1_MEM_WIDTH_HWORD : begin
+ dmem_writedata = {(`SCR1_DMEM_DWIDTH / 16){dmem_wdata[15:0]}};
+ dmem_byteen = 4'b0011 << {dmem_addr[1], 1'b0};
+ end
+ default : begin
+ end
+ endcase
+end
+//-------------------------------------------------------------------------------
+// Memory instantiation
+//-------------------------------------------------------------------------------
+scr1_dp_memory #(
+ .SCR1_WIDTH ( 32 ),
+ .SCR1_SIZE ( SCR1_TCM_SIZE )
+) i_dp_memory (
+ .clk ( clk ),
+ // Instruction port
+ // Port A
+ .rena ( imem_rd ),
+ .addra ( imem_addr[$clog2(SCR1_TCM_SIZE)-1:2] ),
+ .qa ( imem_rdata ),
+ // Data port
+ // Port B
+ .renb ( dmem_rd ),
+ .wenb ( dmem_wr ),
+ .webb ( dmem_byteen ),
+ .addrb ( dmem_addr[$clog2(SCR1_TCM_SIZE)-1:2] ),
+ .qb ( dmem_rdata_local ),
+ .datab ( dmem_writedata )
+);
+//-------------------------------------------------------------------------------
+// Data memory output generation
+//-------------------------------------------------------------------------------
+always_ff @(posedge clk) begin
+ if (dmem_rd) begin
+ dmem_rdata_shift_reg <= dmem_addr[1:0];
+ end
+end
+
+assign dmem_rdata = dmem_rdata_local >> ( 8 * dmem_rdata_shift_reg );
+
+endmodule : scr1_tcm
+
+`endif // SCR1_TCM_EN
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_timer.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_timer.sv
new file mode 100644
index 0000000..343a93a
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_timer.sv
@@ -0,0 +1,271 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_timer.sv>
+/// @brief Memory-mapped Timer
+///
+
+`include "scr1_arch_description.svh"
+`include "scr1_memif.svh"
+
+module scr1_timer (
+ // Common
+ input logic rst_n,
+ input logic clk,
+ input logic rtc_clk,
+
+ // Memory interface
+ input logic dmem_req,
+ input type_scr1_mem_cmd_e dmem_cmd,
+ input type_scr1_mem_width_e dmem_width,
+ input logic [`SCR1_DMEM_AWIDTH-1:0] dmem_addr,
+ input logic [`SCR1_DMEM_DWIDTH-1:0] dmem_wdata,
+ output logic dmem_req_ack,
+ output logic [`SCR1_DMEM_DWIDTH-1:0] dmem_rdata,
+ output type_scr1_mem_resp_e dmem_resp,
+
+ // Timer interface
+ output logic [63:0] timer_val,
+ output logic timer_irq
+);
+
+//-------------------------------------------------------------------------------
+// Local parameters declaration
+//-------------------------------------------------------------------------------
+localparam int unsigned SCR1_TIMER_ADDR_WIDTH = 5;
+localparam logic [SCR1_TIMER_ADDR_WIDTH-1:0] SCR1_TIMER_CONTROL = 5'h0;
+localparam logic [SCR1_TIMER_ADDR_WIDTH-1:0] SCR1_TIMER_DIVIDER = 5'h4;
+localparam logic [SCR1_TIMER_ADDR_WIDTH-1:0] SCR1_TIMER_MTIMELO = 5'h8;
+localparam logic [SCR1_TIMER_ADDR_WIDTH-1:0] SCR1_TIMER_MTIMEHI = 5'hC;
+localparam logic [SCR1_TIMER_ADDR_WIDTH-1:0] SCR1_TIMER_MTIMECMPLO = 5'h10;
+localparam logic [SCR1_TIMER_ADDR_WIDTH-1:0] SCR1_TIMER_MTIMECMPHI = 5'h14;
+
+localparam int unsigned SCR1_TIMER_CONTROL_EN_OFFSET = 0;
+localparam int unsigned SCR1_TIMER_CONTROL_CLKSRC_OFFSET = 1;
+localparam int unsigned SCR1_TIMER_DIVIDER_WIDTH = 10;
+
+//-------------------------------------------------------------------------------
+// Local signals declaration
+//-------------------------------------------------------------------------------
+logic [63:0] mtime_reg;
+logic [63:0] mtime_new;
+logic [63:0] mtimecmp_reg;
+logic [63:0] mtimecmp_new;
+logic timer_en;
+logic timer_clksrc_rtc;
+logic [SCR1_TIMER_DIVIDER_WIDTH-1:0] timer_div;
+
+logic control_up;
+logic divider_up;
+logic mtimelo_up;
+logic mtimehi_up;
+logic mtimecmplo_up;
+logic mtimecmphi_up;
+
+logic dmem_req_valid;
+
+logic [3:0] rtc_sync;
+logic rtc_ext_pulse;
+logic [SCR1_TIMER_DIVIDER_WIDTH-1:0] timeclk_cnt;
+logic timeclk_cnt_en;
+logic time_posedge;
+logic time_cmp_flag;
+
+//-------------------------------------------------------------------------------
+// Registers
+//-------------------------------------------------------------------------------
+
+// CONTROL
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ timer_en <= 1'b1;
+ timer_clksrc_rtc <= 1'b0;
+ end else begin
+ if (control_up) begin
+ timer_en <= dmem_wdata[SCR1_TIMER_CONTROL_EN_OFFSET];
+ timer_clksrc_rtc <= dmem_wdata[SCR1_TIMER_CONTROL_CLKSRC_OFFSET];
+ end
+ end
+end
+
+// DIVIDER
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ timer_div <= '0;
+ end else begin
+ if (divider_up) begin
+ timer_div <= dmem_wdata[SCR1_TIMER_DIVIDER_WIDTH-1:0];
+ end
+ end
+end
+
+// MTIME
+assign time_posedge = (timeclk_cnt_en & (timeclk_cnt == 0));
+
+always_comb begin
+ mtime_new = mtime_reg;
+ if (time_posedge) begin
+ mtime_new = mtime_reg + 1'b1;
+ end
+ if (mtimelo_up) begin
+ mtime_new[31:0] = dmem_wdata;
+ end
+ if (mtimehi_up) begin
+ mtime_new[63:32] = dmem_wdata;
+ end
+end
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ mtime_reg <= '0;
+ end else begin
+ if (time_posedge | mtimelo_up | mtimehi_up) begin
+ mtime_reg <= mtime_new;
+ end
+ end
+end
+
+// MTIMECMP
+always_comb begin
+ mtimecmp_new = mtimecmp_reg;
+ if (mtimecmplo_up) begin
+ mtimecmp_new[31:0] = dmem_wdata;
+ end
+ if (mtimecmphi_up) begin
+ mtimecmp_new[63:32] = dmem_wdata;
+ end
+end
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ mtimecmp_reg <= '0;
+ end else begin
+ if (mtimecmplo_up | mtimecmphi_up) begin
+ mtimecmp_reg <= mtimecmp_new;
+ end
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Interrupt pending
+//-------------------------------------------------------------------------------
+assign time_cmp_flag = (mtime_reg >= ((mtimecmplo_up | mtimecmphi_up) ? mtimecmp_new : mtimecmp_reg));
+
+always_ff @(posedge clk, negedge rst_n) begin
+ if (~rst_n) begin
+ timer_irq <= 1'b0;
+ end else begin
+ if (~timer_irq) begin
+ timer_irq <= time_cmp_flag;
+ end else begin // 1'b1
+ if (mtimecmplo_up | mtimecmphi_up) begin
+ timer_irq <= time_cmp_flag;
+ end
+ end
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Timer divider
+//-------------------------------------------------------------------------------
+assign timeclk_cnt_en = (~timer_clksrc_rtc ? 1'b1 : rtc_ext_pulse) & timer_en;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ timeclk_cnt <= '0;
+ end else begin
+ case (1'b1)
+ divider_up : timeclk_cnt <= dmem_wdata[SCR1_TIMER_DIVIDER_WIDTH-1:0];
+ time_posedge : timeclk_cnt <= timer_div;
+ timeclk_cnt_en : timeclk_cnt <= timeclk_cnt - 1'b1;
+ default : begin end
+ endcase
+ end
+end
+
+//-------------------------------------------------------------------------------
+// RTC synchronization
+//-------------------------------------------------------------------------------
+assign rtc_ext_pulse = rtc_sync[3] ^ rtc_sync[2];
+
+always_ff @(negedge rst_n, posedge rtc_clk) begin
+ if (~rst_n) begin
+ rtc_sync[0] <= 1'b0;
+ end else begin
+ if (timer_clksrc_rtc) begin
+ rtc_sync[0] <= ~rtc_sync[0];
+ end
+ end
+end
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ rtc_sync[3:1] <= '0;
+ end else begin
+ if (timer_clksrc_rtc) begin
+ rtc_sync[3:1] <= rtc_sync[2:0];
+ end
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Memory interface
+//-------------------------------------------------------------------------------
+assign dmem_req_valid = (dmem_width == SCR1_MEM_WIDTH_WORD) & (~|dmem_addr[1:0]) &
+ (dmem_addr[SCR1_TIMER_ADDR_WIDTH-1:2] <= SCR1_TIMER_MTIMECMPHI[SCR1_TIMER_ADDR_WIDTH-1:2]);
+
+assign dmem_req_ack = 1'b1;
+
+always_ff @(negedge rst_n, posedge clk) begin
+ if (~rst_n) begin
+ dmem_resp <= SCR1_MEM_RESP_NOTRDY;
+ dmem_rdata <= '0;
+ end else begin
+ if (dmem_req) begin
+ if (dmem_req_valid) begin
+ dmem_resp <= SCR1_MEM_RESP_RDY_OK;
+ if (dmem_cmd == SCR1_MEM_CMD_RD) begin
+ case (dmem_addr[SCR1_TIMER_ADDR_WIDTH-1:0])
+ SCR1_TIMER_CONTROL : dmem_rdata <= `SCR1_DMEM_DWIDTH'({timer_clksrc_rtc, timer_en});
+ SCR1_TIMER_DIVIDER : dmem_rdata <= `SCR1_DMEM_DWIDTH'(timer_div);
+ SCR1_TIMER_MTIMELO : dmem_rdata <= mtime_reg[31:0];
+ SCR1_TIMER_MTIMEHI : dmem_rdata <= mtime_reg[63:32];
+ SCR1_TIMER_MTIMECMPLO : dmem_rdata <= mtimecmp_reg[31:0];
+ SCR1_TIMER_MTIMECMPHI : dmem_rdata <= mtimecmp_reg[63:32];
+ default : begin end
+ endcase
+ end
+ end else begin
+ dmem_resp <= SCR1_MEM_RESP_RDY_ER;
+ end
+ end else begin
+ dmem_resp <= SCR1_MEM_RESP_NOTRDY;
+ dmem_rdata <= '0;
+ end
+ end
+end
+
+always_comb begin
+ control_up = 1'b0;
+ divider_up = 1'b0;
+ mtimelo_up = 1'b0;
+ mtimehi_up = 1'b0;
+ mtimecmplo_up = 1'b0;
+ mtimecmphi_up = 1'b0;
+ if (dmem_req & dmem_req_valid & (dmem_cmd == SCR1_MEM_CMD_WR)) begin
+ case (dmem_addr[SCR1_TIMER_ADDR_WIDTH-1:0])
+ SCR1_TIMER_CONTROL : control_up = 1'b1;
+ SCR1_TIMER_DIVIDER : divider_up = 1'b1;
+ SCR1_TIMER_MTIMELO : mtimelo_up = 1'b1;
+ SCR1_TIMER_MTIMEHI : mtimehi_up = 1'b1;
+ SCR1_TIMER_MTIMECMPLO : mtimecmplo_up = 1'b1;
+ SCR1_TIMER_MTIMECMPHI : mtimecmphi_up = 1'b1;
+ default : begin end
+ endcase
+ end
+end
+
+//-------------------------------------------------------------------------------
+// Timer interface
+//-------------------------------------------------------------------------------
+assign timer_val = mtime_reg;
+
+endmodule : scr1_timer
\ No newline at end of file
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_top_ahb.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_top_ahb.sv
new file mode 100644
index 0000000..2268a7d
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_top_ahb.sv
@@ -0,0 +1,513 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_top_ahb.sv>
+/// @brief SCR1 AHB top
+///
+
+`include "scr1_arch_description.svh"
+`include "scr1_memif.svh"
+`include "scr1_ahb.svh"
+`ifdef SCR1_IPIC_EN
+`include "scr1_ipic.svh"
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_TCM_EN
+ `define SCR1_IMEM_ROUTER_EN
+`endif // SCR1_TCM_EN
+
+module scr1_top_ahb (
+ // Control
+ input logic pwrup_rst_n, // Power-Up Reset
+ input logic rst_n, // Regular Reset signal
+ input logic cpu_rst_n, // CPU Reset (Core Reset)
+ input logic test_mode, // Test mode
+ input logic test_rst_n, // Test mode's reset
+ input logic clk, // System clock
+ input logic rtc_clk, // Real-time clock
+`ifdef SCR1_DBG_EN
+ output logic sys_rst_n_o, // External System Reset output
+ // (for the processor cluster's components or
+ // external SOC (could be useful in small
+ // SCR-core-centric SOCs))
+ output logic sys_rdc_qlfy_o, // System-to-External SOC Reset Domain Crossing Qualifier
+`endif // SCR1_DBG_EN
+
+ // Fuses
+ input logic [`SCR1_XLEN-1:0] fuse_mhartid, // Hart ID
+`ifdef SCR1_DBG_EN
+ input logic [31:0] fuse_idcode, // TAPC IDCODE
+`endif // SCR1_DBG_EN
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ input logic [SCR1_IRQ_LINES_NUM-1:0] irq_lines, // IRQ lines to IPIC
+`else // SCR1_IPIC_EN
+ input logic ext_irq, // External IRQ input
+`endif // SCR1_IPIC_EN
+ input logic soft_irq, // Software IRQ input
+
+`ifdef SCR1_DBG_EN
+ // -- JTAG I/F
+ input logic trst_n,
+ input logic tck,
+ input logic tms,
+ input logic tdi,
+ output logic tdo,
+ output logic tdo_en,
+`endif // SCR1_DBG_EN
+
+ // Instruction Memory Interface
+ output logic [3:0] imem_hprot,
+ output logic [2:0] imem_hburst,
+ output logic [2:0] imem_hsize,
+ output logic [1:0] imem_htrans,
+ output logic imem_hmastlock,
+ output logic [SCR1_AHB_WIDTH-1:0] imem_haddr,
+ input logic imem_hready,
+ input logic [SCR1_AHB_WIDTH-1:0] imem_hrdata,
+ input logic imem_hresp,
+
+ // Data Memory Interface
+ output logic [3:0] dmem_hprot,
+ output logic [2:0] dmem_hburst,
+ output logic [2:0] dmem_hsize,
+ output logic [1:0] dmem_htrans,
+ output logic dmem_hmastlock,
+ output logic [SCR1_AHB_WIDTH-1:0] dmem_haddr,
+ output logic dmem_hwrite,
+ output logic [SCR1_AHB_WIDTH-1:0] dmem_hwdata,
+ input logic dmem_hready,
+ input logic [SCR1_AHB_WIDTH-1:0] dmem_hrdata,
+ input logic dmem_hresp
+);
+
+//-------------------------------------------------------------------------------
+// Local parameters
+//-------------------------------------------------------------------------------
+localparam int unsigned SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM = 2;
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+// Reset logic
+logic pwrup_rst_n_sync;
+logic rst_n_sync;
+logic cpu_rst_n_sync;
+logic core_rst_n_local;
+`ifdef SCR1_DBG_EN
+logic tapc_trst_n;
+`endif // SCR1_DBG_EN
+
+// Instruction memory interface from core to router
+logic core_imem_req_ack;
+logic core_imem_req;
+type_scr1_mem_cmd_e core_imem_cmd;
+logic [`SCR1_IMEM_AWIDTH-1:0] core_imem_addr;
+logic [`SCR1_IMEM_DWIDTH-1:0] core_imem_rdata;
+type_scr1_mem_resp_e core_imem_resp;
+
+// Data memory interface from core to router
+logic core_dmem_req_ack;
+logic core_dmem_req;
+type_scr1_mem_cmd_e core_dmem_cmd;
+type_scr1_mem_width_e core_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] core_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] core_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] core_dmem_rdata;
+type_scr1_mem_resp_e core_dmem_resp;
+
+// Instruction memory interface from router to AHB bridge
+logic ahb_imem_req_ack;
+logic ahb_imem_req;
+type_scr1_mem_cmd_e ahb_imem_cmd;
+logic [`SCR1_IMEM_AWIDTH-1:0] ahb_imem_addr;
+logic [`SCR1_IMEM_DWIDTH-1:0] ahb_imem_rdata;
+type_scr1_mem_resp_e ahb_imem_resp;
+
+// Data memory interface from router to AHB bridge
+logic ahb_dmem_req_ack;
+logic ahb_dmem_req;
+type_scr1_mem_cmd_e ahb_dmem_cmd;
+type_scr1_mem_width_e ahb_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] ahb_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] ahb_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] ahb_dmem_rdata;
+type_scr1_mem_resp_e ahb_dmem_resp;
+
+`ifdef SCR1_TCM_EN
+// Instruction memory interface from router to TCM
+logic tcm_imem_req_ack;
+logic tcm_imem_req;
+type_scr1_mem_cmd_e tcm_imem_cmd;
+logic [`SCR1_IMEM_AWIDTH-1:0] tcm_imem_addr;
+logic [`SCR1_IMEM_DWIDTH-1:0] tcm_imem_rdata;
+type_scr1_mem_resp_e tcm_imem_resp;
+
+// Data memory interface from router to TCM
+logic tcm_dmem_req_ack;
+logic tcm_dmem_req;
+type_scr1_mem_cmd_e tcm_dmem_cmd;
+type_scr1_mem_width_e tcm_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] tcm_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] tcm_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] tcm_dmem_rdata;
+type_scr1_mem_resp_e tcm_dmem_resp;
+`endif // SCR1_TCM_EN
+
+// Data memory interface from router to memory-mapped timer
+logic timer_dmem_req_ack;
+logic timer_dmem_req;
+type_scr1_mem_cmd_e timer_dmem_cmd;
+type_scr1_mem_width_e timer_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] timer_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] timer_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] timer_dmem_rdata;
+type_scr1_mem_resp_e timer_dmem_resp;
+
+logic timer_irq;
+logic [63:0] timer_val;
+
+
+//-------------------------------------------------------------------------------
+// Reset logic
+//-------------------------------------------------------------------------------
+// Power-Up Reset synchronizer
+scr1_reset_sync_cell #(
+ .STAGES_AMOUNT (SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM)
+) i_pwrup_rstn_reset_sync (
+ .rst_n (pwrup_rst_n ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_in (1'b1 ),
+ .rst_n_out (pwrup_rst_n_sync)
+);
+
+// Regular Reset synchronizer
+scr1_reset_sync_cell #(
+ .STAGES_AMOUNT (SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM)
+) i_rstn_reset_sync (
+ .rst_n (pwrup_rst_n ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_in (rst_n ),
+ .rst_n_out (rst_n_sync )
+);
+
+// CPU Reset synchronizer
+scr1_reset_sync_cell #(
+ .STAGES_AMOUNT (SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM)
+) i_cpu_rstn_reset_sync (
+ .rst_n (pwrup_rst_n ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_in (cpu_rst_n ),
+ .rst_n_out (cpu_rst_n_sync )
+);
+
+`ifdef SCR1_DBG_EN
+// TAPC Reset
+scr1_reset_and2_cell i_tapc_rstn_and2_cell (
+ .rst_n_in ({trst_n, pwrup_rst_n}),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_out (tapc_trst_n )
+);
+`endif // SCR1_DBG_EN
+
+//-------------------------------------------------------------------------------
+// SCR1 core instance
+//-------------------------------------------------------------------------------
+scr1_core_top i_core_top (
+ // Common
+ .pwrup_rst_n (pwrup_rst_n_sync ),
+ .rst_n (rst_n_sync ),
+ .cpu_rst_n (cpu_rst_n_sync ),
+ .test_mode (test_mode ),
+ .test_rst_n (test_rst_n ),
+ .clk (clk ),
+ .core_rst_n_o (core_rst_n_local ),
+ .core_rdc_qlfy_o ( ),
+`ifdef SCR1_DBG_EN
+ .sys_rst_n_o (sys_rst_n_o ),
+ .sys_rdc_qlfy_o (sys_rdc_qlfy_o ),
+`endif // SCR1_DBG_EN
+
+ // Fuses
+ .core_fuse_mhartid_i (fuse_mhartid ),
+`ifdef SCR1_DBG_EN
+ .tapc_fuse_idcode_i (fuse_idcode ),
+`endif // SCR1_DBG_EN
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ .core_irq_lines_i (irq_lines ),
+`else // SCR1_IPIC_EN
+ .core_irq_ext_i (ext_irq ),
+`endif // SCR1_IPIC_EN
+ .core_irq_soft_i (soft_irq ),
+ .core_irq_mtimer_i (timer_irq ),
+
+ // Memory-mapped external timer
+ .core_mtimer_val_i (timer_val ),
+
+`ifdef SCR1_DBG_EN
+ // Debug interface
+ .tapc_trst_n (tapc_trst_n ),
+ .tapc_tck (tck ),
+ .tapc_tms (tms ),
+ .tapc_tdi (tdi ),
+ .tapc_tdo (tdo ),
+ .tapc_tdo_en (tdo_en ),
+`endif // SCR1_DBG_EN
+
+ // Instruction memory interface
+ .imem2core_req_ack_i (core_imem_req_ack),
+ .core2imem_req_o (core_imem_req ),
+ .core2imem_cmd_o (core_imem_cmd ),
+ .core2imem_addr_o (core_imem_addr ),
+ .imem2core_rdata_i (core_imem_rdata ),
+ .imem2core_resp_i (core_imem_resp ),
+
+ // Data memory interface
+ .dmem2core_req_ack_i (core_dmem_req_ack),
+ .core2dmem_req_o (core_dmem_req ),
+ .core2dmem_cmd_o (core_dmem_cmd ),
+ .core2dmem_width_o (core_dmem_width ),
+ .core2dmem_addr_o (core_dmem_addr ),
+ .core2dmem_wdata_o (core_dmem_wdata ),
+ .dmem2core_rdata_i (core_dmem_rdata ),
+ .dmem2core_resp_i (core_dmem_resp )
+);
+
+
+`ifdef SCR1_TCM_EN
+//-------------------------------------------------------------------------------
+// TCM instance
+//-------------------------------------------------------------------------------
+scr1_tcm #(
+ .SCR1_TCM_SIZE (`SCR1_DMEM_AWIDTH'(~SCR1_TCM_ADDR_MASK + 1'b1))
+) i_tcm (
+ .clk (clk ),
+ .rst_n (core_rst_n_local),
+
+ // Instruction interface to TCM
+ .imem_req_ack (tcm_imem_req_ack),
+ .imem_req (tcm_imem_req ),
+ .imem_addr (tcm_imem_addr ),
+ .imem_rdata (tcm_imem_rdata ),
+ .imem_resp (tcm_imem_resp ),
+
+ // Data interface to TCM
+ .dmem_req_ack (tcm_dmem_req_ack),
+ .dmem_req (tcm_dmem_req ),
+ .dmem_cmd (tcm_dmem_cmd ),
+ .dmem_width (tcm_dmem_width ),
+ .dmem_addr (tcm_dmem_addr ),
+ .dmem_wdata (tcm_dmem_wdata ),
+ .dmem_rdata (tcm_dmem_rdata ),
+ .dmem_resp (tcm_dmem_resp )
+);
+`endif // SCR1_TCM_EN
+
+
+//-------------------------------------------------------------------------------
+// Memory-mapped timer instance
+//-------------------------------------------------------------------------------
+scr1_timer i_timer (
+ // Common
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+ .rtc_clk (rtc_clk ),
+
+ // Memory interface
+ .dmem_req (timer_dmem_req ),
+ .dmem_cmd (timer_dmem_cmd ),
+ .dmem_width (timer_dmem_width ),
+ .dmem_addr (timer_dmem_addr ),
+ .dmem_wdata (timer_dmem_wdata ),
+ .dmem_req_ack (timer_dmem_req_ack),
+ .dmem_rdata (timer_dmem_rdata ),
+ .dmem_resp (timer_dmem_resp ),
+
+ // Timer interface
+ .timer_val (timer_val ),
+ .timer_irq (timer_irq )
+);
+
+
+`ifdef SCR1_IMEM_ROUTER_EN
+//-------------------------------------------------------------------------------
+// Instruction memory router
+//-------------------------------------------------------------------------------
+scr1_imem_router #(
+ `ifdef SCR1_TCM_EN
+ .SCR1_ADDR_MASK (SCR1_TCM_ADDR_MASK),
+ .SCR1_ADDR_PATTERN (SCR1_TCM_ADDR_PATTERN)
+ `endif // SCR1_TCM_EN
+) i_imem_router (
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+ // Interface to core
+ .imem_req_ack (core_imem_req_ack),
+ .imem_req (core_imem_req ),
+ .imem_cmd (core_imem_cmd ),
+ .imem_addr (core_imem_addr ),
+ .imem_rdata (core_imem_rdata ),
+ .imem_resp (core_imem_resp ),
+ // Interface to AHB bridge
+ .port0_req_ack (ahb_imem_req_ack ),
+ .port0_req (ahb_imem_req ),
+ .port0_cmd (ahb_imem_cmd ),
+ .port0_addr (ahb_imem_addr ),
+ .port0_rdata (ahb_imem_rdata ),
+ .port0_resp (ahb_imem_resp ),
+ `ifdef SCR1_TCM_EN
+ // Interface to TCM
+ .port1_req_ack (tcm_imem_req_ack ),
+ .port1_req (tcm_imem_req ),
+ .port1_cmd (tcm_imem_cmd ),
+ .port1_addr (tcm_imem_addr ),
+ .port1_rdata (tcm_imem_rdata ),
+ .port1_resp (tcm_imem_resp )
+ `endif // SCR1_TCM_EN
+);
+
+`else // SCR1_IMEM_ROUTER_EN
+
+assign ahb_imem_req = core_imem_req;
+assign ahb_imem_cmd = core_imem_cmd;
+assign ahb_imem_addr = core_imem_addr;
+assign core_imem_req_ack = ahb_imem_req_ack;
+assign core_imem_resp = ahb_imem_resp;
+assign core_imem_rdata = ahb_imem_rdata;
+
+`endif // SCR1_IMEM_ROUTER_EN
+
+//-------------------------------------------------------------------------------
+// Data memory router
+//-------------------------------------------------------------------------------
+scr1_dmem_router #(
+
+`ifdef SCR1_TCM_EN
+ .SCR1_PORT1_ADDR_MASK (SCR1_TCM_ADDR_MASK),
+ .SCR1_PORT1_ADDR_PATTERN (SCR1_TCM_ADDR_PATTERN),
+`else // SCR1_TCM_EN
+ .SCR1_PORT1_ADDR_MASK (32'h00000000),
+ .SCR1_PORT1_ADDR_PATTERN (32'hFFFFFFFF),
+`endif // SCR1_TCM_EN
+
+ .SCR1_PORT2_ADDR_MASK (SCR1_TIMER_ADDR_MASK),
+ .SCR1_PORT2_ADDR_PATTERN (SCR1_TIMER_ADDR_PATTERN)
+
+) i_dmem_router (
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+ // Interface to core
+ .dmem_req_ack (core_dmem_req_ack ),
+ .dmem_req (core_dmem_req ),
+ .dmem_cmd (core_dmem_cmd ),
+ .dmem_width (core_dmem_width ),
+ .dmem_addr (core_dmem_addr ),
+ .dmem_wdata (core_dmem_wdata ),
+ .dmem_rdata (core_dmem_rdata ),
+ .dmem_resp (core_dmem_resp ),
+`ifdef SCR1_TCM_EN
+ // Interface to TCM
+ .port1_req_ack (tcm_dmem_req_ack ),
+ .port1_req (tcm_dmem_req ),
+ .port1_cmd (tcm_dmem_cmd ),
+ .port1_width (tcm_dmem_width ),
+ .port1_addr (tcm_dmem_addr ),
+ .port1_wdata (tcm_dmem_wdata ),
+ .port1_rdata (tcm_dmem_rdata ),
+ .port1_resp (tcm_dmem_resp ),
+`else // SCR1_TCM_EN
+ .port1_req_ack (1'b0),
+ .port1_req ( ),
+ .port1_cmd ( ),
+ .port1_width ( ),
+ .port1_addr ( ),
+ .port1_wdata ( ),
+ .port1_rdata ('0 ),
+ .port1_resp (SCR1_MEM_RESP_RDY_ER),
+`endif // SCR1_TCM_EN
+ // Interface to memory-mapped timer
+ .port2_req_ack (timer_dmem_req_ack ),
+ .port2_req (timer_dmem_req ),
+ .port2_cmd (timer_dmem_cmd ),
+ .port2_width (timer_dmem_width ),
+ .port2_addr (timer_dmem_addr ),
+ .port2_wdata (timer_dmem_wdata ),
+ .port2_rdata (timer_dmem_rdata ),
+ .port2_resp (timer_dmem_resp ),
+ // Interface to AHB bridge
+ .port0_req_ack (ahb_dmem_req_ack ),
+ .port0_req (ahb_dmem_req ),
+ .port0_cmd (ahb_dmem_cmd ),
+ .port0_width (ahb_dmem_width ),
+ .port0_addr (ahb_dmem_addr ),
+ .port0_wdata (ahb_dmem_wdata ),
+ .port0_rdata (ahb_dmem_rdata ),
+ .port0_resp (ahb_dmem_resp )
+);
+
+
+//-------------------------------------------------------------------------------
+// Instruction memory AHB bridge
+//-------------------------------------------------------------------------------
+scr1_imem_ahb i_imem_ahb (
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+ // Interface to imem router
+ .imem_req_ack (ahb_imem_req_ack ),
+ .imem_req (ahb_imem_req ),
+ .imem_addr (ahb_imem_addr ),
+ .imem_rdata (ahb_imem_rdata ),
+ .imem_resp (ahb_imem_resp ),
+ // AHB interface
+ .hprot (imem_hprot ),
+ .hburst (imem_hburst ),
+ .hsize (imem_hsize ),
+ .htrans (imem_htrans ),
+ .hmastlock (imem_hmastlock ),
+ .haddr (imem_haddr ),
+ .hready (imem_hready ),
+ .hrdata (imem_hrdata ),
+ .hresp (imem_hresp )
+);
+
+
+//-------------------------------------------------------------------------------
+// Data memory AHB bridge
+//-------------------------------------------------------------------------------
+scr1_dmem_ahb i_dmem_ahb (
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+ // Interface to dmem router
+ .dmem_req_ack (ahb_dmem_req_ack ),
+ .dmem_req (ahb_dmem_req ),
+ .dmem_cmd (ahb_dmem_cmd ),
+ .dmem_width (ahb_dmem_width ),
+ .dmem_addr (ahb_dmem_addr ),
+ .dmem_wdata (ahb_dmem_wdata ),
+ .dmem_rdata (ahb_dmem_rdata ),
+ .dmem_resp (ahb_dmem_resp ),
+ // AHB interface
+ .hprot (dmem_hprot ),
+ .hburst (dmem_hburst ),
+ .hsize (dmem_hsize ),
+ .htrans (dmem_htrans ),
+ .hmastlock (dmem_hmastlock ),
+ .haddr (dmem_haddr ),
+ .hwrite (dmem_hwrite ),
+ .hwdata (dmem_hwdata ),
+ .hready (dmem_hready ),
+ .hrdata (dmem_hrdata ),
+ .hresp (dmem_hresp )
+);
+
+endmodule : scr1_top_ahb
+
+
diff --git a/verilog/rtl/syntacore_scr1/src/top/scr1_top_axi.sv b/verilog/rtl/syntacore_scr1/src/top/scr1_top_axi.sv
new file mode 100644
index 0000000..735b902
--- /dev/null
+++ b/verilog/rtl/syntacore_scr1/src/top/scr1_top_axi.sv
@@ -0,0 +1,701 @@
+/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
+/// @file <scr1_top_axi.sv>
+/// @brief SCR1 AXI top
+///
+
+`include "scr1_arch_description.svh"
+`include "scr1_memif.svh"
+`ifdef SCR1_IPIC_EN
+`include "scr1_ipic.svh"
+`endif // SCR1_IPIC_EN
+
+`ifdef SCR1_TCM_EN
+ `define SCR1_IMEM_ROUTER_EN
+`endif // SCR1_TCM_EN
+
+module scr1_top_axi (
+ // Control
+ input logic pwrup_rst_n, // Power-Up Reset
+ input logic rst_n, // Regular Reset signal
+ input logic cpu_rst_n, // CPU Reset (Core Reset)
+ input logic test_mode, // Test mode
+ input logic test_rst_n, // Test mode's reset
+ input logic clk, // System clock
+ input logic rtc_clk, // Real-time clock
+`ifdef SCR1_DBG_EN
+ output logic sys_rst_n_o, // External System Reset output
+ // (for the processor cluster's components or
+ // external SOC (could be useful in small
+ // SCR-core-centric SOCs))
+ output logic sys_rdc_qlfy_o, // System-to-External SOC Reset Domain Crossing Qualifier
+`endif // SCR1_DBG_EN
+
+ // Fuses
+ input logic [`SCR1_XLEN-1:0] fuse_mhartid, // Hart ID
+`ifdef SCR1_DBG_EN
+ input logic [31:0] fuse_idcode, // TAPC IDCODE
+`endif // SCR1_DBG_EN
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ input logic [SCR1_IRQ_LINES_NUM-1:0] irq_lines, // IRQ lines to IPIC
+`else // SCR1_IPIC_EN
+ input logic ext_irq, // External IRQ input
+`endif // SCR1_IPIC_EN
+ input logic soft_irq, // Software IRQ input
+
+`ifdef SCR1_DBG_EN
+ // -- JTAG I/F
+ input logic trst_n,
+ input logic tck,
+ input logic tms,
+ input logic tdi,
+ output logic tdo,
+ output logic tdo_en,
+`endif // SCR1_DBG_EN
+
+ // Instruction Memory Interface
+ output logic [3:0] io_axi_imem_awid,
+ output logic [31:0] io_axi_imem_awaddr,
+ output logic [7:0] io_axi_imem_awlen,
+ output logic [2:0] io_axi_imem_awsize,
+ output logic [1:0] io_axi_imem_awburst,
+ output logic io_axi_imem_awlock,
+ output logic [3:0] io_axi_imem_awcache,
+ output logic [2:0] io_axi_imem_awprot,
+ output logic [3:0] io_axi_imem_awregion,
+ output logic [3:0] io_axi_imem_awuser,
+ output logic [3:0] io_axi_imem_awqos,
+ output logic io_axi_imem_awvalid,
+ input logic io_axi_imem_awready,
+ output logic [31:0] io_axi_imem_wdata,
+ output logic [3:0] io_axi_imem_wstrb,
+ output logic io_axi_imem_wlast,
+ output logic [3:0] io_axi_imem_wuser,
+ output logic io_axi_imem_wvalid,
+ input logic io_axi_imem_wready,
+ input logic [3:0] io_axi_imem_bid,
+ input logic [1:0] io_axi_imem_bresp,
+ input logic io_axi_imem_bvalid,
+ input logic [3:0] io_axi_imem_buser,
+ output logic io_axi_imem_bready,
+ output logic [3:0] io_axi_imem_arid,
+ output logic [31:0] io_axi_imem_araddr,
+ output logic [7:0] io_axi_imem_arlen,
+ output logic [2:0] io_axi_imem_arsize,
+ output logic [1:0] io_axi_imem_arburst,
+ output logic io_axi_imem_arlock,
+ output logic [3:0] io_axi_imem_arcache,
+ output logic [2:0] io_axi_imem_arprot,
+ output logic [3:0] io_axi_imem_arregion,
+ output logic [3:0] io_axi_imem_aruser,
+ output logic [3:0] io_axi_imem_arqos,
+ output logic io_axi_imem_arvalid,
+ input logic io_axi_imem_arready,
+ input logic [3:0] io_axi_imem_rid,
+ input logic [31:0] io_axi_imem_rdata,
+ input logic [1:0] io_axi_imem_rresp,
+ input logic io_axi_imem_rlast,
+ input logic [3:0] io_axi_imem_ruser,
+ input logic io_axi_imem_rvalid,
+ output logic io_axi_imem_rready,
+
+ // Data Memory Interface
+ output logic [3:0] io_axi_dmem_awid,
+ output logic [31:0] io_axi_dmem_awaddr,
+ output logic [7:0] io_axi_dmem_awlen,
+ output logic [2:0] io_axi_dmem_awsize,
+ output logic [1:0] io_axi_dmem_awburst,
+ output logic io_axi_dmem_awlock,
+ output logic [3:0] io_axi_dmem_awcache,
+ output logic [2:0] io_axi_dmem_awprot,
+ output logic [3:0] io_axi_dmem_awregion,
+ output logic [3:0] io_axi_dmem_awuser,
+ output logic [3:0] io_axi_dmem_awqos,
+ output logic io_axi_dmem_awvalid,
+ input logic io_axi_dmem_awready,
+ output logic [31:0] io_axi_dmem_wdata,
+ output logic [3:0] io_axi_dmem_wstrb,
+ output logic io_axi_dmem_wlast,
+ output logic [3:0] io_axi_dmem_wuser,
+ output logic io_axi_dmem_wvalid,
+ input logic io_axi_dmem_wready,
+ input logic [3:0] io_axi_dmem_bid,
+ input logic [1:0] io_axi_dmem_bresp,
+ input logic io_axi_dmem_bvalid,
+ input logic [3:0] io_axi_dmem_buser,
+ output logic io_axi_dmem_bready,
+ output logic [3:0] io_axi_dmem_arid,
+ output logic [31:0] io_axi_dmem_araddr,
+ output logic [7:0] io_axi_dmem_arlen,
+ output logic [2:0] io_axi_dmem_arsize,
+ output logic [1:0] io_axi_dmem_arburst,
+ output logic io_axi_dmem_arlock,
+ output logic [3:0] io_axi_dmem_arcache,
+ output logic [2:0] io_axi_dmem_arprot,
+ output logic [3:0] io_axi_dmem_arregion,
+ output logic [3:0] io_axi_dmem_aruser,
+ output logic [3:0] io_axi_dmem_arqos,
+ output logic io_axi_dmem_arvalid,
+ input logic io_axi_dmem_arready,
+ input logic [3:0] io_axi_dmem_rid,
+ input logic [31:0] io_axi_dmem_rdata,
+ input logic [1:0] io_axi_dmem_rresp,
+ input logic io_axi_dmem_rlast,
+ input logic [3:0] io_axi_dmem_ruser,
+ input logic io_axi_dmem_rvalid,
+ output logic io_axi_dmem_rready
+);
+
+//-------------------------------------------------------------------------------
+// Local parameters
+//-------------------------------------------------------------------------------
+localparam int unsigned SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM = 2;
+
+//-------------------------------------------------------------------------------
+// Local signal declaration
+//-------------------------------------------------------------------------------
+// Reset logic
+logic pwrup_rst_n_sync;
+logic rst_n_sync;
+logic cpu_rst_n_sync;
+logic core_rst_n_local;
+logic axi_rst_n;
+`ifdef SCR1_DBG_EN
+logic tapc_trst_n;
+`endif // SCR1_DBG_EN
+
+// Instruction memory interface from core to router
+logic core_imem_req_ack;
+logic core_imem_req;
+type_scr1_mem_cmd_e core_imem_cmd;
+logic [`SCR1_IMEM_AWIDTH-1:0] core_imem_addr;
+logic [`SCR1_IMEM_DWIDTH-1:0] core_imem_rdata;
+type_scr1_mem_resp_e core_imem_resp;
+
+// Data memory interface from core to router
+logic core_dmem_req_ack;
+logic core_dmem_req;
+type_scr1_mem_cmd_e core_dmem_cmd;
+type_scr1_mem_width_e core_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] core_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] core_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] core_dmem_rdata;
+type_scr1_mem_resp_e core_dmem_resp;
+
+// Instruction memory interface from router to AXI bridge
+logic axi_imem_req_ack;
+logic axi_imem_req;
+type_scr1_mem_cmd_e axi_imem_cmd;
+logic [`SCR1_IMEM_AWIDTH-1:0] axi_imem_addr;
+logic [`SCR1_IMEM_DWIDTH-1:0] axi_imem_rdata;
+type_scr1_mem_resp_e axi_imem_resp;
+
+// Data memory interface from router to AXI bridge
+logic axi_dmem_req_ack;
+logic axi_dmem_req;
+type_scr1_mem_cmd_e axi_dmem_cmd;
+type_scr1_mem_width_e axi_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] axi_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] axi_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] axi_dmem_rdata;
+type_scr1_mem_resp_e axi_dmem_resp;
+
+`ifdef SCR1_TCM_EN
+// Instruction memory interface from router to TCM
+logic tcm_imem_req_ack;
+logic tcm_imem_req;
+type_scr1_mem_cmd_e tcm_imem_cmd;
+logic [`SCR1_IMEM_AWIDTH-1:0] tcm_imem_addr;
+logic [`SCR1_IMEM_DWIDTH-1:0] tcm_imem_rdata;
+type_scr1_mem_resp_e tcm_imem_resp;
+
+// Data memory interface from router to TCM
+logic tcm_dmem_req_ack;
+logic tcm_dmem_req;
+type_scr1_mem_cmd_e tcm_dmem_cmd;
+type_scr1_mem_width_e tcm_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] tcm_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] tcm_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] tcm_dmem_rdata;
+type_scr1_mem_resp_e tcm_dmem_resp;
+`endif // SCR1_TCM_EN
+
+// Data memory interface from router to memory-mapped timer
+logic timer_dmem_req_ack;
+logic timer_dmem_req;
+type_scr1_mem_cmd_e timer_dmem_cmd;
+type_scr1_mem_width_e timer_dmem_width;
+logic [`SCR1_DMEM_AWIDTH-1:0] timer_dmem_addr;
+logic [`SCR1_DMEM_DWIDTH-1:0] timer_dmem_wdata;
+logic [`SCR1_DMEM_DWIDTH-1:0] timer_dmem_rdata;
+type_scr1_mem_resp_e timer_dmem_resp;
+
+// Misc
+logic timer_irq;
+logic [63:0] timer_val;
+logic axi_reinit;
+logic axi_imem_idle;
+logic axi_dmem_idle;
+
+//-------------------------------------------------------------------------------
+// Reset logic
+//-------------------------------------------------------------------------------
+// Power-Up Reset synchronizer
+scr1_reset_sync_cell #(
+ .STAGES_AMOUNT (SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM)
+) i_pwrup_rstn_reset_sync (
+ .rst_n (pwrup_rst_n ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_in (1'b1 ),
+ .rst_n_out (pwrup_rst_n_sync)
+);
+
+// Regular Reset synchronizer
+scr1_reset_sync_cell #(
+ .STAGES_AMOUNT (SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM)
+) i_rstn_reset_sync (
+ .rst_n (pwrup_rst_n ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_in (rst_n ),
+ .rst_n_out (rst_n_sync )
+);
+
+// CPU Reset synchronizer
+scr1_reset_sync_cell #(
+ .STAGES_AMOUNT (SCR1_CLUSTER_TOP_RST_SYNC_STAGES_NUM)
+) i_cpu_rstn_reset_sync (
+ .rst_n (pwrup_rst_n ),
+ .clk (clk ),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_in (cpu_rst_n ),
+ .rst_n_out (cpu_rst_n_sync )
+);
+
+`ifdef SCR1_DBG_EN
+// TAPC Reset
+scr1_reset_and2_cell i_tapc_rstn_and2_cell (
+ .rst_n_in ({trst_n, pwrup_rst_n}),
+ .test_rst_n (test_rst_n ),
+ .test_mode (test_mode ),
+ .rst_n_out (tapc_trst_n )
+);
+`endif // SCR1_DBG_EN
+
+`ifdef SCR1_DBG_EN
+assign axi_rst_n = sys_rst_n_o;
+`else // SCR1_DBG_EN
+assign axi_rst_n = rst_n_sync;
+`endif // SCR1_DBG_EN
+
+//-------------------------------------------------------------------------------
+// SCR1 core instance
+//-------------------------------------------------------------------------------
+scr1_core_top i_core_top (
+ // Common
+ .pwrup_rst_n (pwrup_rst_n_sync ),
+ .rst_n (rst_n_sync ),
+ .cpu_rst_n (cpu_rst_n_sync ),
+ .test_mode (test_mode ),
+ .test_rst_n (test_rst_n ),
+ .clk (clk ),
+ .core_rst_n_o (core_rst_n_local ),
+ .core_rdc_qlfy_o ( ),
+`ifdef SCR1_DBG_EN
+ .sys_rst_n_o (sys_rst_n_o ),
+ .sys_rdc_qlfy_o (sys_rdc_qlfy_o ),
+`endif // SCR1_DBG_EN
+
+ // Fuses
+ .core_fuse_mhartid_i (fuse_mhartid ),
+`ifdef SCR1_DBG_EN
+ .tapc_fuse_idcode_i (fuse_idcode ),
+`endif // SCR1_DBG_EN
+
+ // IRQ
+`ifdef SCR1_IPIC_EN
+ .core_irq_lines_i (irq_lines ),
+`else // SCR1_IPIC_EN
+ .core_irq_ext_i (ext_irq ),
+`endif // SCR1_IPIC_EN
+ .core_irq_soft_i (soft_irq ),
+ .core_irq_mtimer_i (timer_irq ),
+
+ // Memory-mapped external timer
+ .core_mtimer_val_i (timer_val ),
+
+`ifdef SCR1_DBG_EN
+ // Debug interface
+ .tapc_trst_n (tapc_trst_n ),
+ .tapc_tck (tck ),
+ .tapc_tms (tms ),
+ .tapc_tdi (tdi ),
+ .tapc_tdo (tdo ),
+ .tapc_tdo_en (tdo_en ),
+`endif // SCR1_DBG_EN
+
+ // Instruction memory interface
+ .imem2core_req_ack_i (core_imem_req_ack),
+ .core2imem_req_o (core_imem_req ),
+ .core2imem_cmd_o (core_imem_cmd ),
+ .core2imem_addr_o (core_imem_addr ),
+ .imem2core_rdata_i (core_imem_rdata ),
+ .imem2core_resp_i (core_imem_resp ),
+
+ // Data memory interface
+ .dmem2core_req_ack_i (core_dmem_req_ack),
+ .core2dmem_req_o (core_dmem_req ),
+ .core2dmem_cmd_o (core_dmem_cmd ),
+ .core2dmem_width_o (core_dmem_width ),
+ .core2dmem_addr_o (core_dmem_addr ),
+ .core2dmem_wdata_o (core_dmem_wdata ),
+ .dmem2core_rdata_i (core_dmem_rdata ),
+ .dmem2core_resp_i (core_dmem_resp )
+);
+
+
+`ifdef SCR1_TCM_EN
+//-------------------------------------------------------------------------------
+// TCM instance
+//-------------------------------------------------------------------------------
+scr1_tcm #(
+ .SCR1_TCM_SIZE (`SCR1_DMEM_AWIDTH'(~SCR1_TCM_ADDR_MASK + 1'b1))
+) i_tcm (
+ .clk (clk ),
+ .rst_n (core_rst_n_local),
+
+ // Instruction interface to TCM
+ .imem_req_ack (tcm_imem_req_ack),
+ .imem_req (tcm_imem_req ),
+ .imem_addr (tcm_imem_addr ),
+ .imem_rdata (tcm_imem_rdata ),
+ .imem_resp (tcm_imem_resp ),
+
+ // Data interface to TCM
+ .dmem_req_ack (tcm_dmem_req_ack),
+ .dmem_req (tcm_dmem_req ),
+ .dmem_cmd (tcm_dmem_cmd ),
+ .dmem_width (tcm_dmem_width ),
+ .dmem_addr (tcm_dmem_addr ),
+ .dmem_wdata (tcm_dmem_wdata ),
+ .dmem_rdata (tcm_dmem_rdata ),
+ .dmem_resp (tcm_dmem_resp )
+);
+`endif // SCR1_TCM_EN
+
+
+//-------------------------------------------------------------------------------
+// Memory-mapped timer instance
+//-------------------------------------------------------------------------------
+scr1_timer i_timer (
+ // Common
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+ .rtc_clk (rtc_clk ),
+
+ // Memory interface
+ .dmem_req (timer_dmem_req ),
+ .dmem_cmd (timer_dmem_cmd ),
+ .dmem_width (timer_dmem_width ),
+ .dmem_addr (timer_dmem_addr ),
+ .dmem_wdata (timer_dmem_wdata ),
+ .dmem_req_ack (timer_dmem_req_ack),
+ .dmem_rdata (timer_dmem_rdata ),
+ .dmem_resp (timer_dmem_resp ),
+
+ // Timer interface
+ .timer_val (timer_val ),
+ .timer_irq (timer_irq )
+);
+
+
+`ifdef SCR1_IMEM_ROUTER_EN
+//-------------------------------------------------------------------------------
+// Instruction memory router
+//-------------------------------------------------------------------------------
+scr1_imem_router #(
+ .SCR1_ADDR_MASK (SCR1_TCM_ADDR_MASK),
+ .SCR1_ADDR_PATTERN (SCR1_TCM_ADDR_PATTERN)
+) i_imem_router (
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+
+ // Interface to core
+ .imem_req_ack (core_imem_req_ack),
+ .imem_req (core_imem_req ),
+ .imem_cmd (core_imem_cmd ),
+ .imem_addr (core_imem_addr ),
+ .imem_rdata (core_imem_rdata ),
+ .imem_resp (core_imem_resp ),
+
+ // Interface to AXI bridge
+ .port0_req_ack (axi_imem_req_ack ),
+ .port0_req (axi_imem_req ),
+ .port0_cmd (axi_imem_cmd ),
+ .port0_addr (axi_imem_addr ),
+ .port0_rdata (axi_imem_rdata ),
+ .port0_resp (axi_imem_resp ),
+
+ // Interface to TCM
+ .port1_req_ack (tcm_imem_req_ack ),
+ .port1_req (tcm_imem_req ),
+ .port1_cmd (tcm_imem_cmd ),
+ .port1_addr (tcm_imem_addr ),
+ .port1_rdata (tcm_imem_rdata ),
+ .port1_resp (tcm_imem_resp )
+);
+
+`else // SCR1_IMEM_ROUTER_EN
+
+assign axi_imem_req = core_imem_req;
+assign axi_imem_cmd = core_imem_cmd;
+assign axi_imem_addr = core_imem_addr;
+assign core_imem_req_ack = axi_imem_req_ack;
+assign core_imem_resp = axi_imem_resp;
+assign core_imem_rdata = axi_imem_rdata;
+
+`endif // SCR1_IMEM_ROUTER_EN
+
+
+//-------------------------------------------------------------------------------
+// Data memory router
+//-------------------------------------------------------------------------------
+scr1_dmem_router #(
+
+`ifdef SCR1_TCM_EN
+ .SCR1_PORT1_ADDR_MASK (SCR1_TCM_ADDR_MASK),
+ .SCR1_PORT1_ADDR_PATTERN (SCR1_TCM_ADDR_PATTERN),
+`else // SCR1_TCM_EN
+ .SCR1_PORT1_ADDR_MASK (32'h00000000),
+ .SCR1_PORT1_ADDR_PATTERN (32'hFFFFFFFF),
+`endif // SCR1_TCM_EN
+
+ .SCR1_PORT2_ADDR_MASK (SCR1_TIMER_ADDR_MASK),
+ .SCR1_PORT2_ADDR_PATTERN (SCR1_TIMER_ADDR_PATTERN)
+
+) i_dmem_router (
+ .rst_n (core_rst_n_local ),
+ .clk (clk ),
+
+ // Interface to core
+ .dmem_req_ack (core_dmem_req_ack ),
+ .dmem_req (core_dmem_req ),
+ .dmem_cmd (core_dmem_cmd ),
+ .dmem_width (core_dmem_width ),
+ .dmem_addr (core_dmem_addr ),
+ .dmem_wdata (core_dmem_wdata ),
+ .dmem_rdata (core_dmem_rdata ),
+ .dmem_resp (core_dmem_resp ),
+
+`ifdef SCR1_TCM_EN
+ // Interface to TCM
+ .port1_req_ack (tcm_dmem_req_ack ),
+ .port1_req (tcm_dmem_req ),
+ .port1_cmd (tcm_dmem_cmd ),
+ .port1_width (tcm_dmem_width ),
+ .port1_addr (tcm_dmem_addr ),
+ .port1_wdata (tcm_dmem_wdata ),
+ .port1_rdata (tcm_dmem_rdata ),
+ .port1_resp (tcm_dmem_resp ),
+`else // SCR1_TCM_EN
+ .port1_req_ack (1'b0 ),
+ .port1_req ( ),
+ .port1_cmd ( ),
+ .port1_width ( ),
+ .port1_addr ( ),
+ .port1_wdata ( ),
+ .port1_rdata ('0 ),
+ .port1_resp (SCR1_MEM_RESP_RDY_ER),
+`endif // SCR1_TCM_EN
+
+ // Interface to memory-mapped timer
+ .port2_req_ack (timer_dmem_req_ack ),
+ .port2_req (timer_dmem_req ),
+ .port2_cmd (timer_dmem_cmd ),
+ .port2_width (timer_dmem_width ),
+ .port2_addr (timer_dmem_addr ),
+ .port2_wdata (timer_dmem_wdata ),
+ .port2_rdata (timer_dmem_rdata ),
+ .port2_resp (timer_dmem_resp ),
+
+ // Interface to AXI bridge
+ .port0_req_ack (axi_dmem_req_ack ),
+ .port0_req (axi_dmem_req ),
+ .port0_cmd (axi_dmem_cmd ),
+ .port0_width (axi_dmem_width ),
+ .port0_addr (axi_dmem_addr ),
+ .port0_wdata (axi_dmem_wdata ),
+ .port0_rdata (axi_dmem_rdata ),
+ .port0_resp (axi_dmem_resp )
+);
+
+
+//-------------------------------------------------------------------------------
+// Instruction memory AXI bridge
+//-------------------------------------------------------------------------------
+scr1_mem_axi #(
+`ifdef SCR1_IMEM_AXI_REQ_BP
+ .SCR1_AXI_REQ_BP (1),
+`else // SCR1_IMEM_AXI_REQ_BP
+ .SCR1_AXI_REQ_BP (0),
+`endif // SCR1_IMEM_AXI_REQ_BP
+`ifdef SCR1_IMEM_AXI_RESP_BP
+ .SCR1_AXI_RESP_BP (1)
+`else // SCR1_IMEM_AXI_RESP_BP
+ .SCR1_AXI_RESP_BP (0)
+`endif // SCR1_IMEM_AXI_RESP_BP
+) i_imem_axi (
+ .clk (clk ),
+ .rst_n (axi_rst_n ),
+ .axi_reinit (axi_reinit ),
+
+ // Interface to core
+ .core_idle (axi_imem_idle ),
+ .core_req_ack (axi_imem_req_ack ),
+ .core_req (axi_imem_req ),
+ .core_cmd (axi_imem_cmd ),
+ .core_width (SCR1_MEM_WIDTH_WORD ),
+ .core_addr (axi_imem_addr ),
+ .core_wdata ('0 ),
+ .core_rdata (axi_imem_rdata ),
+ .core_resp (axi_imem_resp ),
+
+ // AXI I/O
+ .awid (io_axi_imem_awid ),
+ .awaddr (io_axi_imem_awaddr ),
+ .awlen (io_axi_imem_awlen ),
+ .awsize (io_axi_imem_awsize ),
+ .awburst (io_axi_imem_awburst ),
+ .awlock (io_axi_imem_awlock ),
+ .awcache (io_axi_imem_awcache ),
+ .awprot (io_axi_imem_awprot ),
+ .awregion (io_axi_imem_awregion ),
+ .awuser (io_axi_imem_awuser ),
+ .awqos (io_axi_imem_awqos ),
+ .awvalid (io_axi_imem_awvalid ),
+ .awready (io_axi_imem_awready ),
+ .wdata (io_axi_imem_wdata ),
+ .wstrb (io_axi_imem_wstrb ),
+ .wlast (io_axi_imem_wlast ),
+ .wuser (io_axi_imem_wuser ),
+ .wvalid (io_axi_imem_wvalid ),
+ .wready (io_axi_imem_wready ),
+ .bid (io_axi_imem_bid ),
+ .bresp (io_axi_imem_bresp ),
+ .bvalid (io_axi_imem_bvalid ),
+ .buser (io_axi_imem_buser ),
+ .bready (io_axi_imem_bready ),
+ .arid (io_axi_imem_arid ),
+ .araddr (io_axi_imem_araddr ),
+ .arlen (io_axi_imem_arlen ),
+ .arsize (io_axi_imem_arsize ),
+ .arburst (io_axi_imem_arburst ),
+ .arlock (io_axi_imem_arlock ),
+ .arcache (io_axi_imem_arcache ),
+ .arprot (io_axi_imem_arprot ),
+ .arregion (io_axi_imem_arregion ),
+ .aruser (io_axi_imem_aruser ),
+ .arqos (io_axi_imem_arqos ),
+ .arvalid (io_axi_imem_arvalid ),
+ .arready (io_axi_imem_arready ),
+ .rid (io_axi_imem_rid ),
+ .rdata (io_axi_imem_rdata ),
+ .rresp (io_axi_imem_rresp ),
+ .rlast (io_axi_imem_rlast ),
+ .ruser (io_axi_imem_ruser ),
+ .rvalid (io_axi_imem_rvalid ),
+ .rready (io_axi_imem_rready )
+);
+
+
+//-------------------------------------------------------------------------------
+// Data memory AXI bridge
+//-------------------------------------------------------------------------------
+scr1_mem_axi #(
+`ifdef SCR1_DMEM_AXI_REQ_BP
+ .SCR1_AXI_REQ_BP (1),
+`else // SCR1_DMEM_AXI_REQ_BP
+ .SCR1_AXI_REQ_BP (0),
+`endif // SCR1_DMEM_AXI_REQ_BP
+`ifdef SCR1_DMEM_AXI_RESP_BP
+ .SCR1_AXI_RESP_BP (1)
+`else // SCR1_DMEM_AXI_RESP_BP
+ .SCR1_AXI_RESP_BP (0)
+`endif // SCR1_DMEM_AXI_RESP_BP
+) i_dmem_axi (
+ .clk (clk ),
+ .rst_n (axi_rst_n ),
+ .axi_reinit (axi_reinit ),
+
+ // Interface to core
+ .core_idle (axi_dmem_idle ),
+ .core_req_ack (axi_dmem_req_ack ),
+ .core_req (axi_dmem_req ),
+ .core_cmd (axi_dmem_cmd ),
+ .core_width (axi_dmem_width ),
+ .core_addr (axi_dmem_addr ),
+ .core_wdata (axi_dmem_wdata ),
+ .core_rdata (axi_dmem_rdata ),
+ .core_resp (axi_dmem_resp ),
+
+ // AXI I/O
+ .awid (io_axi_dmem_awid ),
+ .awaddr (io_axi_dmem_awaddr ),
+ .awlen (io_axi_dmem_awlen ),
+ .awsize (io_axi_dmem_awsize ),
+ .awburst (io_axi_dmem_awburst ),
+ .awlock (io_axi_dmem_awlock ),
+ .awcache (io_axi_dmem_awcache ),
+ .awprot (io_axi_dmem_awprot ),
+ .awregion (io_axi_dmem_awregion ),
+ .awuser (io_axi_dmem_awuser ),
+ .awqos (io_axi_dmem_awqos ),
+ .awvalid (io_axi_dmem_awvalid ),
+ .awready (io_axi_dmem_awready ),
+ .wdata (io_axi_dmem_wdata ),
+ .wstrb (io_axi_dmem_wstrb ),
+ .wlast (io_axi_dmem_wlast ),
+ .wuser (io_axi_dmem_wuser ),
+ .wvalid (io_axi_dmem_wvalid ),
+ .wready (io_axi_dmem_wready ),
+ .bid (io_axi_dmem_bid ),
+ .bresp (io_axi_dmem_bresp ),
+ .bvalid (io_axi_dmem_bvalid ),
+ .buser (io_axi_dmem_buser ),
+ .bready (io_axi_dmem_bready ),
+ .arid (io_axi_dmem_arid ),
+ .araddr (io_axi_dmem_araddr ),
+ .arlen (io_axi_dmem_arlen ),
+ .arsize (io_axi_dmem_arsize ),
+ .arburst (io_axi_dmem_arburst ),
+ .arlock (io_axi_dmem_arlock ),
+ .arcache (io_axi_dmem_arcache ),
+ .arprot (io_axi_dmem_arprot ),
+ .arregion (io_axi_dmem_arregion ),
+ .aruser (io_axi_dmem_aruser ),
+ .arqos (io_axi_dmem_arqos ),
+ .arvalid (io_axi_dmem_arvalid ),
+ .arready (io_axi_dmem_arready ),
+ .rid (io_axi_dmem_rid ),
+ .rdata (io_axi_dmem_rdata ),
+ .rresp (io_axi_dmem_rresp ),
+ .rlast (io_axi_dmem_rlast ),
+ .ruser (io_axi_dmem_ruser ),
+ .rvalid (io_axi_dmem_rvalid ),
+ .rready (io_axi_dmem_rready )
+);
+
+//-------------------------------------------------------------------------------
+// AXI reinit logic
+//-------------------------------------------------------------------------------
+always_ff @(negedge core_rst_n_local, posedge clk) begin
+ if (~core_rst_n_local) axi_reinit <= 1'b1;
+ else if (axi_imem_idle & axi_dmem_idle) axi_reinit <= 1'b0;
+end
+
+endmodule : scr1_top_axi