// ********************************************************************
//  Microsemi Corporation Proprietary and Confidential
//  Copyright 2018 Microsemi Corporation.  All rights reserved.
//
// ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
// ACCORDANCE WITH THE MICROSEMI LICENSE AGREEMENT AND MUST BE APPROVED
// IN ADVANCE IN WRITING.
//
// Description: CoreCortexM1
//
// Revision Information:
// Date     Description
// 
   module CORECORTEXM1 (
    // Clocks and resets
    HCLK,
    SYSRESETN,
    DBGRESETN,
    NRESET,
    HRESETN,
    // Watchdog signals
    WDOGRES,
    WDOGRESN,
    // Miscellaneous
    LOCKUP,
    HALTED,
    SYSRESETREQ,
    // Interrupt interface
    NMI,
    IRQ31,
    IRQ30,
    IRQ29,
    IRQ28,
    IRQ27,
    IRQ26,
    IRQ25,
    IRQ24,
    IRQ23,
    IRQ22,
    IRQ21,
    IRQ20,
    IRQ19,
    IRQ18,
    IRQ17,
    IRQ16,
    IRQ15,
    IRQ14,
    IRQ13,
    IRQ12,
    IRQ11,
    IRQ10,
    IRQ9,
    IRQ8,
    IRQ7,
    IRQ6,
    IRQ5,
    IRQ4,
    IRQ3,
    IRQ2,
    IRQ1,
    IRQ0,
    // AHB-Lite interface
    HADDR,
    HBURST,
    HPROT,
    HRDATA,
    HREADY,
    HRESP,
    HSIZE,
    HTRANS,
    HWDATA,
    HWRITE,
    HMASTLOCK,
    // Debug signals
    EDBGRQ,
    JTAGTOP,
    JTAGNSW,
    DBGRESTART,
    DBGRESTARTED,
    SWDO,
    SWDOEN,
    NTDOEN,
    SWCLKTCK,
    NTRST,
    SWDITMS,
    TDI,
    TDO
    );
    // Parameters
    parameter      FAMILY = 25;         // FPGA family
    parameter      NUM_IRQ_TOP = 32;    // Valid values are 1,8,16,32
    parameter      USE_BFM = 0 ;        // 0 = BFM not used, 1 = BFM used (Note: Used for simulation only) 
    parameter      ENABLE_ECC = 0;      // 0 = Disabled, 1 = Enabled
    parameter      DEBUG_INCL = 0;      // 0 = Debug logic not included, 1 = Debug logic included
	parameter      DEBUG_IF = 1;        // 0 = FlashPro JTAG (internal), 1 = ARM RealView JTAG (external)
    parameter      INCL_RESET_CTRL = 1; // 0 = Reset Control not included, 1 Reset Control included
	
    // Settings for DEBUG_CONFIG parameter:
    //  0 = Debug logic not included
    //  1 = 2 breakpoints, 1 watchpoint
    //  2 = 4 breakpoints, 2 watchpoints
    localparam       DEBUG_CONFIG = 2;

//    // DEBUG_RESET parameter is only applicable when DEBUG_CONFIG != 0.
//    //  0 = Reset to debug logic (DBGRESETn) driven by NSYSRESET input
//    //  1 = Reset to debug logic (DBGRESETn) driven by PORESETN input
    localparam       DEBUG_RESET = 0;

    // DRIVE_RTCK parameter is only applicable when DEBUG = 1.
    //  0 = RV_RTCK output is tied low
    //  1 = RV_RTCK output is RV_TCK synchronized to HCLK domain
    //parameter       DRIVE_RTCK = 0;

    // UJ_RST_ON_GLOBAL parameter is only applicable when DEBUG = 2.
    //  0 = Instantiate CLKINT buffer for UJTAG URSTB output
    //  1 = Do not instantiate CLKINT buffer for UJTAG URSTB output
    //parameter       UJ_RST_ON_GLOBAL = 1;
    localparam      UJ_RST_ON_GLOBAL = 1;

    // UJ_CLK_ON_GLOBAL parameter is only applicable when DEBUG = 2.
    //  0 = Instantiate CLKINT buffer for UJTAG UDRCK output
    //  1 = Do not instantiate CLKINT buffer for UJTAG UDRCK output
    //parameter       UJ_CLK_ON_GLOBAL = 1;
    localparam      UJ_CLK_ON_GLOBAL = 1;

    // ITCM_SZ and DTCM_SZ control the sizes of the Instruction and
    // Data TCMs. These parameters are used below to set the values
    // of the ITCM_SIZE and DTCM_SIZE parameters.
    localparam        ITCM_SZ = 32;
    localparam        DTCM_SZ = 32;

    //---------------------------------------------------------------------
    // "Cortex-M1" parameters
    //---------------------------------------------------------------------

    localparam        NUM_IRQ     = 32;    // Valid values are 1,8,16,32
    localparam        OS          = 1;    // If 0, timer is absent
    localparam        SMALL_MUL   = 0;    // If 1, use small multiplier
    localparam        BE8         = 0;    // If 1, big endian 8 mode

    localparam      ITCM_SIZE   = (ITCM_SZ ==    0) ? 4'b0000:  //    0 kB
                                  (ITCM_SZ ==    1) ? 4'b0001:  //    1 kB
                                  (ITCM_SZ ==    2) ? 4'b0010:  //    2 kB
                                  (ITCM_SZ ==    4) ? 4'b0011:  //    4 kB
                                  (ITCM_SZ ==    8) ? 4'b0100:  //    8 kB
                                  (ITCM_SZ ==   16) ? 4'b0101:  //   16 kB
                                  (ITCM_SZ ==   32) ? 4'b0110:  //   32 kB
                                  (ITCM_SZ ==   64) ? 4'b0111:  //   64 kB
                                  (ITCM_SZ ==  128) ? 4'b1000:  //  128 kB
                                  (ITCM_SZ ==  256) ? 4'b1001:  //  256 kB
                                  (ITCM_SZ ==  512) ? 4'b1010:  //  512 kB
                                  (ITCM_SZ == 1024) ? 4'b1011:  //    1 MB
                                                      4'b0000;

    localparam      DTCM_SIZE   = (DTCM_SZ ==    0) ? 4'b0000:  //    0 kB
                                  (DTCM_SZ ==    1) ? 4'b0001:  //    1 kB
                                  (DTCM_SZ ==    2) ? 4'b0010:  //    2 kB
                                  (DTCM_SZ ==    4) ? 4'b0011:  //    4 kB
                                  (DTCM_SZ ==    8) ? 4'b0100:  //    8 kB
                                  (DTCM_SZ ==   16) ? 4'b0101:  //   16 kB
                                  (DTCM_SZ ==   32) ? 4'b0110:  //   32 kB
                                  (DTCM_SZ ==   64) ? 4'b0111:  //   64 kB
                                  (DTCM_SZ ==  128) ? 4'b1000:  //  128 kB
                                  (DTCM_SZ ==  256) ? 4'b1001:  //  256 kB
                                  (DTCM_SZ ==  512) ? 4'b1010:  //  512 kB
                                  (DTCM_SZ == 1024) ? 4'b1011:  //    1 MB
                                                      4'b0000;

    localparam      ITCM_LA_EN  = 0;                            // ITCM lower alias enable
    localparam      ITCM_UA_EN  = 1;                            // ITCM upper alias enable
    localparam      SMALL_DEBUG = (DEBUG_CONFIG == 1);          // If 1, reduced debug
    localparam      JTAG        = ((DEBUG_IF == 0) || (DEBUG_IF == 1) || (DEBUG_IF == 3)); // If 0, JTAG DP excluded
    localparam      SW          = ((DEBUG_IF == 2) || (DEBUG_IF == 3));                    // If 0, SW DP excluded
    //---------------------------------------------------------------------



    // Some families have a subtly different UJTAG macro - one that has a
    // UIREG[7:0] port instead of eight separate ports ranging from UIREG0
    // to UIREG7.
    //localparam      USE_NEW_UJTAG =
    //                                (FAMILY == 19) ? 1 :
    //                                (FAMILY == 24) ? 1 :
    //                                (FAMILY == 25) ? 1 :
    //                                (FAMILY == 26) ? 1 :
    //                                                 0 ;

    localparam      uj_jtag_ircode = 8'h33;


    // Clocks and resets
    input           HCLK;
    input           SYSRESETN;
    input           DBGRESETN;
    input           NRESET;
    output          HRESETN;
    // Watchdog signals
    input           WDOGRES;
    output          WDOGRESN;
    // Miscellaneous
    output          LOCKUP;
    output          HALTED;
    output          SYSRESETREQ;
    // Interrupt interface
    input           NMI;
    input           IRQ31;
    input           IRQ30;
    input           IRQ29;
    input           IRQ28;
    input           IRQ27;
    input           IRQ26;
    input           IRQ25;
    input           IRQ24;
    input           IRQ23;
    input           IRQ22;
    input           IRQ21;
    input           IRQ20;
    input           IRQ19;
    input           IRQ18;
    input           IRQ17;
    input           IRQ16;
    input           IRQ15;
    input           IRQ14;
    input           IRQ13;
    input           IRQ12;
    input           IRQ11;
    input           IRQ10;
    input           IRQ9;
    input           IRQ8;
    input           IRQ7;
    input           IRQ6;
    input           IRQ5;
    input           IRQ4;
    input           IRQ3;
    input           IRQ2;
    input           IRQ1;
    input           IRQ0;
    // AHB-Lite interface
    output  [31:0]  HADDR;
    output   [2:0]  HBURST;
    output   [3:0]  HPROT;
    input   [31:0]  HRDATA;
    input           HREADY;
    input    [1:0]  HRESP;
    output   [2:0]  HSIZE;
    output   [1:0]  HTRANS;
    output  [31:0]  HWDATA;
    output          HWRITE;
    output          HMASTLOCK;
    // Debug signals
    input           EDBGRQ;
    output          JTAGTOP;
    output          JTAGNSW;
    input           DBGRESTART;
    output          DBGRESTARTED;
    output          SWDO;
    output          SWDOEN;
    output          NTDOEN;
    input           SWCLKTCK;
    input           NTRST;
    input           SWDITMS;
    input           TDI;
    output          TDO;

    wire    [31:0]  IRQ;

    // Combine individual interrupt inputs into a 32 bit bus
    assign IRQ = {
                    IRQ31,
                    IRQ30,
                    IRQ29,
                    IRQ28,
                    IRQ27,
                    IRQ26,
                    IRQ25,
                    IRQ24,
                    IRQ23,
                    IRQ22,
                    IRQ21,
                    IRQ20,
                    IRQ19,
                    IRQ18,
                    IRQ17,
                    IRQ16,
                    IRQ15,
                    IRQ14,
                    IRQ13,
                    IRQ12,
                    IRQ11,
                    IRQ10,
                    IRQ9,
                    IRQ8,
                    IRQ7,
                    IRQ6,
                    IRQ5,
                    IRQ4,
                    IRQ3,
                    IRQ2,
                    IRQ1,
                    IRQ0
                 };




    reg             SYSRESETREQ_q1;
    reg             merged_sysresetreq_resetn_q1;
    reg             merged_sysresetreq_resetn_q2;
    reg             merged_sysresetn_q1;
    reg             merged_sysresetn_q2;
    reg             merged_sysresetn_q3;
    reg             merged_sysresetn_q4;
    reg             dbgresetn_q1;
    reg             dbgresetn_q2;
    reg             dbgresetn_q3;
    reg             dbgresetn_q4;
    reg             merged_wdogresn_q1;
    reg             merged_wdogresn_q2;
    reg             merged_wdogresn_q3;
    reg             merged_wdogresn_q4;

    wire            merged_sysresetreq_resetn;
    wire            merged_sysresetn;
    wire            M1_SYSRESETn;
    wire            HRESETN;
    wire            M1_DBGRESETn;
    wire            merged_wdogresn;
    wire            WDOGRESN;

    wire            M1_NTRST;
    wire            M1_SWCLKTCK;
    wire            M1_SWDITMS;
    wire            M1_TDI;

    wire            M1_SWCLKTCK_BUF;

    wire            dutntrst;
    wire            duttck;
    wire            duttms;
    wire            duttdi;

    wire     [7:0]  UIREG;
    wire            URSTB /* synthesis syn_keep = 1 */;
    wire            UDRUPD;
    wire            UDRCK /* synthesis syn_keep = 1 */;
    wire            UDRCAP;
    wire            UDRSH;
    wire            UTDI;
    wire            UTDO;
    wire            UTDODRV;
    wire            UTDO_G;
    wire            UJTAG_TDO;
    wire     [3:0]  uj_gpout;
    wire     [3:0]  uj_gpin;

    // Signals that are only driven by the "debug" version of the
    // processor, and not by the "non-debug" version.
    wire            HALTED;
    wire            DBGRESTARTED;
    wire            SWDO;
    wire            SWDOEN;
    wire            M1_TDO;
    wire            NTDOEN;
    wire            JTAGNSW;
    wire            JTAGOP;

    wire            URSTB_BUF;
    wire            UDRCK_BUF;

//-------------------------------------------------------------------------
// Optional reset controller type logic.
//
// The option to include this reset control logic is intended to simplify
// things for the user, to make it easier to build a processor based
// system. If what's implemented here is not what the user wants, then they
// can simply set INCL_RESET_CTRL to 0 and implement whatever logic they
// require external to this core.
//
// When INCL_RESET_CTRL is set to 1, we create a system reset signal to the
// processor (which connects to its SYSRESETn input) that is synchronized
// to HCLK and which asserts when any of the following occur:
//  1. Assertion of the top level SYSRESETN input.
//  2. The processor asserted its SYSRESETREQ output. (Note that this
//     signal is registered before being used to influence the reset input
//     to the processor as advised in the Cortex-M1 TRM.)
//  3. Assertion of the top level watchdog "bark" input (WDOGRES).
//  4. Assertion of the top level NRESET input.
//
// The NRESET input is effectively an "additional" reset input. It could be
// driven from any source. However its intended use is for connection to
// a debug header that supports a reset signal. Several debug connector
// pinouts support a reset signal which is normally labelled "nRESET".
//
//
// Also when INCL_RESET_CTRL = 1, a HRESETN output is driven by the same
// merged, synchronized signal that drives the system reset input of the
// processor. HRESETN can be used to reset other components in the system.
//
//
// Finally, a reset output (WDOGRESN) that the user may wish to connect to
// a watchdog type component is driven when INCL_RESET_CTRL = 1. This is
// similar to the system reset signal described above, except that the
// "bark" signal from the watchdog does not feature in the logic
// controlling the WDOGRESN output.
//
//
// When INCL_RESET_CTRL != 1, the HRESETN and WDOGRESN outputs are tied off
// to inactive levels (high), and the NRESET and WDOGRES inputs are not
// used.
//
//
//-------------------------------------------------------------------------
generate
    if (INCL_RESET_CTRL == 1)
    begin
        // "Merge" various reset sources for the reset signal to the
        // SYSRESETREQ flop into one signal.
        // (The reset for this flop is handled separately to avoid having
        // the flop reset itself when its output is asserted following a
        // system reset request from the processor.)
        assign merged_sysresetreq_resetn =
                                        SYSRESETN       // System reset input.
                                    &&  NRESET          // Additional reset input. Could come from debug header, for example.
                                    &&  !WDOGRES        // "Bark" signal from watchdog.
                                    ;

        // Synchronize "merged" reset signal for SYSRESETREQ flop to HCLK
        // domain.
        always @(posedge HCLK or negedge merged_sysresetreq_resetn)
        begin
            if (!merged_sysresetreq_resetn)
            begin
                merged_sysresetreq_resetn_q1 <= 1'b0;
                merged_sysresetreq_resetn_q2 <= 1'b0;
            end
            else
            begin
                merged_sysresetreq_resetn_q1 <= 1'b1;
                merged_sysresetreq_resetn_q2 <= merged_sysresetreq_resetn_q1;
            end
        end

        // The SYSRESETREQ output from the processor should not be
        // connected directly to the processor's SYSRESETn input.
        // The Cortex-M1 TRM advises using a flop to hold the reset LOW
        // for a cycle.
        always @(posedge HCLK or negedge merged_sysresetreq_resetn_q2)
        begin
            if(!merged_sysresetreq_resetn_q2)
            begin
                SYSRESETREQ_q1 <= 1'b0;
            end
            else
            begin
                SYSRESETREQ_q1 <= SYSRESETREQ;
            end
        end


        // "Merge" various reset sources for system reset into one signal.
        assign merged_sysresetn =
                                        SYSRESETN       // System reset input.
                                    &&  !SYSRESETREQ_q1 // (Registered) system reset request from processor.
                                    &&  NRESET          // Additional reset input. Could come from debug header, for example.
                                    &&  !WDOGRES        // "Bark" signal from watchdog.
                                    ;

        // Synchronize "merged" reset signal to HCLK domain.
        always @(posedge HCLK or negedge merged_sysresetn)
        begin
            if (!merged_sysresetn)
            begin
                merged_sysresetn_q1 <= 1'b0;
                merged_sysresetn_q2 <= 1'b0;
                merged_sysresetn_q3 <= 1'b0;
                merged_sysresetn_q4 <= 1'b0;
            end
            else
            begin
                merged_sysresetn_q1 <= 1'b1;
                merged_sysresetn_q2 <= merged_sysresetn_q1;
                merged_sysresetn_q3 <= merged_sysresetn_q2;
                merged_sysresetn_q4 <= merged_sysresetn_q3;
            end
        end

        // Drive reset input to processor and HRESETN top level output
        // with the merged, synchronized reset.
        // HRESETN can be used to reset other components in the system.
        assign M1_SYSRESETn = merged_sysresetn_q4;
        assign HRESETN      = merged_sysresetn_q4;

        // Also synchronize the debug reset input to the HCLK domain when
        // the user chooses to include optional reset control logic.
        // It seems appropriate to do this since we're already
        // synchronizing the system reset.
        always @(posedge HCLK or negedge DBGRESETN)
        begin
            if (!DBGRESETN)
            begin
                dbgresetn_q1 <= 1'b0;
                dbgresetn_q2 <= 1'b0;
                dbgresetn_q3 <= 1'b0;
                dbgresetn_q4 <= 1'b0;
            end
            else
            begin
                dbgresetn_q1 <= 1'b1;
                dbgresetn_q2 <= dbgresetn_q1;
                dbgresetn_q3 <= dbgresetn_q2;
                dbgresetn_q4 <= dbgresetn_q3;
            end
        end

        assign M1_DBGRESETn = dbgresetn_q4;

        // Create a reset output that the user may wish to connect to a
        // watchdog type component. The sources of this reset are similar
        // to those for the system reset except that the "bark" signal from
        // the watchdog does not contribute here. The idea is that this
        // watchdog type reset output could be used to reset flops in a
        // watchdog that control its "bark" output. These would then only
        // be reset by system reset sources, and not by the "bark" signal
        // itself.
        assign merged_wdogresn =
                                        SYSRESETN       // System reset input.
                                    &&  !SYSRESETREQ_q1 // (Registered) system reset request from processor.
                                    &&  NRESET          // Additional reset input. Could come from debug header, for example.
                                    ;

        // Synchronize "merged" watchdog reset signal to HCLK domain.
        always @(posedge HCLK or negedge merged_wdogresn)
        begin
            if (!merged_wdogresn)
            begin
                merged_wdogresn_q1 <= 1'b0;
                merged_wdogresn_q2 <= 1'b0;
                merged_wdogresn_q3 <= 1'b0;
                merged_wdogresn_q4 <= 1'b0;
            end
            else
            begin
                merged_wdogresn_q1 <= 1'b1;
                merged_wdogresn_q2 <= merged_wdogresn_q1;
                merged_wdogresn_q3 <= merged_wdogresn_q2;
                merged_wdogresn_q4 <= merged_wdogresn_q3;
            end
        end

        assign WDOGRESN = merged_wdogresn_q4;

    end
    else
    begin
        // The SYSRESETREQ output from the processor should not be
        // connected directly to the processor's SYSRESETn input.
        // The Cortex-M1 TRM advises using a flop to hold the reset LOW
        // for a cycle.
        always @(posedge HCLK or negedge SYSRESETN)
        begin
            if(!SYSRESETN)
            begin
                SYSRESETREQ_q1 <= 1'b0;
            end
            else
            begin
                SYSRESETREQ_q1 <= SYSRESETREQ;
            end
        end
		
        // Drive reset inputs to processor directly from top level inputs
        // and tie off HRESETN and WDOGRESN outputs to inactive levels.
        assign M1_SYSRESETn = SYSRESETN && !SYSRESETREQ_q1;
        assign M1_DBGRESETn = DBGRESETN;
        assign HRESETN      = 1'b1;
        assign WDOGRESN     = 1'b1;

        // Tie off unused internal signals.
        assign merged_sysresetreq_resetn    = 1'b1;
        assign merged_sysresetn             = 1'b1;
        assign merged_wdogresn              = 1'b1;
		
        always @(*)
          begin
            merged_sysresetreq_resetn_q1 <= 1'b1;
            merged_sysresetreq_resetn_q2 <= 1'b1;
            merged_sysresetn_q1 <= 1'b1;
            merged_sysresetn_q2 <= 1'b1;
            merged_sysresetn_q3 <= 1'b1;
            merged_sysresetn_q4 <= 1'b1;
            dbgresetn_q1 <= 1'b1;
            dbgresetn_q2 <= 1'b1;
            dbgresetn_q3 <= 1'b1;
            dbgresetn_q4 <= 1'b1;
            merged_wdogresn_q1 <= 1'b1;
            merged_wdogresn_q2 <= 1'b1;
            merged_wdogresn_q3 <= 1'b1;
            merged_wdogresn_q4 <= 1'b1;
          end
    end
endgenerate


//-------------------------------------------------------------------------
// The following code is related to debug connection options.
//
// The debug connection can be through the FlashPro header (when using
// Microsemi's SoftConsole application for software development and
// debugging) or through an ARM header.
//
// When the FlashPro header is used for the debug connection, the UJTAG
// macro is used to facilitate connection between the dedicated JTAG pins
// on the device and the logic in the FPGA fabric. The following ports (of
// this core) must be routed to the top level of your design when you
// choose the "debug through FlashPro header" option:
//      NTRST
//      SWCLKTCK
//      SWDITMS
//      TDI
//      TDO
//
//-------------------------------------------------------------------------
generate
    if ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0) && (UJ_RST_ON_GLOBAL == 1) )
    begin
        CLKINT uj_rst_clkint (.A(URSTB), .Y(URSTB_BUF));
    end
    else
    begin
        assign URSTB_BUF = URSTB;
    end
endgenerate

generate
    if ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0) && (UJ_CLK_ON_GLOBAL == 1))
    begin
        CLKINT uj_clk_clkint (.A(UDRCK), .Y(UDRCK_BUF));
    end
    else
    begin
        assign UDRCK_BUF = UDRCK;
    end
endgenerate


  assign M1_NTRST    = ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0)) ? dutntrst  : NTRST    ;
  assign M1_SWCLKTCK = ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0)) ? duttck    : SWCLKTCK ;
  assign M1_SWDITMS  = ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0)) ? duttms    : SWDITMS  ;
  assign M1_TDI      = ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0)) ? duttdi    : TDI      ;

  assign TDO         = ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0)) ? UJTAG_TDO : M1_TDO   ;


  // Want to use low skew routing for SWCLKTCK clock.
  CLKINT tck_clkint   (.A(M1_SWCLKTCK), .Y(M1_SWCLKTCK_BUF));


generate
    if ((DEBUG_CONFIG > 0) && (DEBUG_INCL == 1) && (DEBUG_IF == 0))
    // Debugging through FlashPro header and using "new" UJTAG macro
    begin
        assign uj_gpin      = uj_gpout;
        assign UTDO_G       = UTDO & UTDODRV;

        ccortexm1_UJTAG_WRAPPER UJ(
            // The following 5 ports need to be routed to the top level when
            // UJTAG is being used.
            .TCK        (SWCLKTCK),
            .TDI        (TDI),
            .TMS        (SWDITMS),
            .TDO        (UJTAG_TDO),
            .TRSTB      (NTRST),

            .UIREG      (UIREG),
            .URSTB      (URSTB),
            .UDRUPD     (UDRUPD),
            .UDRCK      (UDRCK),
            .UDRCAP     (UDRCAP),
            .UDRSH      (UDRSH),
            .UTDI       (UTDI),
            .UTDO       (UTDO_G)
        );

        // Instantiate UJTAG interface block
        ccortexm1_uj_jtag #(uj_jtag_ircode) ujjtag (
            // UJTAG port
            .uireg      (UIREG),
            .urstb      (URSTB_BUF),
            .udrupd     (UDRUPD),
            .udrck      (UDRCK_BUF),
            .udrcap     (UDRCAP),
            .udrsh      (UDRSH),

            .utdi       (UTDI),
            .utdo       (UTDO),
            .utdodrv    (UTDODRV),

            // JTAG port (to DUT)
            .dutntrst   (dutntrst),
            .duttck     (duttck),
            .duttms     (duttms),
            .duttdi     (duttdi),
            .duttdo     (M1_TDO),

            // GPIO register
            .gpout      (uj_gpout),
            .gpin       (uj_gpin)
        );
    end
    else
    // Debugging using "ARM" header (as opposed to FlashPro header) or
    // using non-debug version of processor.
    begin
        assign UJTAG_TDO    = 1'b0;

        assign UIREG        = 8'b0;
        assign URSTB        = 1'b0;
        assign UDRUPD       = 1'b0;
        assign UDRCK        = 1'b0;
        assign UDRCAP       = 1'b0;
        assign UDRSH        = 1'b0;
        assign UTDI         = 1'b0;
        assign UTDO         = 1'b0;
        assign UTDODRV      = 1'b0;
        assign dutntrst     = 1'b0;
        assign duttck       = 1'b0;
        assign duttms       = 1'b0;
        assign duttdi       = 1'b0;
        assign uj_gpout     = 4'b0;
        assign uj_gpin      = 4'b0;

        assign UTDO_G       = 1'b0;
    end
endgenerate

generate if (USE_BFM == 1) begin
/* synthesis translate_off*/
CortexM1Integration_TS
M1
(
.HCLK(HCLK),

.SYSRESETn(SYSRESETN),
.IRQ(IRQ),
.NMI(NMI),

.HRDATA(HRDATA),
.HREADY(HREADY),
.HRESP(HRESP[0]),

.DBGRESETn(DBGRESETN),
.EDBGRQ(EDBGRQ),
.nTRST(NTRST),
.SWCLKTCK(SWCLKTCK),
.SWDITMS(SWDITMS),
.TDI(TDI),

.tcmInitWriteEnable(1'b0),
.tcmInitAddr(18'b0),
.tcmInitWriteData(32'b0),

 // outputs
.SYSRESETREQ(SYSRESETREQ),
.LOCKUP(LOCKUP),

.HADDR(HADDR),
.HBURST(HBURST),
.HPROT(HPROT),

.HSIZE(HSIZE),
.HTRANS(HTRANS),
.HWDATA(HWDATA),
.HWRITE(HWRITE),
.HMASTLOCK(HMASTLOCK),

.JTAGNSW(JTAGNSW),
.JTAGTOP(JTAGTOP),
.SWDO(SWDO),
.SWDOEN(SWDOEN),
.TDO(TDO),
.nTDOEN(NTDOEN),
.HALTED(HALTED)
);
/* synthesis translate_on*/
end
endgenerate 

generate
    if (((DEBUG_CONFIG == 0) || (DEBUG_INCL == 0)) && USE_BFM == 0)
    begin
        CortexM1Integration
        M1 (
            // Clocks and resets
            .HCLK           (HCLK),
            .SYSRESETn      (M1_SYSRESETn),
            // Miscellaneous
            .LOCKUP         (LOCKUP),
            .SYSRESETREQ    (SYSRESETREQ),
            // Interrupt interface
            .IRQ            (IRQ),
            .NMI            (NMI),
            // External AHB-Lite interface
            .HADDR          (HADDR),
            .HBURST         (HBURST),
            .HPROT          (HPROT),
            .HRDATA         (HRDATA),
            .HREADY         (HREADY),
            .HRESP          (HRESP[0]),
            .HSIZE          (HSIZE),
            .HTRANS         (HTRANS),
            .HWDATA         (HWDATA),
            .HWRITE         (HWRITE),
            .HMASTLOCK      (HMASTLOCK)
        );
        assign HALTED       = 1'b0;
        assign DBGRESTARTED = 1'b0;
        assign SWDO         = 1'b0;
        assign SWDOEN       = 1'b0;
        assign M1_TDO       = 1'b0;
        assign NTDOEN       = 1'b1;
        assign JTAGNSW      = 1'b1;
        assign JTAGOP       = 1'b0;
    end
    else if ( USE_BFM == 0 )
    begin
        CortexM1DbgIntegration 
        M1 (
            // Clocks and resets
            .HCLK           (HCLK),
            .DBGRESETn      (M1_DBGRESETn),
            .SYSRESETn      (M1_SYSRESETn),
            // Miscellaneous
            .LOCKUP         (LOCKUP),
            .HALTED         (HALTED),
            .SYSRESETREQ    (SYSRESETREQ),
            .EDBGRQ         (EDBGRQ),
            // Interrupt interface
            .IRQ            (IRQ),
            .NMI            (NMI),
            // External AHB-Lite interface
            .HADDR          (HADDR),
            .HBURST         (HBURST),
            .HPROT          (HPROT),
            .HRDATA         (HRDATA),
            .HREADY         (HREADY),
            .HRESP          (HRESP[0]),
            .HSIZE          (HSIZE),
            .HTRANS         (HTRANS),
            .HWDATA         (HWDATA),
            .HWRITE         (HWRITE),
            .HMASTLOCK      (HMASTLOCK),
            // SWJ-DP interface
            .SWDO           (SWDO),
            .SWDOEN         (SWDOEN),
            .TDO            (M1_TDO),
            .nTDOEN         (NTDOEN),
            .JTAGNSW        (JTAGNSW),
            .JTAGTOP        (JTAGTOP),
            .nTRST          (M1_NTRST),
            .SWCLKTCK       (M1_SWCLKTCK_BUF),
            .SWDITMS        (M1_SWDITMS),
            .TDI            (M1_TDI),
            // Debug sync
            .DBGRESTART     (DBGRESTART),
            .DBGRESTARTED   (DBGRESTARTED)
        );
    end
endgenerate

endmodule
