mirror of
https://github.com/annoyatron255/yosys4gal.git
synced 2024-12-22 18:52:23 +00:00
176 lines
3.9 KiB
Coq
176 lines
3.9 KiB
Coq
|
`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
|