Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quicklogic 'qlf_k4n8' device support in yosys #92

Open
wants to merge 2 commits into
base: master+wip
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ bumpversion:
ABCREV = 341db25
ABCPULL = 1
ABCURL ?= https://github.com/YosysHQ/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1
ABCMKARGS ?= CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1

# set ABCEXTERNAL = <abc-command> to use an external ABC instance
# Note: The in-tree ABC (yosys-abc) will not be installed when ABCEXTERNAL is set.
Expand Down
7 changes: 7 additions & 0 deletions techlibs/quicklogic/Makefile.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

OBJS += techlibs/quicklogic/synth_quicklogic.o

$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/cells_sim.v))
$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/qlf_k4n8_cells_sim.v))
$(eval $(call add_share_file,share/quicklogic,techlibs/quicklogic/qlf_k4n8_arith_map.v))

24 changes: 24 additions & 0 deletions techlibs/quicklogic/cells_sim.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

module inv(output Q, input A);
assign Q = A ? 0 : 1;
endmodule

module buff(output Q, input A);
assign Q = A;
endmodule

module logic_0(output a);
assign a = 0;
endmodule

module logic_1(output a);
assign a = 1;
endmodule

(* blackbox *)
module gclkbuff (input A, output Z);

assign Z = A;

endmodule

135 changes: 135 additions & 0 deletions techlibs/quicklogic/qlf_k4n8_arith_map.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
(* techmap_celltype = "$alu" *)
module _80_quicklogic_alu (A, B, CI, BI, X, Y, CO);
parameter A_SIGNED = 0;
parameter B_SIGNED = 0;
parameter A_WIDTH = 1;
parameter B_WIDTH = 1;
parameter Y_WIDTH = 1;

parameter _TECHMAP_CONSTMSK_CI_ = 0;
parameter _TECHMAP_CONSTVAL_CI_ = 0;

(* force_downto *)
input [A_WIDTH-1:0] A;
(* force_downto *)
input [B_WIDTH-1:0] B;
(* force_downto *)
output [Y_WIDTH-1:0] X, Y;

input CI, BI;
(* force_downto *)
output [Y_WIDTH-1:0] CO;

wire _TECHMAP_FAIL_ = Y_WIDTH <= 2;

(* force_downto *)
wire [Y_WIDTH-1:0] A_buf, B_buf;
\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf));
\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf));

(* force_downto *)
wire [Y_WIDTH-1:0] AA = A_buf;
(* force_downto *)
wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf;
(* force_downto *)
wire [Y_WIDTH-1:0] C;

assign CO = C[Y_WIDTH-1];

genvar i;
generate for (i = 0; i < Y_WIDTH; i = i + 1) begin: slice

wire ci;
wire co;

// First in chain
generate if (i == 0) begin

// CI connected to a constant
if (_TECHMAP_CONSTMSK_CI_ == 1) begin

localparam INIT = (_TECHMAP_CONSTVAL_CI_ == 0) ?
16'b0110_0000_0000_0001 :
16'b1001_0000_0000_0111;

// LUT4 configured as 1-bit adder with CI=const
adder_lut4 #(
.LUT(INIT),
.IN2_IS_CIN(1'b0)
) lut_ci_adder (
.in({AA[i], BB[i], 1'b0, 1'b0}),
.cin(),
.lut4_out(Y[i]),
.cout(ci)
);

// CI connected to a non-const driver
end else begin

// LUT4 configured as passthrough to drive CI of the next stage
adder_lut4 #(
.LUT(16'b1100_0000_0000_0011),
.IN2_IS_CIN(1'b0)
) lut_ci (
.in({1'b0,CI,1'b0,1'b0}),
.cin(),
.lut4_out(),
.cout(ci)
);
end

// Not first in chain
end else begin
assign ci = C[i-1];

end endgenerate

// ....................................................

// Single 1-bit adder, mid-chain adder or non-const CI
// adder
generate if ((i == 0 && _TECHMAP_CONSTMSK_CI_ == 0) || (i > 0)) begin

// LUT4 configured as full 1-bit adder
adder_lut4 #(
.LUT(16'b0110_1001_0110_0001),
.IN2_IS_CIN(1'b1)
) lut_adder (
.in({AA[i], BB[i], 1'b0, 1'b0}),
.cin(ci),
.lut4_out(Y[i]),
.cout(co)
);
end else begin
assign co = ci;

end endgenerate

// ....................................................

// Last in chain
generate if (i == Y_WIDTH-1) begin

// LUT4 configured for passing its CI input to output. This should
// get pruned if the actual CO port is not connected anywhere.
adder_lut4 #(
.LUT(16'b0000_1111_0000_1111),
.IN2_IS_CIN(1'b1)
) lut_co (
.in({1'b0, co, 1'b0, 1'b0}),
.cin(co),
.lut4_out(C[i]),
.cout()
);
// Not last in chain
end else begin
assign C[i] = co;

end endgenerate

end: slice
endgenerate

/* End implementation */
assign X = AA ^ BB;
endmodule
70 changes: 70 additions & 0 deletions techlibs/quicklogic/qlf_k4n8_cells_sim.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
(* abc9_box, lib_whitebox *)
module adder_lut4(
output lut4_out,
(* abc9_carry *)
output cout,
input [0:3] in,
(* abc9_carry *)
input cin
);
parameter [0:15] LUT=0;
parameter IN2_IS_CIN = 0;

wire [0:3] li = (IN2_IS_CIN) ? {in[0], in[1], cin, in[3]} : {in[0], in[1], in[2], in[3]};

// Output function
wire [0:7] s1 = li[0] ?
{LUT[1], LUT[3], LUT[5], LUT[7], LUT[9], LUT[11], LUT[13], LUT[15]}:
{LUT[0], LUT[2], LUT[4], LUT[6], LUT[8], LUT[10], LUT[12], LUT[14]};

wire [0:3] s2 = li[1] ? {s1[1], s1[3], s1[5], s1[7]} :
{s1[0], s1[2], s1[4], s1[6]};

wire [0:1] s3 = li[2] ? {s2[1], s2[3]} : {s2[0], s2[2]};

assign lut4_out = li[3] ? s3[1] : s3[0];

// Carry out function
assign cout = (s2[2]) ? cin : s2[3];
endmodule

(* abc9_lut=1, lib_whitebox *)
module frac_lut4(
input [0:3] in,
output [0:1] lut2_out,
output lut4_out
);
parameter [0:15] LUT = 0;

// Effective LUT input
wire [0:3] li = in;

// Output function
wire [0:7] s1 = li[0] ?
{LUT[1], LUT[3], LUT[5], LUT[7], LUT[9], LUT[11], LUT[13], LUT[15]}:
{LUT[0], LUT[2], LUT[4], LUT[6], LUT[8], LUT[10], LUT[12], LUT[14]};

wire [0:3] s2 = li[1] ? {s1[1], s1[3], s1[5], s1[7]} :
{s1[0], s1[2], s1[4], s1[6]};

wire [0:1] s3 = li[2] ? {s2[1], s2[3]} : {s2[0], s2[2]};

assign lut2_out[0] = s2[2];
assign lut2_out[1] = s2[3];

assign lut4_out = li[3] ? s3[1] : s3[0];

endmodule

(* abc9_flop, lib_whitebox *)
module scff(
output reg Q,
input D,
input clk
);
parameter [0:0] INIT = 1'b0;
initial Q = INIT;

always @(posedge clk)
Q <= D;
endmodule
Loading