3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-12-15 00:38:59 +00:00

Merge pull request #5496 from YosysHQ/emil/liberty-flop-loops

read_liberty: support loopy retention cells
This commit is contained in:
Emil J 2025-12-01 22:50:20 +01:00 committed by GitHub
commit 9871e9b17e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 415 additions and 99 deletions

View file

@ -5,8 +5,9 @@ module dff (D, CLK, Q);
output Q;
assign Q = IQ; // IQ
always @(posedge CLK) begin
// "(D)"
IQ <= D;
end
always @(posedge CLK) begin
IQN <= ~(D);
end
endmodule

View file

@ -41,6 +41,7 @@ module imux2 (A, B, S, Y);
endmodule
module dff (D, CLK, RESET, PRESET, Q, QN);
reg IQ, IQN;
wire IQ_clear, IQ_preset;
input D;
input CLK;
input RESET;
@ -49,25 +50,30 @@ module dff (D, CLK, RESET, PRESET, Q, QN);
assign Q = IQ; // "IQ"
output QN;
assign QN = IQN; // "IQN"
always @(posedge CLK, posedge RESET, posedge PRESET) begin
if ((RESET) && (PRESET)) begin
always @(posedge CLK, posedge IQ_clear, posedge IQ_preset) begin
if (IQ_clear) begin
IQ <= 0;
IQN <= 0;
end
else if (RESET) begin
IQ <= 0;
IQN <= 1;
end
else if (PRESET) begin
else if (IQ_preset) begin
IQ <= 1;
IQN <= 0;
end
else begin
// "D"
IQ <= D;
end
end
always @(posedge CLK, posedge IQ_clear, posedge IQ_preset) begin
if (IQ_preset) begin
IQN <= 0;
end
else if (IQ_clear) begin
IQN <= 1;
end
else begin
IQN <= ~(D);
end
end
assign IQ_clear = RESET;
assign IQ_preset = PRESET;
endmodule
module latch (D, G, Q, QN);
reg IQ, IQN;

View file

@ -0,0 +1,9 @@
read_liberty retention.lib
rename retention_cell retention_cell_lib
read_verilog retention.lib.verilogsim
proc
rename retention_cell retention_cell_vlog
async2sync
equiv_make retention_cell_lib retention_cell_vlog equiv
equiv_induct equiv
equiv_status -assert equiv

View file

@ -0,0 +1,57 @@
library (retention) {
delay_model : table_lookup;
voltage_unit : 1V;
current_unit : 1mA;
leakage_power_unit : 1nW;
time_unit : 1ns;
capacitive_load_unit (1, pf);
pulling_resistance_unit : 1kohm;
input_threshold_pct_rise : 50;
input_threshold_pct_fall : 50;
output_threshold_pct_rise : 50;
output_threshold_pct_fall : 50;
slew_lower_threshold_pct_rise : 30;
slew_upper_threshold_pct_rise : 70;
slew_upper_threshold_pct_fall : 70;
slew_lower_threshold_pct_fall : 30;
cell ("retention_cell") {
ff (Q1,QN1) {
clocked_on : "CK";
next_state : "(D * !SE + SI * SE)";
clear : "(((!B2B) * !Q2) + !RD)";
preset : "((!B2B) * Q2)";
clear_preset_var1 : "L";
clear_preset_var2 : "H";
}
latch (Q2,QN2) {
enable : "B1";
data_in : "Q1";
}
pin (B1) {
direction : input;
}
pin (B2B) {
direction : input;
}
pin (CK) {
clock : true;
direction : input;
}
pin (D) {
direction : input;
}
pin (Q) {
direction : output;
function : "Q1";
}
pin (RD) {
direction : input;
}
pin (SE) {
direction : input;
}
pin (SI) {
direction : input;
}
}
}

View file

@ -0,0 +1,42 @@
library(retention) {
cell("retention_cell") {
ff(Q1, QN1) {
clocked_on : "CK" ;
next_state : "(D * !SE + SI * SE)" ;
clear : "(((!B2B) * !Q2) + !RD)" ;
preset : "((!B2B) * Q2)" ;
clear_preset_var1 : "L" ;
clear_preset_var2 : "H" ;
}
latch(Q2, QN2) {
enable : "B1" ;
data_in : "Q1" ;
}
pin(B1) {
direction : input ;
}
pin(B2B) {
direction : input ;
}
pin(CK) {
clock : true ;
direction : input ;
}
pin(D) {
direction : input ;
}
pin(Q) {
direction : output ;
function : "Q1" ;
}
pin(RD) {
direction : input ;
}
pin(SE) {
direction : input ;
}
pin(SI) {
direction : input ;
}
}
}

View file

@ -0,0 +1,44 @@
module retention_cell (B1, B2B, CK, D, Q, RD, SE, SI);
reg Q1, QN1;
wire Q1_clear, Q1_preset;
reg Q2, QN2;
input B1;
input B2B;
input CK;
input D;
output Q;
assign Q = Q1; // "Q1"
input RD;
input SE;
input SI;
always @(posedge CK, posedge Q1_clear, posedge Q1_preset) begin
if (Q1_clear) begin
Q1 <= 0;
end
else if (Q1_preset) begin
Q1 <= 1;
end
else begin
Q1 <= ((D&(~SE))|(SI&SE));
end
end
always @(posedge CK, posedge Q1_clear, posedge Q1_preset) begin
if (Q1_clear) begin
QN1 <= 1;
end
else if (Q1_preset) begin
QN1 <= 0;
end
else begin
QN1 <= ~(((D&(~SE))|(SI&SE)));
end
end
assign Q1_clear = (((~B2B)&(~Q2))|(~RD));
assign Q1_preset = ((~B2B)&Q2);
always @* begin
if (B1) begin
Q2 <= Q1;
QN2 <= ~(Q1);
end
end
endmodule

View file

@ -4,8 +4,9 @@ module DFF (D, CK, Q);
input CK;
output Q;
always @(posedge CK) begin
// "D"
IQ <= D;
end
always @(posedge CK) begin
IQN <= ~(D);
end
endmodule

View file

@ -5,8 +5,9 @@ module dff1 (D, CLK, Q);
output Q;
assign Q = IQ; // IQ
always @(posedge CLK) begin
// !D
IQ <= (~D);
end
always @(posedge CLK) begin
IQN <= ~((~D));
end
endmodule
@ -17,8 +18,9 @@ module dff2 (D, CLK, Q);
output Q;
assign Q = IQ; // "IQ"
always @(posedge CLK) begin
// D '
IQ <= (~D);
end
always @(posedge CLK) begin
IQN <= ~((~D));
end
endmodule
@ -32,8 +34,9 @@ module dffe (D, EN, CLK, Q, QN);
output QN;
assign QN = IQN; // "IQN"
always @(negedge CLK) begin
// ( D & EN ) | ( IQ & ! EN )
IQ <= ((D&EN)|(IQ&(~EN)));
end
always @(negedge CLK) begin
IQN <= ~(((D&EN)|(IQ&(~EN))));
end
endmodule