Add initial Verilog model for the GAL16V8

This commit is contained in:
annoyatron255 2024-05-03 21:44:22 -05:00
parent bb48e10488
commit 5ac484b1a8
No known key found for this signature in database
GPG key ID: 95283811BE4E93F8
6 changed files with 543 additions and 0 deletions

279
models/GAL16V8_reg.hex Normal file
View file

@ -0,0 +1,279 @@
00
00
08
92
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
fe
ff
ff
ff
ef
ff
ff
ff
ff
fe
ff
ff
ff
ef
ff
ff
ff
ff
fe
ff
ff
ff
ef
ff
00
00
00
00
00
00
00
00
ee
ee
ee
ff
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
ff
ff
de
ff
ff
ff
ed
ff
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
ff
fe
ff
ff
ff
ef
ff
ff
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
ee
ff
ff
ff
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
00
f0
c2
f6
b6
46
2a
a6
ce
2e
00
ff
ff
ff
ff
ff
ff
ff
ff
02

175
models/GAL16V8_reg.v Normal file
View file

@ -0,0 +1,175 @@
`default_nettype none
module GAL16V8_reg (
input wire clk,
input wire [7:0] in,
input wire oe_n,
inout wire [7:0] io
);
// Read in binary JEDEC file
reg [7:0] jed_bin_file [0:278];
initial $readmemh("GAL16V8_reg.hex", jed_bin_file);
// Linearize to a fuse map
wire [2193:0] fuses;
genvar i, j;
generate
for (i = 0; i < 274; i = i + 1) begin
for (j = 0; j < 8; j = j + 1) begin
assign fuses[8*i + j] = jed_bin_file[i + 4][j];
end
end
// Last couple bits
for (j = 0; j < 2; j = j + 1) begin
assign fuses[8*274 + j] = jed_bin_file[274 + 4][j];
end
endgenerate
// Extract useful fuses
wire syn_fuse, ac0_fuse;
assign syn_fuse = fuses[2192];
assign ac0_fuse = fuses[2193];
wire [7:0] xor_fuses;
assign xor_fuses = fuses[2055:2048];
wire [7:0] ac1_fuses;
assign ac1_fuses = fuses[2127:2120];
wire [255:0] sop_fuses [0:7];
wire [7:0] ptd_fuses [0:7];
generate
for (i = 0; i < 8; i = i + 1) begin
assign sop_fuses[i] = fuses[256*i +: 256];
assign ptd_fuses[i] = fuses[2128 + 8*i +: 8];
end
endgenerate
// Interleave in and feedback for SOP inputs
wire [7:0] feedback;
wire [15:0] interleaved;
generate
for (i = 0; i < 8; i = i + 1) begin
assign interleaved[2*i +: 2] = {feedback[i], in[i]};
end
endgenerate
// Generate GAL elements
generate
for (i = 0; i < 8; i = i + 1) begin
wire one_sop_out, sop_out;
// 1SOP
sop #(
.NUM_PRODUCTS(1),
.NUM_INPUTS(16)
) one_sop_inst (
.sop_fuses(sop_fuses[i][255:224]),
.ptd_fuses(ptd_fuses[i][0]),
.in(interleaved),
.out(one_sop_out)
);
// SOP
sop #(
.NUM_PRODUCTS(7),
.NUM_INPUTS(16)
) sop_inst (
.sop_fuses(sop_fuses[i][223:0]),
.ptd_fuses(ptd_fuses[i][7:1]),
.in(interleaved),
.out(sop_out)
);
// OLMC
olmc olmc_inst (
.xor_fuse(xor_fuses[i]),
.ac1_fuse(ac1_fuses[i]),
.sop(sop_out),
.one_sop(one_sop_out),
.clk(clk),
.oe_n(oe_n),
.io(io[i]),
.feedback(feedback[i])
);
end
endgenerate
// Simulation printing
initial begin
#1;
$display("SYN: %d, AC0: %d", syn_fuse, ac0_fuse);
$display("XOR: %b, AC1: %b", xor_fuses, ac1_fuses);
$display("Fuses: %x", fuses);
$display("sop0 %x", sop_fuses[0]);
$display("ptd0 %x", ptd_fuses[0]);
$display("sop1 %x", sop_fuses[1]);
$display("ptd1 %x", ptd_fuses[1]);
$display("sop2 %x", sop_fuses[2]);
$display("ptd2 %x", ptd_fuses[2]);
$display("sop3 %x", sop_fuses[3]);
$display("ptd3 %x", ptd_fuses[3]);
$display("sop4 %x", sop_fuses[4]);
$display("ptd4 %x", ptd_fuses[4]);
$display("sop5 %x", sop_fuses[5]);
$display("ptd5 %x", ptd_fuses[5]);
$display("sop6 %x", sop_fuses[6]);
$display("ptd6 %x", ptd_fuses[6]);
$display("sop7 %x", sop_fuses[7]);
$display("ptd7 %x", ptd_fuses[7]);
end
endmodule
module sop #(
parameter NUM_PRODUCTS = 7,
parameter NUM_INPUTS = 16
)(
input wire [2*NUM_INPUTS*NUM_PRODUCTS-1:0] sop_fuses,
input wire [NUM_PRODUCTS-1:0] ptd_fuses,
input wire [NUM_INPUTS-1:0] in,
output reg out
);
integer i, j;
reg match;
always @ (*) begin
out = 0;
for (i = 0; i < NUM_PRODUCTS; i = i + 1) begin
match = 1;
for (j = 0; j < NUM_INPUTS; j = j + 1) begin
if (!sop_fuses[2*NUM_INPUTS*i + 2*j + 0] && !in[j]) match = 0;
if (!sop_fuses[2*NUM_INPUTS*i + 2*j + 1] && in[j]) match = 0;
end
if (match && ptd_fuses[i]) out = 1;
end
end
endmodule
module olmc (
input wire xor_fuse,
input wire ac1_fuse,
input wire sop,
input wire one_sop,
input wire clk,
input wire oe_n,
inout wire io,
output wire feedback
);
// Internal combined SOP output with optional inversion
wire out;
assign out = (ac1_fuse ? sop : (sop || one_sop)) ^ xor_fuse;
reg reg_out;
always @ (posedge clk) begin
reg_out <= out;
end
assign feedback = ac1_fuse ? !reg_out : out;
assign io = ac1_fuse ? (one_sop ? !out : 1'bz) : // Combinational
(oe_n ? 1'bz : !reg_out); // Registered
endmodule

38
models/GAL16V8_reg_tb.v Normal file
View file

@ -0,0 +1,38 @@
module GAL16V8_reg_tb(
output reg clk = 0,
output reg [7:0] in,
output reg oe_n,
inout wire [7:0] io
);
GAL16V8_reg GAL16V8_reg_inst (
.clk(clk),
.in(in),
.oe_n(oe_n),
.io(io)
);
always #5 clk = !clk;
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, GAL16V8_reg_tb);
#3;
in = 8'b0000_1100;
oe_n = 0;
#10;
in = 8'b0000_1001;
#10;
in = 8'b0000_0110;
#10;
in = 8'b0000_0011;
#10;
in = 8'b0000_1100;
#30;
oe_n = 1;
#10;
$finish;
end
endmodule

15
models/original.v Normal file
View file

@ -0,0 +1,15 @@
module original (
input wire clk,
input wire [5:0] in,
output reg [4:0] out
);
always @(posedge clk) begin
out[0] <= in[0] && in[1];
out[1] <= in[2] || in[3];
out[2] <= in[4] && !in[5] || !in[4] && in[5];
out[3] <= in[0] && in[1] && in[2] && in[3] && in[4] && in[5];
out[4] <= !(in[0] || in[1] || in[2] || in[3] || in[4] || in[5]);
end
endmodule

14
models/prove_equiv.tcl Executable file
View file

@ -0,0 +1,14 @@
#!/usr/bin/env -S yosys -c
yosys -import
read_verilog original.v
flatten
synth
read_verilog wrapper.v GAL16V8_reg.v
flatten
synth
equiv_make original wrapper equiv
equiv_induct equiv
equiv_status -assert equiv

22
models/wrapper.v Normal file
View file

@ -0,0 +1,22 @@
module wrapper (
input wire clk,
input wire [5:0] in,
output wire [4:0] out
);
wire [7:0] in_int;
wire [7:0] io_int;
wire oe_n;
assign oe_n = 0;
assign in_int = {3'b0, in};
assign out = {io_int[3], io_int[4], io_int[5], io_int[6], io_int[7]};
GAL16V8_reg GAL16V8_reg_inst (
.clk(clk),
.in(in_int),
.oe_n(oe_n),
.io(io_int)
);
endmodule