aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/common
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/common')
-rw-r--r--techlibs/common/gen_fine_ffs.py49
-rw-r--r--techlibs/common/simcells.v284
-rw-r--r--techlibs/common/simlib.v121
-rw-r--r--techlibs/common/techmap.v41
4 files changed, 470 insertions, 25 deletions
diff --git a/techlibs/common/gen_fine_ffs.py b/techlibs/common/gen_fine_ffs.py
index 5d331e767..25c6ef171 100644
--- a/techlibs/common/gen_fine_ffs.py
+++ b/techlibs/common/gen_fine_ffs.py
@@ -133,6 +133,55 @@ endmodule
"""
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
+//- $_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - {L:0|1} a | a
+//- d {C:\\|/} - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_{C:N|P}{L:N|P}_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin
+ if (L == {L:0|1})
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q)
+//-
+//- A {C:negative|positive} edge D-type flip-flop with {L:negative|positive} polarity async load and {E:negative|positive}
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - {L:0|1} a - | a
+//- d {C:\\|/} - - {E:0|1} | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_{C:N|P}{L:N|P}{E:N|P}_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @({C:neg|pos}edge C or {L:neg|pos}edge L) begin
+ if (L == {L:0|1})
+ Q <= AD;
+ else if (E == {E:0|1})
+ Q <= D;
+end
+endmodule
+""",
+"""
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
//- $_DFFSR_{C:N|P}{S:N|P}{R:N|P}_ (C, S, R, D, Q)
//-
//- A {C:negative|positive} edge D-type flip-flop with {S:negative|positive} polarity set and {R:negative|positive}
diff --git a/techlibs/common/simcells.v b/techlibs/common/simcells.v
index 7d9bebe2a..ad1fdc817 100644
--- a/techlibs/common/simcells.v
+++ b/techlibs/common/simcells.v
@@ -1254,6 +1254,290 @@ endmodule
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
//-
+//- $_ALDFF_NN_ (D, C, L, AD, Q)
+//-
+//- A negative edge D-type flip-flop with negative polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 0 a | a
+//- d \ - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_NN_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(negedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFF_NP_ (D, C, L, AD, Q)
+//-
+//- A negative edge D-type flip-flop with positive polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 1 a | a
+//- d \ - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_NP_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(negedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFF_PN_ (D, C, L, AD, Q)
+//-
+//- A positive edge D-type flip-flop with negative polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 0 a | a
+//- d / - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_PN_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(posedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFF_PP_ (D, C, L, AD, Q)
+//-
+//- A positive edge D-type flip-flop with positive polarity async load.
+//-
+//- Truth table: D C L AD | Q
+//- ----------+---
+//- - - 1 a | a
+//- d / - - | d
+//- - - - - | q
+//-
+module \$_ALDFF_PP_ (D, C, L, AD, Q);
+input D, C, L, AD;
+output reg Q;
+always @(posedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NNN_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with negative polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d \ - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NNN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NNP_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with negative polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d \ - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NNP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NPN_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with positive polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d \ - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NPN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_NPP_ (D, C, L, AD, E, Q)
+//-
+//- A negative edge D-type flip-flop with positive polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d \ - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_NPP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(negedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PNN_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with negative polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d / - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PNN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PNP_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with negative polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 0 a - | a
+//- d / - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PNP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or negedge L) begin
+ if (L == 0)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PPN_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with positive polarity async load and negative
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d / - - 0 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PPN_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 0)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
+//- $_ALDFFE_PPP_ (D, C, L, AD, E, Q)
+//-
+//- A positive edge D-type flip-flop with positive polarity async load and positive
+//- polarity clock enable.
+//-
+//- Truth table: D C L AD E | Q
+//- ------------+---
+//- - - 1 a - | a
+//- d / - - 1 | d
+//- - - - - - | q
+//-
+module \$_ALDFFE_PPP_ (D, C, L, AD, E, Q);
+input D, C, L, AD, E;
+output reg Q;
+always @(posedge C or posedge L) begin
+ if (L == 1)
+ Q <= AD;
+ else if (E == 1)
+ Q <= D;
+end
+endmodule
+
+// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+//-
//- $_DFFSR_NNN_ (C, S, R, D, Q)
//-
//- A negative edge D-type flip-flop with negative polarity set and negative
diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v
index cf0839ebe..b14488ff4 100644
--- a/techlibs/common/simlib.v
+++ b/techlibs/common/simlib.v
@@ -1292,6 +1292,33 @@ endmodule
// --------------------------------------------------------
+module \$bmux (A, S, Y);
+
+parameter WIDTH = 0;
+parameter S_WIDTH = 0;
+
+input [(WIDTH << S_WIDTH)-1:0] A;
+input [S_WIDTH-1:0] S;
+output [WIDTH-1:0] Y;
+
+wire [WIDTH-1:0] bm0_out, bm1_out;
+
+generate
+ if (S_WIDTH > 1) begin:muxlogic
+ \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm0 (.A(A), .S(S[S_WIDTH-2:0]), .Y(bm0_out));
+ \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm1 (.A(A[(WIDTH << S_WIDTH)-1:WIDTH << (S_WIDTH - 1)]), .S(S[S_WIDTH-2:0]), .Y(bm1_out));
+ assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out;
+ end else if (S_WIDTH == 1) begin:simple
+ assign Y = S ? A[1] : A[0];
+ end else begin:passthru
+ assign Y = A;
+ end
+endgenerate
+
+endmodule
+
+// --------------------------------------------------------
+
module \$pmux (A, B, S, Y);
parameter WIDTH = 0;
@@ -1318,6 +1345,26 @@ end
endmodule
// --------------------------------------------------------
+
+module \$demux (A, S, Y);
+
+parameter WIDTH = 1;
+parameter S_WIDTH = 1;
+
+input [WIDTH-1:0] A;
+input [S_WIDTH-1:0] S;
+output [(WIDTH << S_WIDTH)-1:0] Y;
+
+genvar i;
+generate
+ for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices
+ assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0;
+ end
+endgenerate
+
+endmodule
+
+// --------------------------------------------------------
`ifndef SIMLIB_NOLUT
module \$lut (A, Y);
@@ -1326,30 +1373,9 @@ parameter WIDTH = 0;
parameter LUT = 0;
input [WIDTH-1:0] A;
-output reg Y;
-
-wire lut0_out, lut1_out;
+output Y;
-generate
- if (WIDTH <= 1) begin:simple
- assign {lut1_out, lut0_out} = LUT;
- end else begin:complex
- \$lut #( .WIDTH(WIDTH-1), .LUT(LUT ) ) lut0 ( .A(A[WIDTH-2:0]), .Y(lut0_out) );
- \$lut #( .WIDTH(WIDTH-1), .LUT(LUT >> (2**(WIDTH-1))) ) lut1 ( .A(A[WIDTH-2:0]), .Y(lut1_out) );
- end
-
- if (WIDTH > 0) begin:lutlogic
- always @* begin
- casez ({A[WIDTH-1], lut0_out, lut1_out})
- 3'b?11: Y = 1'b1;
- 3'b?00: Y = 1'b0;
- 3'b0??: Y = lut0_out;
- 3'b1??: Y = lut1_out;
- default: Y = 1'bx;
- endcase
- end
- end
-endgenerate
+\$bmux #(.WIDTH(1), .S_WIDTH(WIDTH)) mux(.A(LUT), .S(A), .Y(Y));
endmodule
@@ -1890,6 +1916,30 @@ endmodule
// --------------------------------------------------------
+module \$aldff (CLK, ALOAD, AD, D, Q);
+
+parameter WIDTH = 0;
+parameter CLK_POLARITY = 1'b1;
+parameter ALOAD_POLARITY = 1'b1;
+
+input CLK, ALOAD;
+input [WIDTH-1:0] AD;
+input [WIDTH-1:0] D;
+output reg [WIDTH-1:0] Q;
+wire pos_clk = CLK == CLK_POLARITY;
+wire pos_aload = ALOAD == ALOAD_POLARITY;
+
+always @(posedge pos_clk, posedge pos_aload) begin
+ if (pos_aload)
+ Q <= AD;
+ else
+ Q <= D;
+end
+
+endmodule
+
+// --------------------------------------------------------
+
module \$sdff (CLK, SRST, D, Q);
parameter WIDTH = 0;
@@ -1939,6 +1989,31 @@ endmodule
// --------------------------------------------------------
+module \$aldffe (CLK, ALOAD, AD, EN, D, Q);
+
+parameter WIDTH = 0;
+parameter CLK_POLARITY = 1'b1;
+parameter EN_POLARITY = 1'b1;
+parameter ALOAD_POLARITY = 1'b1;
+
+input CLK, ALOAD, EN;
+input [WIDTH-1:0] D;
+input [WIDTH-1:0] AD;
+output reg [WIDTH-1:0] Q;
+wire pos_clk = CLK == CLK_POLARITY;
+wire pos_aload = ALOAD == ALOAD_POLARITY;
+
+always @(posedge pos_clk, posedge pos_aload) begin
+ if (pos_aload)
+ Q <= AD;
+ else if (EN == EN_POLARITY)
+ Q <= D;
+end
+
+endmodule
+
+// --------------------------------------------------------
+
module \$sdffe (CLK, SRST, EN, D, Q);
parameter WIDTH = 0;
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v
index d3dc85f24..91d385b80 100644
--- a/techlibs/common/techmap.v
+++ b/techlibs/common/techmap.v
@@ -59,12 +59,12 @@ module _90_simplemap_compare_ops;
endmodule
(* techmap_simplemap *)
-(* techmap_celltype = "$pos $slice $concat $mux $tribuf" *)
+(* techmap_celltype = "$pos $slice $concat $mux $tribuf $bmux" *)
module _90_simplemap_various;
endmodule
(* techmap_simplemap *)
-(* techmap_celltype = "$sr $ff $dff $dffe $adff $adffe $sdff $sdffe $sdffce $dffsr $dffsre $dlatch $adlatch $dlatchsr" *)
+(* techmap_celltype = "$sr $ff $dff $dffe $adff $adffe $aldff $aldffe $sdff $sdffe $sdffce $dffsr $dffsre $dlatch $adlatch $dlatchsr" *)
module _90_simplemap_registers;
endmodule
@@ -597,6 +597,43 @@ module _90_pmux (A, B, S, Y);
assign Y = |S ? Y_B : A;
endmodule
+// --------------------------------------------------------
+// Demultiplexers
+// --------------------------------------------------------
+
+(* techmap_celltype = "$demux" *)
+module _90_demux (A, S, Y);
+ parameter WIDTH = 1;
+ parameter S_WIDTH = 1;
+
+ (* force_downto *)
+ input [WIDTH-1:0] A;
+ (* force_downto *)
+ input [S_WIDTH-1:0] S;
+ (* force_downto *)
+ output [(WIDTH << S_WIDTH)-1:0] Y;
+
+ generate
+ if (S_WIDTH == 0) begin
+ assign Y = A;
+ end else if (S_WIDTH == 1) begin
+ assign Y[0+:WIDTH] = S ? 0 : A;
+ assign Y[WIDTH+:WIDTH] = S ? A : 0;
+ end else begin
+ localparam SPLIT = S_WIDTH / 2;
+ wire [(1 << (S_WIDTH-SPLIT))-1:0] YH;
+ wire [(1 << SPLIT)-1:0] YL;
+ $demux #(.WIDTH(1), .S_WIDTH(SPLIT)) lo (.A(1'b1), .S(S[SPLIT-1:0]), .Y(YL));
+ $demux #(.WIDTH(1), .S_WIDTH(S_WIDTH-SPLIT)) hi (.A(1'b1), .S(S[S_WIDTH-1:SPLIT]), .Y(YH));
+ genvar i;
+ for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin
+ localparam [S_WIDTH-1:0] IDX = i;
+ assign Y[i*WIDTH+:WIDTH] = (YL[IDX[SPLIT-1:0]] & YH[IDX[S_WIDTH-1:SPLIT]]) ? A : 0;
+ end
+ end
+ endgenerate
+endmodule
+
// --------------------------------------------------------
// LUTs