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