psurply / ReGAL

A set of scripts used to assist reverse engineering of old-school Programmable Array Logic devices.
MIT License
67 stars 7 forks source link

Invalid Jed produced, signals inverted #7

Open ladmanj opened 1 year ago

ladmanj commented 1 year ago

Dear @psurply,

I'm struggling with non-functional Jed outputs from ReGAL, which I found an excellent tool otherwise. Some signals are inverted inappropriately.

Here is example of a problematic design. But similar errors are produced in 3 of 4 files of my current design. The design is in the attached file including simulation testbench.

Thank you for fixing it, if possible.

I analyzed the output Jed files using the old tool JED2EQN from National Semiconductor of that time, running under MS-DOS. A much newer tool https://github.com/dev-zzo/jedisasm gives comparable results.

Jakub Ladman

Full original verilog source (working in simulation)

`default_nettype none

module top (
input  CLK,WR_EN,WR_FLAG,NRST,
output NWR_LOAD,WID2,WID1,WID0,WDIV2,WDIV1,WDIV0,
output WR_CLK
);

reg [5:0] wcnt;

wire run;
assign run = (wcnt != 6'd63);

always @(posedge CLK) begin

    if(~NRST | ~WR_EN) begin
        wcnt <= ~6'd0;
    end
    else if (run | ~WR_FLAG)
        wcnt <= wcnt + 6'd1;
end

assign {WID2,WID1,WID0,WDIV2,WDIV1,WDIV0} = wcnt;

assign NWR_LOAD = (wcnt > 6'd4);

assign WR_CLK = WDIV2       // 12.5 kHz bit clock,
                & run;      // out low when counter stopped.
endmodule

Shortened jed2eqn output with bug:

/o19 = /rf18 * /rf17 * /rf16 * /rf15
    + /rf18 * /rf17 * /rf16 * /rf14 * /rf13
o19.oe = vcc

/o12 = /rf15
    + rf18 * rf17 * rf16 * rf15 * rf14 * rf13
o12.oe = vcc

shortened jedisasm PLD output with bug

/* Pin 19; AC1:1; XOR:0 */
NWR_LOAD =
    WID2 & !WID1 & !WID0 & !WDIV2
  # WID2 & !WID1 & !WID0 & !WDIV1 & !WDIV0;

/* Pin 12; AC1:1; XOR:0 */
WR_CLK =
    !WDIV2
  # !WID2 & WID1 & WID0 & WDIV2 & WDIV1 & WDIV0;

shortened PLD to verilog rewrite with manual bug fix

/* Pin 19; AC1:1; XOR:0 */
assign NWR_LOAD = ~ 
-- fix -----------^

 (   (rWID2 & ~rWID1 & ~rWID0 & ~rWDIV2)
  | (rWID2 & ~rWID1 & ~rWID0 & ~rWDIV1 & ~rWDIV0));

/* Pin 12; AC1:1; XOR:0 */
assign WR_CLK = ~ 
-- fix ---------^
 (   (~rWDIV2)
  | (~rWID2 & rWID1 & rWID0 & rWDIV2 & rWDIV1 & rWDIV0));

Full jed2eqn output (with bug)

; JED2EQN -- JEDEC file to Boolean Equations disassembler (Version V063)
; Copyright (c) National Semiconductor Corporation 1990-1993
; Disassembled from writecnt.jed. Date: 9-14-123
;$GALMODE REGISTERED

chip writecnt GAL16V8

CLK=1 i3=3 i7=7 i9=9 GND=10 /OE=11 o12=12 rf13=13 rf14=14 rf15=15 
rf16=16 rf17=17 rf18=18 o19=19 VCC=20 

@ues 0000000000000000
@ptd unused

equations

/o19 = /rf18 * /rf17 * /rf16 * /rf15
    + /rf18 * /rf17 * /rf16 * /rf14 * /rf13
o19.oe = vcc
/rf18 := i3 * /rf18 * /rf17 * i9
    + i3 * /rf18 * rf17 * /rf15 * i9
    + i3 * /rf18 * rf15 * /rf13 * i9
    + i3 * /rf18 * /rf14 * rf13 * i9
    + i3 * /rf18 * rf17 * /rf16 * rf15 * i9
    + i3 * rf18 * rf17 * rf16 * rf15 * /i7 * rf14 * rf13 * i9
rf18.oe = OE
rf17 := /i3
    + rf17 * /rf16
    + i3 * /i9
    + rf17 * rf16 * /rf13
    + rf17 * /rf14 * rf13
    + rf17 * rf16 * /rf15 * rf13
    + /rf17 * rf16 * rf15 * rf14 * rf13
    + rf18 * rf17 * rf16 * rf15 * i7 * rf14 * rf13
rf17.oe = OE
rf16 := /i3
    + rf16 * /rf15
    + i3 * /i9
    + rf16 * rf15 * /rf14
    + /rf16 * rf15 * rf14 * rf13
    + rf16 * rf15 * rf14 * /rf13
    + rf18 * rf17 * rf16 * rf15 * i7 * rf14 * rf13
rf16.oe = OE
rf15 := /i3
    + rf15 * /rf13
    + i3 * /i9
    + /rf15 * rf14 * rf13
    + rf15 * /rf14 * rf13
    + rf18 * rf17 * rf16 * rf15 * i7 * rf14 * rf13
rf15.oe = OE
rf14 := /i3
    + rf14 * /rf13
    + /rf14 * rf13
    + i3 * /i9
    + rf18 * rf17 * rf16 * rf15 * i7 * rf14 * rf13
rf14.oe = OE
rf13 := /i9
    + /rf13 * i9
    + /i3 * rf13 * i9
    + rf18 * rf17 * rf16 * rf15 * i7 * rf14 * rf13
rf13.oe = OE
/o12 = /rf15
    + rf18 * rf17 * rf16 * rf15 * rf14 * rf13
o12.oe = vcc

Full jedisasm output (with bug)

Pin  1 = CLK;
Pin  2 = PIN02;
Pin  3 = WR_EN;
Pin  4 = PIN04;
Pin  5 = PIN05;
Pin  6 = PIN06;
Pin  7 = WR_FLAG;
Pin  8 = NC8;
Pin  9 = NRST;
Pin 10 = PIN10;
Pin 11 = PIN11;
Pin 12 = WR_CLK;
Pin 13 = WDIV0;
Pin 14 = WDIV1;
Pin 15 = WDIV2;
Pin 16 = WID0;
Pin 17 = WID1;
Pin 18 = !WID2;
Pin 19 = NWR_LOAD;
Pin 20 = PIN20;

/* Pin 19; AC1:1; XOR:0 */
NWR_LOAD =
    WID2 & !WID1 & !WID0 & !WDIV2
  # WID2 & !WID1 & !WID0 & !WDIV1 & !WDIV0;

/* Pin 18; AC1:0; XOR:0 */
WID2.d =
    WR_EN & WID2 & !WID1 & NRST
  # WR_EN & WID2 & WID1 & !WDIV2 & NRST
  # WR_EN & WID2 & WDIV2 & !WDIV0 & NRST
  # WR_EN & WID2 & !WDIV1 & WDIV0 & NRST
  # WR_EN & WID2 & WID1 & !WID0 & WDIV2 & NRST
  # WR_EN & !WID2 & WID1 & WID0 & WDIV2 & !WR_FLAG & WDIV1 & WDIV0 & NRST;

/* Pin 17; AC1:0; XOR:1 */
WID1.d =
    !WR_EN
  # WID1 & !WID0
  # WR_EN & !NRST
  # WID1 & WID0 & !WDIV0
  # WID1 & !WDIV1 & WDIV0
  # WID1 & WID0 & !WDIV2 & WDIV0
  # !WID1 & WID0 & WDIV2 & WDIV1 & WDIV0
  # !WID2 & WID1 & WID0 & WDIV2 & WR_FLAG & WDIV1 & WDIV0;

/* Pin 16; AC1:0; XOR:1 */
WID0.d =
    !WR_EN
  # WID0 & !WDIV2
  # WR_EN & !NRST
  # WID0 & WDIV2 & !WDIV1
  # !WID0 & WDIV2 & WDIV1 & WDIV0
  # WID0 & WDIV2 & WDIV1 & !WDIV0
  # !WID2 & WID1 & WID0 & WDIV2 & WR_FLAG & WDIV1 & WDIV0;

/* Pin 15; AC1:0; XOR:1 */
WDIV2.d =
    !WR_EN
  # WDIV2 & !WDIV0
  # WR_EN & !NRST
  # !WDIV2 & WDIV1 & WDIV0
  # WDIV2 & !WDIV1 & WDIV0
  # !WID2 & WID1 & WID0 & WDIV2 & WR_FLAG & WDIV1 & WDIV0;

/* Pin 14; AC1:0; XOR:1 */
WDIV1.d =
    !WR_EN
  # WDIV1 & !WDIV0
  # !WDIV1 & WDIV0
  # WR_EN & !NRST
  # !WID2 & WID1 & WID0 & WDIV2 & WR_FLAG & WDIV1 & WDIV0;

/* Pin 13; AC1:0; XOR:1 */
WDIV0.d =
    !NRST
  # !WDIV0 & NRST
  # !WR_EN & WDIV0 & NRST
  # !WID2 & WID1 & WID0 & WDIV2 & WR_FLAG & WDIV1 & WDIV0;

/* Pin 12; AC1:1; XOR:0 */
WR_CLK =
    !WDIV2
  # !WID2 & WID1 & WID0 & WDIV2 & WDIV1 & WDIV0;

Full PLD to verilog rewrite used for simulation and debug (with fix)

module writecounter (
  input CLK,

  input WR_EN,

  input WR_FLAG,

  input NRST,

  output WR_CLK,
  output WDIV0,
  output WDIV1,
  output WDIV2,
  output WID0,
  output WID1,
  output WID2,
  output NWR_LOAD
);

reg rWDIV0;
reg rWDIV1;
reg rWDIV2;
reg rWID0;
reg rWID1;
reg rWID2;

assign WDIV0 =  rWDIV0;
assign WDIV1 =  rWDIV1;
assign WDIV2 =  rWDIV2;
assign WID0  =  rWID0;
assign WID1  =  rWID1;
assign WID2  = ~rWID2;

/* Pin 19; AC1:1; XOR:0 */
assign NWR_LOAD = ~
 (   (rWID2 & ~rWID1 & ~rWID0 & ~rWDIV2)
  | (rWID2 & ~rWID1 & ~rWID0 & ~rWDIV1 & ~rWDIV0));

/* Pin 18; AC1:0; XOR:0 */
always@(posedge CLK) begin
  rWID2 <=
    (WR_EN & rWID2 & ~rWID1 & NRST)
  | (WR_EN & rWID2 & rWID1 & ~rWDIV2 & NRST)
  | (WR_EN & rWID2 & rWDIV2 & ~rWDIV0 & NRST)
  | (WR_EN & rWID2 & ~rWDIV1 & rWDIV0 & NRST)
  | (WR_EN & rWID2 & rWID1 & ~rWID0 & rWDIV2 & NRST)
  | (WR_EN & ~rWID2 & rWID1 & rWID0 & rWDIV2 & ~WR_FLAG & rWDIV1 & rWDIV0 & NRST);

/* Pin 17; AC1:0; XOR:1 */
  rWID1 <=
    (~WR_EN)
  | (rWID1 & ~rWID0)
  | (WR_EN & ~NRST)
  | (rWID1 & rWID0 & ~rWDIV0)
  | (rWID1 & ~rWDIV1 & rWDIV0)
  | (rWID1 & rWID0 & ~rWDIV2 & rWDIV0)
  | (~rWID1 & rWID0 & rWDIV2 & rWDIV1 & rWDIV0)
  | (~rWID2 & rWID1 & rWID0 & rWDIV2 & WR_FLAG & rWDIV1 & rWDIV0);

/* Pin 16; AC1:0; XOR:1 */
  rWID0 <=
    (~WR_EN)
  | (rWID0 & ~rWDIV2)
  | (WR_EN & ~NRST)
  | (rWID0 & rWDIV2 & ~rWDIV1)
  | (~rWID0 & rWDIV2 & rWDIV1 & rWDIV0)
  | (rWID0 & rWDIV2 & rWDIV1 & ~rWDIV0)
  | (~rWID2 & rWID1 & rWID0 & rWDIV2 & WR_FLAG & rWDIV1 & rWDIV0);

/* Pin 15; AC1:0; XOR:1 */
  rWDIV2 <= 
    (~WR_EN)
  | (rWDIV2 & ~rWDIV0)
  | (WR_EN & ~NRST)
  | (~rWDIV2 & rWDIV1 & rWDIV0)
  | (rWDIV2 & ~rWDIV1 & rWDIV0)
  | (~rWID2 & rWID1 & rWID0 & rWDIV2 & WR_FLAG & rWDIV1 & rWDIV0);

/* Pin 14; AC1:0; XOR:1 */
  rWDIV1 <=
    (~WR_EN)
  | (rWDIV1 & ~rWDIV0)
  | (~rWDIV1 & rWDIV0)
  | (WR_EN & ~NRST)
  | (~rWID2 & rWID1 & rWID0 & rWDIV2 & WR_FLAG & rWDIV1 & rWDIV0);

/* Pin 13; AC1:0; XOR:1 */
  rWDIV0 <=
    (~NRST)
  | (~rWDIV0 & NRST)
  | (~WR_EN & rWDIV0 & NRST)
  | (~rWID2 & rWID1 & rWID0 & rWDIV2 & WR_FLAG & rWDIV1 & rWDIV0);
end

/* Pin 12; AC1:1; XOR:0 */
assign WR_CLK = ~
 (   (~rWDIV2)
  | (~rWID2 & rWID1 & rWID0 & rWDIV2 & rWDIV1 & rWDIV0));
endmodule

project.zip

ladmanj commented 1 year ago

I must now admit that I'm super confused, where the problem originates from. I found correlation with the presence of the XOR:0 in the comment (produced by jedisasm). That is conforming to the fact that the output is always inverted both by the output driver and by the fact that the loopback is fed by !Q output of the FF where used.

pic

Maybe in my jed -> verilog reverse there are some gaps in understanding My physical device isn't working according to the simulation however.