From 41c60bcab640b7488867da05dc31ab10d6a2de19 Mon Sep 17 00:00:00 2001 From: annoyatron255 Date: Sun, 5 May 2024 20:02:46 -0500 Subject: [PATCH] Add initial GAL22V10 model --- models/.gitignore | 3 +- models/{wrapper.v => GAL16V8_wrapper.v} | 0 models/GAL22V10_reg.v | 163 ++++++++++++++++++++++++ models/GAL22V10_reg_tb.v | 30 +++++ models/GAL22V10_wrapper.v | 12 ++ models/prove_equiv.tcl | 46 +++++-- testcases/olmc_test.pcf | 6 +- 7 files changed, 246 insertions(+), 14 deletions(-) rename models/{wrapper.v => GAL16V8_wrapper.v} (100%) create mode 100644 models/GAL22V10_reg.v create mode 100644 models/GAL22V10_reg_tb.v create mode 100644 models/GAL22V10_wrapper.v diff --git a/models/.gitignore b/models/.gitignore index ee0fde1..d290c64 100644 --- a/models/.gitignore +++ b/models/.gitignore @@ -1,4 +1,5 @@ a.out dump.vcd -GAL16V8_reg.bin GAL16V8_reg.hex +GAL22V10_reg.hex +__temp.bin diff --git a/models/wrapper.v b/models/GAL16V8_wrapper.v similarity index 100% rename from models/wrapper.v rename to models/GAL16V8_wrapper.v diff --git a/models/GAL22V10_reg.v b/models/GAL22V10_reg.v new file mode 100644 index 0000000..7ad2b22 --- /dev/null +++ b/models/GAL22V10_reg.v @@ -0,0 +1,163 @@ +`default_nettype none +module GAL22V10_reg ( + input wire [12:0] in, // Pin {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 1 is clk + inout wire [9:0] io // Pin {14, 15, 16, 17, 18, 19, 20, 21, 22, 23} +); + // Read in binary JEDEC file + reg [7:0] jed_bin_file [0:740]; + initial $readmemh("GAL22V10_reg.hex", jed_bin_file); + + // Linearize to a fuse map + wire [5891:0] fuses; + genvar i, j; + generate + for (i = 0; i < 736; 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 < 4; j = j + 1) begin + assign fuses[8*736 + j] = jed_bin_file[736 + 4][j]; + end + endgenerate + + // Extract useful fuses + wire [9:0] xor_fuses; + assign xor_fuses = {fuses[5826], fuses[5824], fuses[5822], fuses[5820], fuses[5818], + fuses[5816], fuses[5814], fuses[5812], fuses[5810], fuses[5808]}; + + wire [9:0] reg_fuses; + assign reg_fuses = {fuses[5827], fuses[5825], fuses[5823], fuses[5821], fuses[5819], + fuses[5817], fuses[5815], fuses[5813], fuses[5811], fuses[5809]}; + + wire [747:0] sop_fuses [0:9]; + assign sop_fuses[0] = {352'b0, fuses[439:44]}; + assign sop_fuses[1] = {264'b0, fuses[923:440]}; + assign sop_fuses[2] = {176'b0, fuses[1495:924]}; + assign sop_fuses[3] = {88'b0, fuses[2155:1496]}; + assign sop_fuses[4] = fuses[2903:2156]; + assign sop_fuses[5] = fuses[3651:2904]; + assign sop_fuses[6] = {88'b0, fuses[4311:3652]}; + assign sop_fuses[7] = {176'b0, fuses[4883:4312]}; + assign sop_fuses[8] = {264'b0, fuses[5367:4884]}; + assign sop_fuses[9] = {352'b0, fuses[5763:5368]}; + + + // Interleave in and feedback for SOP inputs + wire [9:0] feedback; + wire [21:0] interleaved; + generate + for (i = 0; i < 10; i = i + 1) begin + assign interleaved[2*i +: 2] = {feedback[i], in[i]}; + end + assign interleaved[21:20] = {in[11], in[10]}; + endgenerate + + // Generate GAL elements + generate + for (i = 0; i < 10; i = i + 1) begin + wire one_sop_out, sop_out; + + // 1SOP + sop #( + .NUM_PRODUCTS(1), + .NUM_INPUTS(22) + ) one_sop_inst ( + .sop_fuses(sop_fuses[i][43:0]), + .in(interleaved), + .out(one_sop_out) + ); + + // SOP + sop #( + .NUM_PRODUCTS(16), + .NUM_INPUTS(22) + ) sop_inst ( + .sop_fuses(sop_fuses[i][747:44]), + .in(interleaved), + .out(sop_out) + ); + + // OLMC + olmc olmc_inst ( + .xor_fuse(xor_fuses[i]), + .reg_fuse(reg_fuses[i]), + .sop(sop_out), + .one_sop(one_sop_out), + .clk(in[0]), + .io(io[i]), + .feedback(feedback[i]) + ); + end + endgenerate + + // Simulation printing + initial begin + #1; + $display("XOR: %b, REG: %b", xor_fuses, reg_fuses); + $display("Fuses: %x", fuses); + + $display("sop0 %x", sop_fuses[0]); + $display("sop1 %x", sop_fuses[1]); + $display("sop2 %x", sop_fuses[2]); + $display("sop3 %x", sop_fuses[3]); + $display("sop4 %x", sop_fuses[4]); + $display("sop5 %x", sop_fuses[5]); + $display("sop6 %x", sop_fuses[6]); + $display("sop7 %x", sop_fuses[7]); + $display("sop8 %x", sop_fuses[8]); + $display("sop9 %x", sop_fuses[9]); + 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_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) out = 1; + end + end +endmodule + +module olmc ( + input wire xor_fuse, + input wire reg_fuse, + + input wire sop, + input wire one_sop, + + input wire clk, + + inout wire io, + output wire feedback +); + // Internal combined SOP output with optional inversion + wire out; + assign out = sop ^ xor_fuse; + + reg reg_out; + always @ (posedge clk) begin + reg_out <= out; + end + + assign feedback = reg_fuse ? !out : !reg_out ^ xor_fuse; + + assign io = reg_fuse ? (one_sop ? !out : 1'bz) : // Combinational + (one_sop ? !reg_out : 1'bz); // Registered +endmodule diff --git a/models/GAL22V10_reg_tb.v b/models/GAL22V10_reg_tb.v new file mode 100644 index 0000000..904bb3c --- /dev/null +++ b/models/GAL22V10_reg_tb.v @@ -0,0 +1,30 @@ +module GAL22V10_reg_tb( + output reg [12:0] in = 13'bx_xxxx_xxxx_xxx1, + inout wire [9:0] io +); + +GAL22V10_reg GAL22V10_reg_inst ( + .in(in), + .io(io) +); + +always #5 in[0] = !in[0]; + +initial begin + $dumpfile("dump.vcd"); + $dumpvars(0, GAL22V10_reg_tb); + #3; + in[12:1] = 12'bxxxx_xxxx_x00x; + #10; + in[12:1] = 12'bxxxx_xxxx_x01x; + #10; + in[12:1] = 12'bxxxx_xxxx_x10x; + #10; + in[12:1] = 12'bxxxx_xxxx_x11x; + #10; + in[12:1] = 12'bxxxx_xxxx_x00x; + #10; + $finish; +end + +endmodule diff --git a/models/GAL22V10_wrapper.v b/models/GAL22V10_wrapper.v new file mode 100644 index 0000000..0064e88 --- /dev/null +++ b/models/GAL22V10_wrapper.v @@ -0,0 +1,12 @@ +`default_nettype none +module __wrapper ( + input wire [12:0] __in, // Pin {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 1 is clk + inout wire [9:0] __io // Pin {14, 15, 16, 17, 18, 19, 20, 21, 22, 23} +); + +GAL22V10_reg GAL22V10_reg_inst ( + .in(__in), + .io(__io) +); + +endmodule diff --git a/models/prove_equiv.tcl b/models/prove_equiv.tcl index 83382e5..49470c1 100755 --- a/models/prove_equiv.tcl +++ b/models/prove_equiv.tcl @@ -2,7 +2,7 @@ yosys -import # Parse arguments -if { $argc < 3 } { +if {$argc < 3} { puts "USAGE: $argv0 -- ..." exit } @@ -11,24 +11,44 @@ set jedec_file [lindex $argv 0] set pcf_file [lindex $argv 1] set verilog_files [lrange $argv 2 end] -# Convert JEDEC file to hex for Verilog model -exec jedutil -convert $jedec_file GAL16V8_reg.bin -exec xxd -ps -c 1 GAL16V8_reg.bin GAL16V8_reg.hex +# Convert JEDEC file to bin +exec jedutil -convert $jedec_file __temp.bin + +# Find chip being used +set jedec_bin_size [file size __temp.bin] +if {$jedec_bin_size == 279} { + set chip GAL16V8 + set pin_mapping [dict create 1 "clk" 2 "in\[0\]" 3 "in\[1\]" 4 "in\[2\]" 5 "in\[3\]" 6 "in\[4\]" 7 "in\[5\]" 8 "in\[6\]" 9 "in\[7\]" 11 "oe_n" 12 "io\[7\]" 13 "io\[6\]" 14 "io\[5\]" 15 "io\[4\]" 16 "io\[3\]" 17 "io\[2\]" 18 "io\[1\]" 19 "io\[0\]"] +} elseif {$jedec_bin_size == 741} { + set chip GAL22V10 + set pin_mapping [dict create 1 "in\[0\]" 2 "in\[1\]" 3 "in\[2\]" 4 "in\[3\]" 5 "in\[4\]" 6 "in\[5\]" 7 "in\[6\]" 8 "in\[7\]" 9 "in\[8\]" 10 "in\[9\]" 11 "in\[10\]" 12 "in\[11\]" 13 "in\[12\]" 14 "io\[9\]" 15 "io\[8\]" 16 "io\[7\]" 17 "io\[6\]" 18 "io\[5\]" 19 "io\[4\]" 20 "io\[3\]" 21 "io\[2\]" 22 "io\[1\]" 23 "io\[0\]"] +} else { + puts "Error: Unknown chip for JEDEC file" + exit +} +puts "Chip found to be $chip" + +# Convert binary JEDEC file to hex for Verilog +exec xxd -ps -c 1 __temp.bin ${chip}_reg.hex +exec rm __temp.bin # Read and synthesize original Verilog read_verilog $verilog_files hierarchy -auto-top -flatten + tribuf synth +#yosys proc +#yosys memory +#clean -purge +flatten + splitnets -ports yosys rename -top __original select -module __original # Process PCF file and rename ports set used [list] -set pin_mapping [dict create 1 "clk" 2 "in\[0\]" 3 "in\[1\]" 4 "in\[2\]" 5 "in\[3\]" 6 "in\[4\]" 7 "in\[5\]" 8 "in\[6\]" 9 "in\[7\]" 11 "oe_n" 12 "io\[7\]" 13 "io\[6\]" 14 "io\[5\]" 15 "io\[4\]" 16 "io\[3\]" 17 "io\[2\]" 18 "io\[1\]" 19 "io\[0\]"] - set pcf_fp [open $pcf_file r] foreach line [split [read $pcf_fp] "\n"] { puts $line @@ -45,10 +65,15 @@ select -clear design -stash __original # Read and synthesize GAL model -read_verilog wrapper.v GAL16V8_reg.v -flatten +read_verilog ${chip}_wrapper.v ${chip}_reg.v + tribuf synth +#yosys proc +#yosys memory +#clean -purge +flatten + splitnets -ports select -module __wrapper @@ -56,7 +81,7 @@ select -module __wrapper foreach pin_name [dict values $pin_mapping] { if {[lsearch -exact $used $pin_name] >= 0} { puts "$pin_name is used" - } elseif {$pin_name == "oe_n"} { + } elseif {$pin_name == "oe_n" && $chip == "GAL16V8"} { puts "$pin_name is not used" # Enable registered outputs if net unused connect -set __oe_n '0 @@ -74,4 +99,5 @@ design -copy-from __original -as __original A:top equiv_make __original __wrapper equiv tribuf -formal equiv equiv_induct equiv +shell equiv_status -assert equiv diff --git a/testcases/olmc_test.pcf b/testcases/olmc_test.pcf index db28f8b..0ad6e45 100644 --- a/testcases/olmc_test.pcf +++ b/testcases/olmc_test.pcf @@ -1,7 +1,7 @@ set_io clk 1 set_io A 3 set_io B 4 -set_io AND 13 -set_io NAND 14 -set_io REG_AND 15 +set_io AND 14 +set_io NAND 15 +set_io REG_AND 17 set_io REG_NAND 16