Skip to content

MEM_43

Source: Verilog/CPU-BOARD-3202/circuit/MEM_43.v

Where it sits (Simulation): ND120_TOP > ND120_CORE > ND3202D > MEM_43 - instance path: CORE.CPU_BOARD.MEM

Used in: ND3202D (all tops)

Contains: MEM_ADDR_44, MEM_ADEC_45, MEM_DATA_46, MEM_ERROR_47, MEM_LBDIF_48, MEM_RAM_49_BLOCKRAM (only on Basys3, Cmod), MEM_RAM_49_DDR2 (only on Nexys, MEGA65 R3), MEM_RAM_49_SDRAM (only on Tang, MiSTer, MEGA65 R6, QMTECH), MEM_RAM_49_SIM (only on Simulation), MEM_RAMC_50

Module hierarchy - All modules

MEM_43 symbol

Schematic

Drawn from the Verilog: the yosys netlist of the Simulation (Verilator) build, instance CORE.CPU_BOARD.MEM. Sub-modules are boxes (click the picture to open it full size; there every sub-module box links to its page, and every wire shows its Verilog name).

MEM_43 schematic

Description

ND120 CPU, MM&M MEM MEMORY TOP LEVEL SHEET 43 of 50 Last reviewed: 22-MAR-2025 Ronny Hansen

Ports

Direction Width Name Description
input 1 ERRFA_CONTX console TX line in (probe arming)
output 1 ERRFA_TXD SINTRAN ERRFATAL evidence probe TX (MEM_RAM_49_BLOCKRAM)
input 1 sysclk System clock in FPGA
input 1 sys_rst_n (active low) System reset in FPGA
input 1 BDAP50_n (active low) BUS DAta Present (Delayed 50ns)
input 1 BDRY50_n (active low) BUS Data ReadY (Delayed 50ns)
input [4:0] BD_23_19_n (active low) Bus Data and Address (bits 23:19 negated)
input 1 BIOXE_n (active low) BUS IOX Enable
input 1 BMEM_n (active low) BUS MEMORY Enable
input 1 DBAPR BUS Address Present
input 1 ECCR BUS ECC Request
input 1 ECREQ BUS ECC Request
input 1 FETCH Bus Fetch
input 1 GNT_n (active low) Bus Grant
input 1 IBINPUT_n (active low) Bus Input Enable
input 1 IORQ_n (active low) Bus Input/Output Request
input 1 MOR_n (active low) Memory Error
input 1 MR_n (active low) Master Reset
input 1 OSC Oscillator
input 1 PA_n (active low) Parity Error Address (PEA)
input 1 PD1 Power Down 1
input 1 PD3 Power Down 3
input 1 PD4 Power Down 4
input [4:0] PPN_23_19 Physical Page Number Bits 23:19
input 1 PS_n (active low) Parity Error Signal (PES)
input 1 REFRQ_n (active low) Refresh Request
input 1 REF_n (active low) Refresh
input 1 RERR_n (active low) Refresh Error
input 1 SEMRQ50_n (active low) Semaphore Request
input 1 SSEMA_n (active low) Semaphore
input 1 WRITE Write
input [23:0] LBD_23_0_IN Local Bus Address and Data 23:0 (IN) - Address and Data for RAM
output [23:0] LBD_23_0_OUT Local Bus Address and Data 23:0 (OUT) - Data from from RAM (15:0)
output 1 BDRY_n (active low) Bus Data Ready
output 1 BGNT50_n (active low) Bus Grant (Delayed 50ns)
output 1 BGNT_n (active low) Bus Grant
output 1 CGNT50_n (active low) CPU Grant (Delayed 50ns)
output 1 CGNT_n (active low) CPU Grant
output 1 CRQ_n (active low) CPU Request
output 1 GNT50_n (active low) CPU Grant (Delayed 50ns)
output [15:0] IDB_15_0_OUT Bus Data 15:0
output 1 LERR_n (active low) Local Error
output 1 LPERR_n (active low) Local Parity Error
output 1 MOFF_n (active low) Memory Off
output 1 MOR25_n (active low) Memory Request (Delayed 25ns)
output 1 MWRITE_n (active low) Memory Write
output 1 LED4 LED4_RED_PARITY_ERROR
output 1 LED5 LED5_RED_DISABLE_PARITY
output 1 LED_CPU_GI LED_CPU_GRANT_INDICATOR
output 1 LED_BUS_GI LED_BUS_GRANT_INDICATOR
input 1 clk2x 2x sysclk, same PLL, edge-aligned
input 1 clk2x_sdram 180 degrees from clk2x, to the SDRAM chip
output 1 O_sdram_clk
output 1 O_sdram_cke
output 1 O_sdram_cs_n (active low)
output 1 O_sdram_cas_n (active low)
output 1 O_sdram_ras_n (active low)
output 1 O_sdram_wen_n (active low)
inout [31:0] IO_sdram_dq
output [10:0] O_sdram_addr
output [1:0] O_sdram_ba
output [3:0] O_sdram_dqm
output [15:0] DBG_MEMW
output [15:0] DBG_PGW
input 1 stor_clk 27 MHz crystal (pin 4) (from ND120_TANG20K_TOP.sys_clk)
input 1 stor_rst_n (active low)
input 1 mem_start
input 1 mem_we
input [19:0] mem_addr
input [31:0] mem_wdata
output [31:0] mem_rdata
output 1 mem_busy
output 1 mem_done
input 1 ui_clk
input 1 ui_rst
output 1 mm_req_valid
output 1 mm_req_we
output [26:0] mm_req_addr
output [127:0] mm_req_wdata
output [15:0] mm_req_wmask
input 1 mm_req_ready
input 1 mm_rsp_valid
input [127:0] mm_rsp_rdata
output [7:0] DBG_DDR2_BRIDGE

Verilog source

Verilog/CPU-BOARD-3202/circuit/MEM_43.v on GitHub.

Show the Verilog of MEM_43 (716 lines)
/**************************************************************************
** ND120 CPU, MM&M                                                       **
** MEM                                                                   **
** MEMORY TOP LEVEL                                                      **
** SHEET 43 of 50                                                        **
**                                                                       **
** Last reviewed: 22-MAR-2025                                            **
** Ronny Hansen                                                          **
***************************************************************************/

module MEM_43 (

`ifdef ND120_ERRFA_PROBE
    input  ERRFA_CONTX,  // console TX line in (probe arming)
    output ERRFA_TXD,    // SINTRAN ERRFATAL evidence probe TX (MEM_RAM_49_BLOCKRAM)
`endif

    // Input signals

    input sysclk,    // System clock in FPGA
    input sys_rst_n, // System reset in FPGA

    input       BDAP50_n,    //! BUS DAta Present (Delayed 50ns)
    input       BDRY50_n,    //! BUS Data ReadY (Delayed 50ns)
    input [4:0] BD_23_19_n,  //! Bus Data and Address (bits 23:19 negated)
    input       BIOXE_n,     //! BUS IOX Enable
    input       BMEM_n,      //! BUS MEMORY Enable
    input       DBAPR,       //! BUS Address Present
    input       ECCR,        //! BUS ECC Request
    input       ECREQ,       //! BUS ECC Request
    input       FETCH,       //! Bus Fetch
    input       GNT_n,       //! Bus Grant
    input       IBINPUT_n,   //! Bus Input Enable
    input       IORQ_n,      //! Bus Input/Output Request
    input       MOR_n,       //! Memory Error
    input       MR_n,        //! Master Reset
    input       OSC,         //! Oscillator
    input       PA_n,        //! Parity Error Address (PEA)
    input       PD1,         //! Power Down 1
    input       PD3,         //! Power Down 3
    input       PD4,         //! Power Down 4
    input [4:0] PPN_23_19,   //! Physical Page Number Bits 23:19
    input       PS_n,        //! Parity Error Signal (PES)
    input       REFRQ_n,     //! Refresh Request
    input       REF_n,       //! Refresh
    input       RERR_n,      //! Refresh Error
    input       SEMRQ50_n,   //! Semaphore Request
    input       SSEMA_n,     //! Semaphore
    input       WRITE,       //! Write

    input [23:0] LBD_23_0_IN,  //! Local Bus Address and Data 23:0 (IN) -  Address and Data for RAM
    output [23:0] LBD_23_0_OUT,  //! Local Bus Address and Data 23:0 (OUT) - Data from from RAM (15:0)

    // Output signals

    output        BDRY_n,        //! Bus Data Ready
    output        BGNT50_n,      //! Bus Grant (Delayed 50ns)
    output        BGNT_n,        //! Bus Grant
    output        CGNT50_n,      //! CPU Grant (Delayed 50ns)
    output        CGNT_n,        //! CPU Grant
    output        CRQ_n,         //! CPU Request
    output        GNT50_n,       //! CPU Grant (Delayed 50ns)
    output [15:0] IDB_15_0_OUT,  //! Bus Data 15:0
    output        LERR_n,        //! Local Error
    output        LPERR_n,       //! Local Parity Error
    output        MOFF_n,        //! Memory Off
    output        MOR25_n,       //! Memory Request (Delayed 25ns)
    output        MWRITE_n,      //! Memory Write
    output        LED4,          //! LED4_RED_PARITY_ERROR
    output        LED5,          //! LED5_RED_DISABLE_PARITY
    output        LED_CPU_GI,    //! LED_CPU_GRANT_INDICATOR
    output        LED_BUS_GI     // LED_BUS_GRANT_INDICATOR

`ifdef MAIN_RAM_SDRAM
    // SDRAM main-memory backend (Tang Nano 20K): the sheet-49 RAM is replaced
    // by MEM_RAM_49_SDRAM, which needs a 2x clock pair and the SDRAM device
    // pins threaded to the top level. Absent in Verilator/Basys3 builds.
    ,
    input         clk2x,        //! 2x sysclk, same PLL, edge-aligned
    input         clk2x_sdram,  //! 180 degrees from clk2x, to the SDRAM chip
    output        O_sdram_clk,
    output        O_sdram_cke,
    output        O_sdram_cs_n,
    output        O_sdram_cas_n,
    output        O_sdram_ras_n,
    output        O_sdram_wen_n,
    inout  [31:0] IO_sdram_dq,
    output [10:0] O_sdram_addr,
    output [ 1:0] O_sdram_ba,
    output [ 3:0] O_sdram_dqm,
    // Write-path debug: raw signal bus for the on-chip capture (see top)
    output [15:0] DBG_MEMW,
    //! SDRAM-bridge page-write watch (24-AUG zero-page campaign): every access
    //! to physical rows 1016..1023 in both banks, taken AT THE BRIDGE.
    output [15:0] DBG_PGW
`ifdef ND_STORAGE_PORT
    // nd_storage device port, passed straight down to MEM_RAM_49_SDRAM (which
    // forces the leading address 1, so device traffic physically cannot reach
    // the CPU's half of the chip). stor_clk is its OWN domain - the backend
    // toggle-CDCs it into clk2x. See MEM_RAM_49_SDRAM.v section 5.2.
    ,
    input  wire        stor_clk,  //! 27 MHz crystal (pin 4) (from ND120_TANG20K_TOP.sys_clk)
    input  wire        stor_rst_n,
    input  wire        mem_start,
    input  wire        mem_we,
    input  wire [19:0] mem_addr,
    input  wire [31:0] mem_wdata,
    output wire [31:0] mem_rdata,
    output wire        mem_busy,
    output wire        mem_done
`endif
`endif
`ifdef MAIN_RAM_DDR2
    // DDR2 main-memory backend (Nexys 4 DDR): the sheet-49 RAM is replaced by
    // MEM_RAM_49_DDR2 (BRAM cache in front of the MIG, reached through
    // nd_ddr2_arb at the board top). The ui_clk-domain client port is
    // threaded to the top level. MEM_HOLD never leaves this sheet - it
    // freezes the two control PALs inside MEM_RAMC_50 on a cache miss.
    ,
    input  wire         ui_clk,
    input  wire         ui_rst,
    output wire         mm_req_valid,
    output wire         mm_req_we,
    output wire [ 26:0] mm_req_addr,
    output wire [127:0] mm_req_wdata,
    output wire [ 15:0] mm_req_wmask,
    input  wire         mm_req_ready,
    input  wire         mm_rsp_valid,
    input  wire [127:0] mm_rsp_rdata,
    output wire [  7:0] DBG_DDR2_BRIDGE
`endif
);


  /*******************************************************************************
   ** The wires are defined here                                                 **
   *******************************************************************************/
  wire [ 2:0] s_bank_2_0;
  wire [ 4:0] s_bus_bd;
`ifdef MAIN_RAM_DDR2
  wire        s_mem_hold;  // cache-miss cycle stretch from MEM_RAM_49_DDR2
`else
  wire        s_mem_hold = 1'b0;
`endif
  wire [ 4:0] s_bus_ppn;
  wire [ 9:0] s_aa_9_0;
  wire [15:0] s_idb_15_0_out;

  wire [17:0] s_data_dd_in;
  wire [17:0] s_data_dd_out;

  wire [17:0] s_ram_dd_17_0_in;  // INPUT TO MEM_DATA
  wire [17:0] s_ram_dd_17_0_out;  // OUTPUT FROM MEM_DATA

  wire [23:0] s_lbd_23_0_in;  // RAM DATA 16 bits and ADDRESS 24 bits
  wire [15:0] s_lbd_15_0_out;  // RAM DATA 16 bits

  wire        s_bcgnt50;
  wire        s_bcgnt50r_n;
  wire        s_bdap50_n;
  wire        s_bdry;
  wire        s_bdry50_n;
  wire        s_bgnt_n;
  wire        s_bgnt25_n;
  wire        s_bcgnt25;
  wire        s_bgnt50_n;
  wire        s_bioxe_n;
  wire        s_bioxl_n;
  wire        s_blockl_n;
  wire        s_blockl25;
  wire        s_blrq_n;
  wire        s_blrq50_n;
  wire        s_bmem_n;
  wire        s_cas;
  wire        s_cgnt_n;
  wire        s_cgnt25_n;
  wire        s_cgnt50_n;
  wire        s_clrq_n;
  wire        s_corr_n;
  wire        s_crq_n;
  wire        s_dbapr;
  wire        s_eccr;
  wire        s_ecreq;
  wire        s_fetch;
  wire        s_gnt_n;
  wire        s_gnt50_n;
  wire        s_hien_n;
  wire        s_hierr;
  wire        s_ibinput_n;
  wire        s_iorq_n;
  wire        s_lerr_n;
  wire        s_loen_n;
  wire        s_loerr;
  wire        s_lperr_n;
  wire        s_moff_n;
  wire        s_mor_n;
  wire        s_mor25_n;
  wire        s_mr_n;
  wire        s_mwrite_n;
  wire        s_mwrite50_n;
  wire        s_osc;
  wire        s_pa_n;
  wire        s_pd1;
  wire        s_pd3;
  wire        s_pd4;
  wire        s_ps_n;
  wire        s_qd_n;
  wire        s_ras;
  wire        s_rdata;
  wire        s_rdata25;
  wire        s_ref_n;
  wire        s_refrq_n;
  wire        s_rerr_n;
  wire        s_rgnt_n;
  wire        s_rlrq_n;
  wire        s_semreq50_n;
  wire        s_ssema_n;
  wire        s_write;



  /*******************************************************************************
   ** Here all input connections are defined                                     **
   *******************************************************************************/
  assign s_bus_bd[4:0]       = BD_23_19_n;
  assign s_bus_ppn[4:0]      = PPN_23_19;
  assign s_lbd_23_0_in[23:0] = LBD_23_0_IN[23:0];
  assign s_ibinput_n         = IBINPUT_n;
  assign s_pd3               = PD3;
  assign s_dbapr             = DBAPR;
  assign s_ref_n             = REF_n;
  assign s_pa_n              = PA_n;
  assign s_iorq_n            = IORQ_n;
  assign s_ecreq             = ECREQ;
  assign s_pd1               = PD1;
  assign s_semreq50_n        = SEMRQ50_n;
  assign s_gnt_n             = GNT_n;
  assign s_ssema_n           = SSEMA_n;
  assign s_ps_n              = PS_n;
  assign s_bmem_n            = BMEM_n;
  assign s_bioxe_n           = BIOXE_n;
  assign s_bdry50_n          = BDRY50_n;
  assign s_bdap50_n          = BDAP50_n;
  assign s_eccr              = ECCR;
  assign s_mor_n             = MOR_n;
  assign s_mr_n              = MR_n;
  assign s_refrq_n           = REFRQ_n;
  assign s_rerr_n            = RERR_n;
  assign s_osc               = OSC;
  assign s_fetch             = FETCH;
  assign s_pd4               = PD4;
  assign s_write             = WRITE;

  /*******************************************************************************
   ** Here all output connections are defined                                    **
   *******************************************************************************/
  assign BDRY_n              = s_bdry;
  assign BGNT50_n            = s_bgnt50_n;
  assign BGNT_n              = s_bgnt_n;
  assign CGNT50_n            = s_cgnt50_n;
  assign CGNT_n              = s_cgnt_n;
  assign CRQ_n               = s_crq_n;
  assign GNT50_n             = s_gnt50_n;
  assign IDB_15_0_OUT        = s_idb_15_0_out[15:0];
  assign LERR_n              = s_lerr_n;
  // The 74LS112 local-parity-error flip-flop (8J, sheet 46 region F6) was
  // computed and then thrown away by the `| 1`, so LPERR~ could never go
  // active. Restored - see the note in MEM_DATA_46.v about why memory
  // classifies as Mpm 5 rather than Local when nothing can report an error.
  assign LPERR_n             = s_lperr_n;
  assign MOFF_n              = s_moff_n;
  assign MOR25_n             = s_mor25_n;
  assign MWRITE_n            = s_mwrite_n;
  assign LBD_23_0_OUT        = {8'b00000000, s_lbd_15_0_out};


  /*******************************************************************************
   ** Here all internal busses are connected                                     **
   *******************************************************************************/
  assign s_data_dd_in        = s_ram_dd_17_0_out;
  assign s_ram_dd_17_0_in    = s_data_dd_out;

  /*******************************************************************************
   ** Here all sub-circuits are defined                                          **
   *******************************************************************************/

  /*
   * Memory address decoder for the ND120 CPU system.
   * Decodes the address bus and generates the address for the memory module.
   * Also handles the memory control signals and error handling.
   */
  MEM_ADEC_45 ADEC
  (
    .sysclk(sysclk),
    .sys_rst_n(sys_rst_n),
    // Inputs
    .BGNT_n(s_bgnt_n),
    .BMEM_n(s_bmem_n),
    .CGNT_n(s_cgnt_n),
    .DBAPR(s_dbapr),
    .ECREQ(s_ecreq),
    .IBINPUT_n(s_ibinput_n),
    .IORQ_n(s_iorq_n),
    .PD4(s_pd4),
    .REFRQ_n(s_refrq_n),
    .RGNT_n(s_rgnt_n),
    .WRITE(s_write),

    .BD23_19_n(s_bus_bd[4:0]),
    .PPN_23_19(s_bus_ppn[4:0]),

      // Outputs
    .BANK_2_0(s_bank_2_0[2:0]),
    .BLRQ_n(s_blrq_n),
    .CLRQ_n(s_clrq_n),
    .CRQ_n(s_crq_n),
    .MOFF_n(s_moff_n),
    .MWRITE_n(s_mwrite_n),
    .RLRQ_n(s_rlrq_n)
  );

  /*
   * Memory local bus interface for the ND120 CPU system.
   * Handles the local bus interface and memory control signals.
   */
  MEM_LBDIF_48 LBDIF (
      .sysclk(sysclk),
      // Input signals
      .BDAP50_n(s_bdap50_n),
      .BGNT25_n(s_bgnt25_n),
      .BGNT50_n(s_bgnt50_n),
      .BGNT_n(s_bgnt_n),
      .BIOXE_n(s_bioxe_n),
      .BLRQ50_n(s_blrq50_n),
      .BLRQ_n(s_blrq_n),
      .CGNT25_n(s_cgnt25_n),
      .CGNT50_n(s_cgnt50_n),
      .CGNT_n(s_cgnt_n),
      .ECCR(s_eccr),
      .GNT50_n(s_gnt50_n),
      .GNT_n(s_gnt_n),
      .MOR_n(s_mor_n),
      .MR_n(s_mr_n),
      .MWRITE_n(s_mwrite_n),
      .OSC(s_osc),
      .sys_rst_n(sys_rst_n),
      .PD4(s_pd4),
      .REF_n(s_ref_n),

      // Output signals
      .BCGNT25(s_bcgnt25),
      .BCGNT50(s_bcgnt50),
      .BCGNT50R_n(s_bcgnt50r_n),
      .BDRY_n(s_bdry),
      .BIOXL_n(s_bioxl_n),
      .BLOCKL25_n(s_blockl25),
      .BLOCKL_n(s_blockl_n),
      .HIEN_n(s_hien_n),
      .LOEN_n(s_loen_n),
      .MOR25_n(s_mor25_n),
      .MWRITE50_n(s_mwrite50_n),
      .RAS(s_ras),
      .RDATA(s_rdata),
      .RDATA25(s_rdata25)
  );

  /*
   * Memory data handling module for the ND120 CPU system.
   * Handles data transfer between the memory and the CPU.
   */
  MEM_DATA_46 DATA (
      .OSC(s_osc),  // Clock (added for FPGA synthesis)
      .sys_rst_n(sys_rst_n),  // System reset (for FPGA synthesis)

      // Input signals
      .BCGNT50R_n(s_bcgnt50r_n),
      .BIOXL_n(s_bioxl_n),
      .DD_17_0_IN(s_data_dd_in[17:0]),
      .ECCR(s_eccr),
      .HIEN_n(s_hien_n),
      .LBD_15_0_IN(s_lbd_23_0_in[15:0]),
      .MR_n(s_mr_n),
      .MWRITE_n(s_mwrite_n),
      .PA_n(s_pa_n),
      .QD_n(s_qd_n),
      .RDATA(s_rdata),

      // Output signals
      .DD_17_0_OUT(s_data_dd_out[17:0]),
      .HIERR(s_hierr),
      .LBD_15_0_OUT(s_lbd_15_0_out[15:0]),
      .LED4(LED4),
      .LED5(LED5),
      .LERR_n(s_lerr_n),
      .LOERR(s_loerr),
      .LPERR_n(s_lperr_n)
  );

  /*
   * Memory error handling module for the ND120 CPU system.
   * Handles memory error detection and reporting.
   */
  MEM_ERROR_47 ERROR (
      // Clock and reset (added for FPGA synthesis)
      .sysclk(sysclk),
      .OSC(s_osc),
      .sys_rst_n(sys_rst_n),

      // Input signals
      .BCGNT50(s_bcgnt50),
      .BLOCKL25(s_blockl25),
      .BLOCKL_n(s_blockl_n),
      .CGNT50_n(s_cgnt50_n),
      .CORR_n(s_corr_n),
      .FETCH(s_fetch),
      .LBD_23_0_IN(s_lbd_23_0_in[23:0]),
      .MR_n(s_mr_n),
      .PA_n(s_pa_n),
      .PD4(s_pd4),
      .PS_n(s_ps_n),
      .RDATA25(s_rdata25),
      .RERR_n(s_rerr_n),

      // Output signals
      .HIERR(s_hierr),
      .IDB_15_0_OUT(s_idb_15_0_out[15:0]),
      .LERR_n(s_lerr_n),
      .LOERR(s_loerr)
  );

  /*
   * Memory RAM control module for the ND120 CPU system.
   * Handles memory control signals and error handling.
   */
  MEM_RAMC_50 RAMC (
      // Input signals
      .BDAP50_n(s_bdap50_n),
      .BDRY50_n(s_bdry50_n),
      .BCGNT25(s_bcgnt25),
      .BGNT25_n(s_bgnt25_n),
      .BGNT_n(s_bgnt_n),
      .BLRQ50_n(s_blrq50_n),
      .CAS(s_cas),
      .CGNT25_n(s_cgnt25_n),
      .CGNT_n(s_cgnt_n),
      .CLRQ_n(s_clrq_n),
      .HIEN_n(s_hien_n),
      .LOEN_n(s_loen_n),
      .MR_n(s_mr_n),
      .OSC(s_osc),
      .PD1(s_pd1),
      .PD3(s_pd3),
      .QD_n(s_qd_n),
      .RAS(s_ras),
      .RGNT_n(s_rgnt_n),
      .RLRQ_n(s_rlrq_n),
      .SEMRQ50_n(s_semreq50_n),
      .SSEMA_n(s_ssema_n),
      .MEM_HOLD(s_mem_hold),

      // Output signals
      .LED_CPU_GI(LED_CPU_GI),
      .LED_BUS_GI(LED_BUS_GI)
  );

  /*
   * Memory address decoder for the ND120 CPU system.
   * Decodes the address bus and generates the address for the memory module.
   * Also handles the memory control signals and error handling.
   */
  MEM_ADDR_44 ADDR (
      .sysclk(sysclk),
      // Input signals
      .BCGNT50(s_bcgnt25), // Need to latch address earlier before it goes away. Thats why this is changed to BCGNT25 (Ronny 7.12.2024)
      .HIEN_n(s_hien_n),
      .LBD_19_0(s_lbd_23_0_in[19:0]),
      .LOEN_n(s_loen_n),
      .PD4(s_pd4),

      // Output signals
      .AA_9_0(s_aa_9_0[9:0])
  );

  /*
   * Top level memory module for the ND120 CPU system.
   * Handles memory operations and interfaces with the system bus.
   * Provides memory access, control and error handling functionality.
   */
`ifdef MAIN_RAM_SDRAM
  // Raw write-path signal bus for the top-level capture engine.
  // v4: bridge-FSM focus (v3 proved AA row/col + BANK0 + write mode are all
  // correct at the bridge inputs, so the break is inside the bridge or the
  // SDRAM controller - watch commands issue and data_ready come back).
  // Bits [7:6] are 0 here; ND3202D overlays wdec (trigger) and WRITE.
  wire [7:0] s_dbg_bridge;
  assign DBG_MEMW = {s_dbg_bridge[7:0],              // [15:8] bridge: {bstate[2:0],
                                                     //   wr, rd, data_ready, have_data, busy}
                     2'b00,                          // [7:6] (wdec, WRITE in ND3202D)
                     s_bank_2_0[0],                  // [5] BANK0
                     s_mwrite50_n,                   // [4]
                     s_dbapr,                        // [3]
                     s_ecreq,                        // [2]
                     s_cas,                          // [1]
                     s_ras};                         // [0]

  // Tang Nano 20K: sheet-49 RAM implemented on the embedded 8 MB SDRAM
  // (fpga/tang-nano-20k/sdram-bridge/MEM_RAM_49_SDRAM.v; same interface,
  // 2 banks = 4 MB, self-scheduled refresh - see docs/nd120-dram-memory.md)
  MEM_RAM_49_SDRAM RAM (
      .sysclk(sysclk),
      .sys_rst_n(sys_rst_n),
      // Input signals
      .AA_9_0(s_aa_9_0[9:0]),
      .BANK0(s_bank_2_0[0]),
      .BANK1(s_bank_2_0[1]),
      .BANK2(s_bank_2_0[2]),
      .CAS(s_cas),
      .CORR_n(s_corr_n),
      .DD_17_0_IN(s_ram_dd_17_0_in[17:0]),
      .MWRITE50_n(s_mwrite50_n),
      .RAS(s_ras),

      // Output signals
      .DD_17_0_OUT(s_ram_dd_17_0_out[17:0]),

      // SDRAM backend (threaded to the board top)
      .clk2x(clk2x),
      .clk2x_sdram(clk2x_sdram),
      .O_sdram_clk(O_sdram_clk),
      .O_sdram_cke(O_sdram_cke),
      .O_sdram_cs_n(O_sdram_cs_n),
      .O_sdram_cas_n(O_sdram_cas_n),
      .O_sdram_ras_n(O_sdram_ras_n),
      .O_sdram_wen_n(O_sdram_wen_n),
      .IO_sdram_dq(IO_sdram_dq),
      .DBG_BRIDGE(s_dbg_bridge),
      .DBG_PGW(DBG_PGW),
      .O_sdram_addr(O_sdram_addr),
      .O_sdram_ba(O_sdram_ba),
      .O_sdram_dqm(O_sdram_dqm)
`ifdef ND_STORAGE_PORT
      ,
      .stor_clk  (stor_clk),
      .stor_rst_n(stor_rst_n),
      .mem_start (mem_start),
      .mem_we    (mem_we),
      .mem_addr  (mem_addr),
      .mem_wdata (mem_wdata),
      .mem_rdata (mem_rdata),
      .mem_busy  (mem_busy),
      .mem_done  (mem_done)
`endif
  );
`elsif MAIN_RAM_DDR2
  // Nexys 4 DDR: sheet-49 RAM implemented as a BRAM cache in front of the
  // 128 MiB DDR2 (fpga/nexys4ddr/ddr2/MEM_RAM_49_DDR2.v; same interface,
  // BANK0+BANK2 = 4 MB like the Tang, BANK1 absent). A cache miss freezes
  // the two control PALs (MEM_HOLD) until the line arrives - the CPU waits
  // via CGNTCACT_n, DMA via BDRY_n; see the module header for the proof.
`ifndef ND120_DDR2_CACHE_BITS
  `define ND120_DDR2_CACHE_BITS 14
`endif
  MEM_RAM_49_DDR2 #(
      .CACHE_IDX_BITS(`ND120_DDR2_CACHE_BITS)
  ) RAM (
      .sysclk(sysclk),
      .sys_rst_n(sys_rst_n),
      .AA_9_0(s_aa_9_0[9:0]),
      .BANK0(s_bank_2_0[0]),
      .BANK1(s_bank_2_0[1]),
      .BANK2(s_bank_2_0[2]),
      .CAS(s_cas),
      .RAS(s_ras),
      .MWRITE50_n(s_mwrite50_n),
      .DD_17_0_IN(s_ram_dd_17_0_in[17:0]),
      .DD_17_0_OUT(s_ram_dd_17_0_out[17:0]),
      .CORR_n(s_corr_n),
      .MEM_HOLD(s_mem_hold),

      // DDR2 client port, threaded to the board top (nd_ddr2_arb)
      .ui_clk(ui_clk),
      .ui_rst(ui_rst),
      .mm_req_valid(mm_req_valid),
      .mm_req_we(mm_req_we),
      .mm_req_addr(mm_req_addr),
      .mm_req_wdata(mm_req_wdata),
      .mm_req_wmask(mm_req_wmask),
      .mm_req_ready(mm_req_ready),
      .mm_rsp_valid(mm_rsp_valid),
      .mm_rsp_rdata(mm_rsp_rdata),
      .DBG_BRIDGE(DBG_DDR2_BRIDGE)
  );
`elsif MAIN_RAM_BLOCKRAM
  // FPGA block-RAM backend: one clean synchronous BRAM instead of the six
  // emulated SIP1M9 chips (MEM_RAM_49_BLOCKRAM.v). Default 3 banks x 4K words
  // (Basys3 xc7a35t budget); boards with more BRAM override the words-per-bank
  // exponent with ND120_BLOCKRAM_ADDR_BITS (Nexys 4 DDR sets 15 = 32K words
  // per bank in fpga/nexys4ddr/build.tcl).
`ifndef ND120_BLOCKRAM_ADDR_BITS
  `define ND120_BLOCKRAM_ADDR_BITS 12
`endif
  // Bank slots the array is declared with: 4 (default, unchanged for every
  // proven build) or 3 (MiSTer: only banks 0-2 exist, and the fourth slot
  // is what kept a 64K-word bank from fitting the Cyclone V; a 32K-word bank
  // wraps addresses >= 0o100000 and is the LIST-FILE-NAMES runaway of
  // 24-AUG-2026 - Verilog/docs/nd120-facts.md).
`ifndef ND120_BLOCKRAM_BANK_SLOTS
  `define ND120_BLOCKRAM_BANK_SLOTS 4
`endif
  MEM_RAM_49_BLOCKRAM #(
      .BANK_ADDR_BITS(`ND120_BLOCKRAM_ADDR_BITS),
      .BANK_SLOTS    (`ND120_BLOCKRAM_BANK_SLOTS)
  ) RAM (
`ifdef ND120_ERRFA_PROBE
      .ERRFA_CONTX(ERRFA_CONTX),
      .ERRFA_TXD(ERRFA_TXD),
`endif
      .sysclk(sysclk),
      .sys_rst_n(sys_rst_n),
      .AA_9_0(s_aa_9_0[9:0]),
      .BANK0(s_bank_2_0[0]),
      .BANK1(s_bank_2_0[1]),
      .BANK2(s_bank_2_0[2]),
      .CAS(s_cas),
      .CORR_n(s_corr_n),
      .DD_17_0_IN(s_ram_dd_17_0_in[17:0]),
      .MWRITE50_n(s_mwrite50_n),
      .RAS(s_ras),
      .DD_17_0_OUT(s_ram_dd_17_0_out[17:0])
  );
`elsif VERILATOR_SIM
  // Simulation backend: the zero-delay DRAM model on the shared sheet-49
  // interface (MEM_RAM_49_SIM.v, 3 banks x 1M x 18 bits = 6 MB - onboard
  // decode reaches a 4 MB window, fully backed). This is the RAM that the
  // sim builds actually compile; the SIP1M9 `else` branch below is NOT
  // used by the sim. The C++ harnesses preload/inspect programs directly
  // through its b0_* arrays (e.g. runSim/Run120.cpp reads ...RAM__DOT__b0_lo).
  //
  // To model a small FPGA-size RAM in a Verilator build instead, define
  // MAIN_RAM_BLOCKRAM (selects MEM_RAM_49_BLOCKRAM above). NOTE: FORCE_SMALL_RAM
  // is unrelated - it is a RAM_SIZE guard inside the legacy MEM_RAM_49.v
  // (SIP1M9) and has NO effect on this MEM_RAM_49_SIM module.
  MEM_RAM_49_SIM RAM (
      .sysclk(sysclk),
      .sys_rst_n(sys_rst_n),
      .AA_9_0(s_aa_9_0[9:0]),
      .BANK0(s_bank_2_0[0]),
      .BANK1(s_bank_2_0[1]),
      .BANK2(s_bank_2_0[2]),
      .CAS(s_cas),
      .CORR_n(s_corr_n),
      .DD_17_0_IN(s_ram_dd_17_0_in[17:0]),
      .MWRITE50_n(s_mwrite50_n),
      .RAS(s_ras),
      .DD_17_0_OUT(s_ram_dd_17_0_out[17:0])
  );
`elsif MAIN_RAM_SIP1M9
  // ===========================================================================
  // OPT-IN ONLY (3-AUG-2026): the original six-chip SIP1M9 sheet
  // (MEM_RAM_49.v + Shared/support/SIP1M9.v), kept as a schematic-faithful
  // reference of the real sheet-49 DRAM array. It is NO LONGER a fallback -
  // a board reaches it only by defining MAIN_RAM_SIP1M9 deliberately.
  //
  // Why this changed: until today this was the `else branch, and its own
  // comment claimed "NOT USED BY ANY CURRENT BUILD". That was WRONG. Basys3
  // defined no MAIN_RAM_* at all - the real synthesis logs show only
  // FPGA_FF_MODE, SKIP_WCS_LOAD, BOARD_CLK_FREQ and UART_BAUD_RATE - so it had
  // been silently landing here, which is precisely what the old comment said
  // must never happen. Basys3 now selects MAIN_RAM_BLOCKRAM explicitly in
  // fpga/basys3/vivado_build.tcl, and a missing selection is a COMPILE ERROR
  // (the `else below) instead of a silent choice.
  //
  // Backend map:
  //   * Verilator sim  -> MEM_RAM_49_SIM      (`elsif VERILATOR_SIM)
  //   * Tang Nano 20K  -> MEM_RAM_49_SDRAM    (`ifdef MAIN_RAM_SDRAM)
  //   * BRAM boards    -> MEM_RAM_49_BLOCKRAM (`elsif MAIN_RAM_BLOCKRAM)
  //   * this reference -> MEM_RAM_49          (`elsif MAIN_RAM_SIP1M9)
  // A new board either reuses one of those or adds its own
  // MEM_RAM_49_<board>.v implementing the same sheet-49 interface (AA_9_0,
  // BANK0/1/2, RAS, CAS, MWRITE50_n, DD_17_0_IN/OUT, CORR_n).
  // ===========================================================================
  MEM_RAM_49 RAM (
      .sysclk(sysclk),
      .sys_rst_n(sys_rst_n),
      // Input signals
      .AA_9_0(s_aa_9_0[9:0]),
      .BANK0(s_bank_2_0[0]),
      .BANK1(s_bank_2_0[1]),
      .BANK2(s_bank_2_0[2]),
      .CAS(s_cas),
      .CORR_n(s_corr_n),
      .DD_17_0_IN(s_ram_dd_17_0_in[17:0]),
      .MWRITE50_n(s_mwrite50_n),
      .RAS(s_ras),

      // Output signals
      .DD_17_0_OUT(s_ram_dd_17_0_out[17:0])
  );
`else
  // ===========================================================================
  // NO MAIN MEMORY BACKEND SELECTED - this is a build-configuration error.
  //
  // Every build must choose one, explicitly:
  //   MAIN_RAM_SDRAM     Tang Nano 20K (8 MB SDRAM via sdram-bridge)
  //   MAIN_RAM_BLOCKRAM  BRAM boards (Basys3, Cmod A7, QMTech)
  //   VERILATOR_SIM      Verilator harnesses (6 MB behavioural model)
  //   MAIN_RAM_SIP1M9    the six-chip sheet-49 reference (opt-in only)
  //
  // Instantiating a module that does not exist is the portable way to fail at
  // ELABORATION in every tool we use (iverilog, Verilator, Vivado, Gowin) -
  // there is no standard `error directive in Verilog-2001. The module name is
  // the diagnostic; read it and go define one of the four above.
  // ===========================================================================
  ND120_ERROR_no_main_ram_backend_selected NO_RAM_BACKEND ();
`endif
endmodule