mirror of https://github.com/YosysHQ/yosys.git
gowin: add hardware latch support (DL/DLN/DLC/DLP variants)
Add simulation models, techmap, and dfflegalize rules for Gowin DL-series latch primitives. Latches use the same physical BEL as DFFs with REGMODE set to LATCH. All 12 variants are supported: DL, DLE, DLN, DLNE, DLC, DLCE, DLNC, DLNCE, DLP, DLPE, DLNP, DLNPE.
This commit is contained in:
parent
1d3f9b7905
commit
8e97f34d31
|
|
@ -3,6 +3,7 @@ OBJS += techlibs/gowin/synth_gowin.o
|
|||
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_map.v))
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_sim.v))
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_latch.v))
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_xtra_gw1n.v))
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_xtra_gw2a.v))
|
||||
$(eval $(call add_share_file,share/gowin,techlibs/gowin/cells_xtra_gw5a.v))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
`default_nettype none
|
||||
|
||||
// DL D Latch with Positive Gate
|
||||
module \$_DLATCH_P_ (input E, D, output Q);
|
||||
DL _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(E));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// DLN D Latch with Negative Gate
|
||||
module \$_DLATCH_N_ (input E, D, output Q);
|
||||
DLN _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(E));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// DLC D Latch with Positive Gate and Asynchronous Clear
|
||||
module \$_DLATCH_PP0_ (input E, R, D, output Q);
|
||||
DLC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(E), .CLEAR(R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// DLNC D Latch with Negative Gate and Asynchronous Clear
|
||||
module \$_DLATCH_NP0_ (input E, R, D, output Q);
|
||||
DLNC _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(E), .CLEAR(R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// DLP D Latch with Positive Gate and Asynchronous Preset
|
||||
module \$_DLATCH_PP1_ (input E, R, D, output Q);
|
||||
DLP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(E), .PRESET(R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
||||
// DLNP D Latch with Negative Gate and Asynchronous Preset
|
||||
module \$_DLATCH_NP1_ (input E, R, D, output Q);
|
||||
DLNP _TECHMAP_REPLACE_ (.D(D), .Q(Q), .CLK(E), .PRESET(R));
|
||||
wire _TECHMAP_REMOVEINIT_Q_ = 1;
|
||||
endmodule
|
||||
|
|
@ -540,6 +540,113 @@ module DFFNCE (output reg Q, input D, CLK, CE, CLEAR);
|
|||
end
|
||||
endmodule // DFFNCE (negative clock edge; asynchronous clear; clock enable)
|
||||
|
||||
// Latch sim cells
|
||||
// Gate signal uses CLK port name to match the physical DFF BEL pin
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DL (output reg Q, input D, CLK);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (CLK) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLN (output reg Q, input D, CLK);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (!CLK) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLE (output reg Q, input D, CLK, CE);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (CLK && CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLNE (output reg Q, input D, CLK, CE);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (!CLK && CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLC (output reg Q, input D, CLK, CLEAR);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (CLEAR) Q <= 1'b0;
|
||||
else if (CLK) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLCE (output reg Q, input D, CLK, CE, CLEAR);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (CLEAR) Q <= 1'b0;
|
||||
else if (CLK && CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLNC (output reg Q, input D, CLK, CLEAR);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (CLEAR) Q <= 1'b0;
|
||||
else if (!CLK) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLNCE (output reg Q, input D, CLK, CE, CLEAR);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (CLEAR) Q <= 1'b0;
|
||||
else if (!CLK && CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLP (output reg Q, input D, CLK, PRESET);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (PRESET) Q <= 1'b1;
|
||||
else if (CLK) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLPE (output reg Q, input D, CLK, CE, PRESET);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (PRESET) Q <= 1'b1;
|
||||
else if (CLK && CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLNP (output reg Q, input D, CLK, PRESET);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (PRESET) Q <= 1'b1;
|
||||
else if (!CLK) Q <= D;
|
||||
endmodule
|
||||
|
||||
(* lib_whitebox *)
|
||||
module DLNPE (output reg Q, input D, CLK, CE, PRESET);
|
||||
parameter [0:0] INIT = 1'b0;
|
||||
initial Q = INIT;
|
||||
always @*
|
||||
if (PRESET) Q <= 1'b1;
|
||||
else if (!CLK && CE) Q <= D;
|
||||
endmodule
|
||||
|
||||
// TODO add more DFF sim cells
|
||||
|
||||
module VCC(output V);
|
||||
|
|
|
|||
|
|
@ -340,17 +340,18 @@ struct SynthGowinPass : public ScriptPass
|
|||
run("opt_clean");
|
||||
if (family == "gw5a") {
|
||||
if (strict_gw5a_dffs) {
|
||||
run("dfflegalize -cell $_SDFFE_PP?P_ r -cell $_DFFE_PP?P_ r");
|
||||
run("dfflegalize -cell $_SDFFE_PP?P_ r -cell $_DFFE_PP?P_ r -cell $_DLATCH_?_ x -cell $_DLATCH_?P?_ x");
|
||||
} else {
|
||||
run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFFE_PP?P_ r -cell $_DFFE_PP?P_ r");
|
||||
run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFFE_PP?P_ r -cell $_DFFE_PP?P_ r -cell $_DLATCH_?_ x -cell $_DLATCH_?P?_ x");
|
||||
}
|
||||
} else {
|
||||
if (nodffe)
|
||||
run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFF_?P?_ r -cell $_DFF_?P?_ r");
|
||||
run("dfflegalize -cell $_DFF_?_ 0 -cell $_SDFF_?P?_ r -cell $_DFF_?P?_ r -cell $_DLATCH_?_ x -cell $_DLATCH_?P?_ x");
|
||||
else
|
||||
run("dfflegalize -cell $_DFF_?_ 0 -cell $_DFFE_?P_ 0 -cell $_SDFF_?P?_ r -cell $_SDFFE_?P?P_ r -cell $_DFF_?P?_ r -cell $_DFFE_?P?P_ r");
|
||||
run("dfflegalize -cell $_DFF_?_ 0 -cell $_DFFE_?P_ 0 -cell $_SDFF_?P?_ r -cell $_SDFFE_?P?P_ r -cell $_DFF_?P?_ r -cell $_DFFE_?P?P_ r -cell $_DLATCH_?_ x -cell $_DLATCH_?P?_ x");
|
||||
}
|
||||
run("techmap -map +/gowin/cells_map.v");
|
||||
run("techmap -map +/gowin/cells_latch.v");
|
||||
run("opt_expr -mux_undef");
|
||||
run("simplemap");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
read_verilog ../common/latches.v
|
||||
design -save read
|
||||
|
||||
hierarchy -top latchp
|
||||
proc
|
||||
equiv_opt -async2sync -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check
|
||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||
cd latchp # Constrain all select calls below inside the top module
|
||||
select -assert-count 1 t:DL
|
||||
select -assert-count 3 t:IBUF
|
||||
select -assert-count 1 t:OBUF
|
||||
|
||||
select -assert-none t:DL t:IBUF t:OBUF %% t:* %D
|
||||
|
||||
design -load read
|
||||
hierarchy -top latchn
|
||||
proc
|
||||
equiv_opt -async2sync -assert -map +/gowin/cells_sim.v synth_gowin # equivalency check
|
||||
design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design)
|
||||
cd latchn # Constrain all select calls below inside the top module
|
||||
select -assert-count 1 t:DLN
|
||||
select -assert-count 3 t:IBUF
|
||||
select -assert-count 1 t:OBUF
|
||||
|
||||
select -assert-none t:DLN t:IBUF t:OBUF %% t:* %D
|
||||
Loading…
Reference in New Issue