PAL_44511A_EN¶
Source: Verilog/PAL/PAL_44511A_EN.v
Where it sits (Simulation): ND120_TOP > ND120_CORE > ND3202D > CPU_15 > CPU_PROC_32 > CPU_PROC_CMDDEC_34 > PAL_44511A_EN
- instance path: CORE.CPU_BOARD.CPU.PROC.CMDDEC.PAL_44511_ULEV0
Used in: CPU_PROC_CMDDEC_34 (all tops)
Contains: no other modules.
Module hierarchy - All modules

Schematic¶
Drawn from the Verilog: the yosys netlist of the Simulation (Verilator) build, instance CORE.CPU_BOARD.CPU.PROC.CMDDEC.PAL_44511_ULEV0. 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).
Description¶
ND120 PALASM CODE CONVERTED TO VERILOG
Component PAL 44511A (LEV0) - clock-enable wrapper
USE_ENABLE=0 (default): instantiates the original PAL_44511A untouched
(posedge CK registered outputs).
USE_ENABLE=1: structural copy of PAL_44511A with the registered
equations captured on posedge sysclk + if (EN) (P2 clock-domain
conversion, docs/plan-fix-unconstrained-clocks.md - EN is CYC_36's
CLK_EN pulse aligned with the CLK rise). Equations are line-for-line
identical to PAL_44511A.v; only the flop trigger changes.
The original PAL_44511A.v is generated from PALASM and is never
modified - keep the equations here in sync with it.
Last reviewed: 10-JUL-2026
Ronny Hansen
Parameters¶
| Parameter | Default |
|---|---|
USE_ENABLE |
0 |
Ports¶
| Direction | Width | Name | Description |
|---|---|---|---|
| input | 1 |
sysclk |
FPGA system clock (used only when USE_ENABLE=1) |
| input | 1 |
EN |
Clock enable (used only when USE_ENABLE=1) |
| input | 1 |
CK |
Clock signal (used only when USE_ENABLE=0) |
| input | 1 |
OE_n (active low) |
OUTPUT ENABLE (active-low) for Q0-Q3 |
| input | 1 |
PIL0 |
I0 - PIL0 |
| input | 1 |
PIL1 |
I1 - PIL1 |
| input | 1 |
PIL2 |
I2 - PIL2 |
| input | 1 |
PIL3 |
I3 - PIL3 |
| input | 1 |
CLK |
I4 - CLK (same signal as CK) |
| input | 1 |
MREQ_n (active low) |
I5 - MREQ_n |
| input | 1 |
WCA_n (active low) |
I6 - WCA_n |
| output | 1 |
CUP |
Q0_n - (not connected) |
| output | 1 |
CWR_n (active low) |
B0_n - CWR_n |
| output | 1 |
LEV0 |
B3_n - LEV0 |
Verilog source¶
Verilog/PAL/PAL_44511A_EN.v on GitHub.
Show the Verilog of PAL_44511A_EN (189 lines)
/**********************************************************************************************************
** ND120 PALASM CODE CONVERTED TO VERILOG **
** **
** Component PAL 44511A (LEV0) - clock-enable wrapper **
** **
** USE_ENABLE=0 (default): instantiates the original PAL_44511A untouched **
** (posedge CK registered outputs). **
** USE_ENABLE=1: structural copy of PAL_44511A with the registered **
** equations captured on `posedge sysclk + if (EN)` (P2 clock-domain **
** conversion, docs/plan-fix-unconstrained-clocks.md - EN is CYC_36's **
** CLK_EN pulse aligned with the CLK rise). Equations are line-for-line **
** identical to PAL_44511A.v; only the flop trigger changes. **
** **
** The original PAL_44511A.v is generated from PALASM and is never **
** modified - keep the equations here in sync with it. **
** **
** Last reviewed: 10-JUL-2026 **
** Ronny Hansen **
***********************************************************************************************************/
module PAL_44511A_EN #(
parameter integer USE_ENABLE = 0
) (
input sysclk, //! FPGA system clock (used only when USE_ENABLE=1)
input EN, //! Clock enable (used only when USE_ENABLE=1)
input CK, //! Clock signal (used only when USE_ENABLE=0)
input OE_n, //! OUTPUT ENABLE (active-low) for Q0-Q3
input PIL0, //! I0 - PIL0
input PIL1, //! I1 - PIL1
input PIL2, //! I2 - PIL2
input PIL3, //! I3 - PIL3
input CLK, //! I4 - CLK (same signal as CK)
input MREQ_n, //! I5 - MREQ_n
input WCA_n, //! I6 - WCA_n
//input I7, //! I7 - (not connected)
output CUP, //! Q0_n - (not connected)
//output Q1_n, //! Q1_n - (not connected)
//output Q2_n, //! Q2_n - (not connected)
//output Q2_n, //! Q3_n - (not connected)
output CWR_n, //! B0_n - CWR_n
//output B1_n, //! B1_n - (not connected)
//output B2_n, //! B2_n - (not connected)
output LEV0 //! B3_n - LEV0
);
generate
if (USE_ENABLE == 1) begin : gen_enable
/* verilator lint_off UNUSEDSIGNAL */
wire unused_clk = CK;
/* verilator lint_on UNUSEDSIGNAL */
// Register declarations for state-holding variables
reg CWR_hold = 1'b0;
reg CUP_n_reg = 1'b0;
// negated wires
wire MREQ = ~MREQ_n;
wire WCA = ~WCA_n;
wire CLK_n = ~CLK;
// CWR IS COMBINATIONAL, NOT REGISTERED. From the original PALASM,
// DesignDocuments/PAL-Code/SRC/44511A.txt:
//
// IF (VCC) CWR = MREQ * WCA + CWR * /CLK <-- '=' combinational
// /CUP := /CWR * MREQ + /CUP * /MREQ <-- ':=' registered
//
// In PALASM '=' is a combinational output and ':=' a registered one, and
// on a PAL16R4 only Q0-Q3 have flip-flops - CWR is pin B0, which has
// none. LEV0 (B3) in this same file was already modelled combinationally;
// CWR was not, and that was the bug.
//
// WHY IT MATTERED. A registered CWR is not visible until the NEXT clock
// edge, by which time MREQ has gone. The CUP term /CWR * MREQ needs both
// in the SAME cycle, so CUP never asserted at all. Everything followed
// from that: the used-bit PAL never wrote, CHIP_21F stayed zero, and
// s_hit - which requires !s_used_n - could never assert. The machine's
// own diagnostic (CACHE-120-A00 under TPE) reported exactly that chain:
// "CUP does not work", "DATA is NOT COPIED to DATA CACHE", used bit
// "Expected 1 Found 0", while the cache DATA memory test passed.
//
// HOW IT IS MODELLED HERE (FF mode, chosen 28-AUG-2026). The set term is
// combinational, so CWR is visible in the very cycle MREQ * WCA happens -
// that is what CUP needs. The hold term is a register qualified by /CLK,
// matching "HOLD UNTIL START OF NEXT CYCLE": the hold dies at the CLK rise,
// so CWR does not survive into the high phase.
//
// THE HOLD TERM IS A LEVEL LATCH, SAMPLED AT SYSCLK RATE (29-AUG-2026).
// The real pin is a feedback latch: CWR sets the instant MREQ * WCA
// appears and stays set for the rest of the CLK-low phase, and /CUP
// samples it at the CLK rise. The previous model loaded CWR_hold only
// on the CLK rise itself (the EN pulse), so the only WCA it could ever
// remember was one still present AT the rise. On this board WCA lives
// in cycle state d (PAL 44402D: ... * CYD ...) and CLK rises at TERM,
// four states later - by then WCA is long gone. Measured in Verilator
// FF mode (runSim ND120_CACHE_TRACE, 29-AUG-2026): WCA=1, CWR=1, MREQ=1
// for 4 sysclk, CWR_hold stayed 0, CUP_n stayed 1. Every cache write
// was lost that way and CACHE-1X0-A00 test 2 reported "CUP does not
// work", the same verdict as the Nexys board.
//
// Now CWR_hold is updated on EVERY sysclk: it sets on MREQ * WCA and
// holds while CLK is low, exactly the listing's CWR * /CLK term at
// sysclk resolution. At the EN sample CLK is still low (CLK_EN is the
// cycle BEFORE the rise, see CYC_36.v), so CUP sees the held CWR.
// This is the USE_LATCHES=0 path the FPGA builds; PAL_44511A.v (the
// latch-mode twin) models the same latch level-sensitively.
wire CWR = (MREQ & WCA) | (CWR_hold & CLK_n);
// LEVEL ZERO
assign LEV0 = ~(PIL3 | PIL2 | PIL1 | PIL0);
// Sequential logic - equations identical to PAL_44511A.v,
// captured on the enable instead of posedge CK.
always @(posedge sysclk) begin
// CWR hold latch at sysclk rate - NOT gated by EN (see above): set on
// MREQ * WCA, kept while CLK is low, dies once CLK is high.
CWR_hold <= (MREQ & WCA) | (CWR_hold & CLK_n);
if (EN) begin
// Logic for CUP (ADDED CACHE UPDATE BIT). 44511A OCR/PNG (registered):
// /CUP := /CWR * MREQ + /CUP * /MREQ
// (intent: CUP := CWR*MREQ + CUP*/MREQ - SET on write-to-cache, hold until next MREQ).
// Fix 26-JUL: the prior if/else had the MREQ polarity flipped (CWR_n & MREQ_n),
// so CUP was never set on a cache write and spuriously set when idle -> the
// CACHE-1X0 diagnostic reported "Cache updated bit: Not working".
CUP_n_reg <= (~CWR & MREQ) | (CUP_n_reg & MREQ_n);
end
end
// PIN 19 POLARITY (29-AUG-2026, 23:30) - THE CACHE'S FAULT 2.
//
// MEASURED (runSim, CACHE-1X0-A00 test 2, per-clock log of the test's
// read of the word it had just written): both tag comparators match,
// the used bit is set and valid, RT and DT are asserted, no write is
// in progress - and sheet 25's HIT stays 0 on every clock of the
// cycle. The only HIT input left is this pin. Same six test-2 lines on
// the Nexys with everything else fixed, so it is not a model artefact.
//
// THE HARDWARE. Sheet 25: HIT is the output of a 74S260 5-input NOR
// (21H) whose inputs are USED~, HIT~1, HIT~0, the net CWR and ground -
// HIT is high only when ALL of them are LOW. Sheet 34: net CWR is pin
// 19 of this PAL, wired straight to the connector, no inverter. So on
// the real board pin 19 must be LOW on a normal read and go HIGH only
// across a cache write (MREQ * WCA, held until CLK) - that is the pin
// FOLLOWING the listing's CWR expression, not its complement.
//
// This file used to drive the complement ("/CWR is active low, pin =
// ~CWR", the convention the 44402D's /USED and /WCA pins follow and
// which is right for them). For this pin that makes HIT possible only
// WHILE the cache is being written, i.e. never on a read: every read
// ran the full memory cycle and took the memory word, exactly the
// "DATA is taken FROM MEMORY when present in DATA CACHE" family of
// errors. The listing's naming and the schematic's naming disagree on
// this net (the listing calls the pin /CWR, both sheets call the net
// CWR with no ~), and the measurement decides: the pin follows CWR.
// The CUP equation below uses the internal CWR and is unaffected.
// outputs
assign CWR_n = OE_n ? 1'b0 : CWR; // pin 19 follows CWR - see the note above
assign CUP = OE_n ? 1'b0 : ~CUP_n_reg;
end else begin : gen_orig
/* verilator lint_off UNUSEDSIGNAL */
wire unused_sys = sysclk & EN;
/* verilator lint_on UNUSEDSIGNAL */
PAL_44511A PAL (
.CK(CK),
.OE_n(OE_n),
.PIL0(PIL0),
.PIL1(PIL1),
.PIL2(PIL2),
.PIL3(PIL3),
.CLK(CLK),
.MREQ_n(MREQ_n),
.WCA_n(WCA_n),
.CUP(CUP),
.CWR_n(CWR_n),
.LEV0(LEV0)
);
end
endgenerate
endmodule