aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/synth/ghdlsynth_gates.h11
-rw-r--r--src/synth/netlists-builders.adb35
-rw-r--r--src/synth/netlists-builders.ads6
-rw-r--r--src/synth/netlists-disp_vhdl.adb73
-rw-r--r--src/synth/netlists-gates.ads17
-rw-r--r--src/synth/netlists-inference.adb19
-rw-r--r--src/synth/synth-expr.adb13
-rw-r--r--src/synth/synth-oper.adb13
-rw-r--r--src/synth/synth-stmts.adb4
9 files changed, 118 insertions, 73 deletions
diff --git a/src/synth/ghdlsynth_gates.h b/src/synth/ghdlsynth_gates.h
index fd45445a2..03bd87499 100644
--- a/src/synth/ghdlsynth_gates.h
+++ b/src/synth/ghdlsynth_gates.h
@@ -81,11 +81,12 @@ enum Module_Id {
Id_Mem_Rd_Sync = 77,
Id_Mem_Wr_Sync = 78,
Id_Mem_Multiport = 79,
- Id_Edge = 80,
- Id_Assert = 81,
- Id_Assume = 82,
- Id_Cover = 83,
- Id_Assert_Cover = 84,
+ Id_Posedge = 80,
+ Id_Negedge = 81,
+ Id_Assert = 82,
+ Id_Assume = 83,
+ Id_Cover = 84,
+ Id_Assert_Cover = 85,
Id_Allconst = 90,
Id_Anyconst = 91,
Id_Allseq = 92,
diff --git a/src/synth/netlists-builders.adb b/src/synth/netlists-builders.adb
index ac1115af7..15d570a70 100644
--- a/src/synth/netlists-builders.adb
+++ b/src/synth/netlists-builders.adb
@@ -385,19 +385,22 @@ package body Netlists.Builders is
Set_Ports_Desc (Res, Inputs (0 .. 1), Outputs (0 .. 0));
end Create_Memory_Modules;
- procedure Create_Edge_Module (Ctxt : Context_Acc;
- Res : out Module;
- Name : Name_Id)
-
+ procedure Create_Edge_Module (Ctxt : Context_Acc)
is
Outputs : Port_Desc_Array (0 .. 0);
Inputs : Port_Desc_Array (0 .. 0);
begin
- Res := New_User_Module
- (Ctxt.Design, New_Sname_Artificial (Name, No_Sname), Id_Edge, 1, 1, 0);
+ Ctxt.M_Posedge := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Name_Posedge, No_Sname),
+ Id_Posedge, 1, 1, 0);
Inputs := (0 => Create_Input ("i", 1));
Outputs := (0 => Create_Output ("o", 1));
- Set_Ports_Desc (Res, Inputs, Outputs);
+ Set_Ports_Desc (Ctxt.M_Posedge, Inputs, Outputs);
+
+ Ctxt.M_Negedge := New_User_Module
+ (Ctxt.Design, New_Sname_Artificial (Name_Negedge, No_Sname),
+ Id_Negedge, 1, 1, 0);
+ Set_Ports_Desc (Ctxt.M_Negedge, Inputs, Outputs);
end Create_Edge_Module;
procedure Create_Mux_Modules (Ctxt : Context_Acc)
@@ -707,7 +710,7 @@ package body Netlists.Builders is
Create_Monadic_Module (Design, Res.M_Reduce (Id_Red_And),
Get_Identifier ("red_and"), Id_Red_And);
- Create_Edge_Module (Res, Res.M_Edge, Name_Edge);
+ Create_Edge_Module (Res);
Create_Mux_Modules (Res);
Create_Objects_Module (Res);
@@ -932,19 +935,31 @@ package body Netlists.Builders is
return Inst;
end Build_Const_Log;
- function Build_Edge (Ctxt : Context_Acc; Src : Net) return Net
+ function Build_Edge (Ctxt : Context_Acc; M : Module; Src : Net) return Net
is
pragma Assert (Get_Width (Src) = 1);
Inst : Instance;
O : Net;
begin
- Inst := New_Internal_Instance (Ctxt, Ctxt.M_Edge);
+ Inst := New_Internal_Instance (Ctxt, M);
O := Get_Output (Inst, 0);
pragma Assert (Get_Width (O) = 1);
Connect (Get_Input (Inst, 0), Src);
return O;
end Build_Edge;
+ pragma Inline (Build_Edge);
+
+ function Build_Posedge (Ctxt : Context_Acc; Src : Net) return Net is
+ begin
+ return Build_Edge (Ctxt, Ctxt.M_Posedge, Src);
+ end Build_Posedge;
+
+ function Build_Negedge (Ctxt : Context_Acc; Src : Net) return Net is
+ begin
+ return Build_Edge (Ctxt, Ctxt.M_Negedge, Src);
+ end Build_Negedge;
+
function Build_Mux2 (Ctxt : Context_Acc;
Sel : Net;
I0, I1 : Net) return Net
diff --git a/src/synth/netlists-builders.ads b/src/synth/netlists-builders.ads
index 5c67384be..a58f1bba9 100644
--- a/src/synth/netlists-builders.ads
+++ b/src/synth/netlists-builders.ads
@@ -86,7 +86,8 @@ package Netlists.Builders is
function Build_Const_Log (Ctxt : Context_Acc;
W : Width) return Instance;
- function Build_Edge (Ctxt : Context_Acc; Src : Net) return Net;
+ function Build_Posedge (Ctxt : Context_Acc; Src : Net) return Net;
+ function Build_Negedge (Ctxt : Context_Acc; Src : Net) return Net;
function Build_Mux2 (Ctxt : Context_Acc;
Sel : Net;
@@ -222,7 +223,8 @@ private
M_Const_Z : Module;
M_Const_Bit : Module;
M_Const_Log : Module;
- M_Edge : Module;
+ M_Posedge : Module;
+ M_Negedge : Module;
M_Mux2 : Module;
M_Mux4 : Module;
M_Nop : Module;
diff --git a/src/synth/netlists-disp_vhdl.adb b/src/synth/netlists-disp_vhdl.adb
index 172e9d921..8fdffbdc5 100644
--- a/src/synth/netlists-disp_vhdl.adb
+++ b/src/synth/netlists-disp_vhdl.adb
@@ -507,7 +507,8 @@ package body Netlists.Disp_Vhdl is
return False;
end Need_Signal;
- type Conv_Type is (Conv_None, Conv_Slv, Conv_Unsigned, Conv_Signed);
+ type Conv_Type is
+ (Conv_None, Conv_Slv, Conv_Unsigned, Conv_Signed, Conv_Edge, Conv_Clock);
procedure Disp_Net_Expr (N : Net; Inst : Instance; Conv : Conv_Type)
is
@@ -542,12 +543,27 @@ package body Netlists.Disp_Vhdl is
Put ("signed'(");
Disp_Constant_Inline (Net_Inst);
Put (")");
+ when Conv_Edge
+ | Conv_Clock =>
+ -- Not expected: a constant is not an edge.
+ raise Internal_Error;
end case;
else
case Conv is
when Conv_None
| Conv_Slv =>
Disp_Net_Name (N);
+ when Conv_Edge =>
+ case Edge_Module_Id (Get_Id (Net_Inst)) is
+ when Id_Posedge =>
+ Put ("rising_edge (");
+ when Id_Negedge =>
+ Put ("falling_edge (");
+ end case;
+ Disp_Net_Name (Get_Input_Net (Net_Inst, 0));
+ Put (")");
+ when Conv_Clock =>
+ Disp_Net_Name (Get_Input_Net (Net_Inst, 0));
when Conv_Unsigned =>
Put ("unsigned");
if Get_Width (N) = 1 then
@@ -597,18 +613,25 @@ package body Netlists.Disp_Vhdl is
if C = '\' then
I := I + 1;
-- Conversion (optional).
- if S (I) = 'u' then
- Conv := Conv_Unsigned;
- I := I + 1;
- elsif S (I) = 's' then
- Conv := Conv_Signed;
- I := I + 1;
- elsif S (I) = 'f' then
- Conv := Conv_Slv;
- I := I + 1;
- else
- Conv := Conv_None;
- end if;
+ case S (I) is
+ when 'u' =>
+ Conv := Conv_Unsigned;
+ I := I + 1;
+ when 's' =>
+ Conv := Conv_Signed;
+ I := I + 1;
+ when 'f' =>
+ Conv := Conv_Slv;
+ I := I + 1;
+ when 'e' =>
+ Conv := Conv_Edge;
+ I := I + 1;
+ when 'c' =>
+ Conv := Conv_Clock;
+ I := I + 1;
+ when others =>
+ Conv := Conv_None;
+ end case;
Idx := Character'Pos (S (I + 1)) - Character'Pos ('0');
case S (I) is
when 'o' =>
@@ -630,6 +653,9 @@ package body Netlists.Disp_Vhdl is
Put_Uns32 (V);
when Conv_Signed =>
Put_Int32 (To_Int32 (V));
+ when Conv_Edge
+ | Conv_Clock =>
+ raise Internal_Error;
end case;
when 'l' =>
pragma Assert (Idx = 0);
@@ -691,6 +717,8 @@ package body Netlists.Disp_Vhdl is
when Id_Mem_Wr_Sync =>
-- Clock
S := Get_Input_Net (Port_Inst, 2);
+ -- Strip the edge.
+ S := Get_Input_Net (Get_Net_Parent (S), 0);
Data_W := Get_Width (Get_Input_Net (Port_Inst, 4));
when Id_Mem_Rd =>
-- Address
@@ -699,6 +727,8 @@ package body Netlists.Disp_Vhdl is
when Id_Mem_Rd_Sync =>
-- Clock
S := Get_Input_Net (Port_Inst, 2);
+ -- Strip the edge.
+ S := Get_Input_Net (Get_Net_Parent (S), 0);
Data_W := Get_Width (Get_Output (Port_Inst, 1));
when Id_Memory
| Id_Memory_Init =>
@@ -750,7 +780,7 @@ package body Netlists.Disp_Vhdl is
case Get_Id (Port_Inst) is
when Id_Mem_Wr_Sync =>
Disp_Template
- (" if rising_edge(\i2) and (\fi3 = '1') then" & NL,
+ (" if \ei2 and (\fi3 = '1') then" & NL,
Port_Inst);
Disp_Template (" \o0 (", Mem);
Disp_Template ("to_integer (\ui1)) := \i4;" & NL, Port_Inst);
@@ -761,7 +791,7 @@ package body Netlists.Disp_Vhdl is
Disp_Template ("(to_integer (\ui1));" & NL, Port_Inst);
when Id_Mem_Rd_Sync =>
Disp_Template
- (" if rising_edge(\i2) and (\fi3 = '1') then" & NL,
+ (" if \ei2 and (\fi3 = '1') then" & NL,
Port_Inst);
Disp_Template (" \o1 <= ", Port_Inst);
Disp_Template ("\o0", Mem);
@@ -969,19 +999,19 @@ package body Netlists.Disp_Vhdl is
null;
when Id_Adff
| Id_Iadff =>
- Disp_Template (" process (\i0, \i2)" & NL &
+ Disp_Template (" process (\ci0, \i2)" & NL &
" begin" & NL &
" if \i2 = '1' then" & NL &
" \o0 <= \i3;" & NL &
- " elsif rising_edge (\i0) then" & NL &
+ " elsif \ei0 then" & NL &
" \o0 <= \i1;" & NL &
" end if;" & NL &
" end process;" & NL, Inst);
when Id_Dff
| Id_Idff =>
- Disp_Template (" process (\i0)" & NL &
+ Disp_Template (" process (\ci0)" & NL &
" begin" & NL &
- " if rising_edge (\i0) then" & NL &
+ " if \ei0 then" & NL &
" \o0 <= \i1;" & NL &
" end if;" & NL &
" end process;" & NL, Inst);
@@ -1202,9 +1232,12 @@ package body Netlists.Disp_Vhdl is
(" \o0 <= \i0; -- reduce and" & NL, Inst);
end if;
end;
- when Id_Edge =>
+ when Id_Posedge =>
Disp_Template
(" \o0 <= '1' when rising_edge (\i0) else '0';" & NL, Inst);
+ when Id_Negedge =>
+ Disp_Template
+ (" \o0 <= '1' when falling_edge (\i0) else '0';" & NL, Inst);
when Id_Assert =>
Disp_Template
(" \l0: assert \i0 = '1' severity error;" & NL, Inst);
diff --git a/src/synth/netlists-gates.ads b/src/synth/netlists-gates.ads
index 04920b224..8dcb65cce 100644
--- a/src/synth/netlists-gates.ads
+++ b/src/synth/netlists-gates.ads
@@ -275,19 +275,20 @@ package Netlists.Gates is
-- Virtual gate to gather 2 dffs of a multiport memory.
Id_Mem_Multiport : constant Module_Id := 79;
- -- Positive/rising edge detector. This is a pseudo gate.
- -- A negative edge detector can be made using by negating the clock before
- -- the detector.
- Id_Edge : constant Module_Id := 80;
+ -- Positive/rising edge and negative/falling edge detector.
+ -- These are pseudo gates.
+ Id_Posedge : constant Module_Id := 80;
+ Id_Negedge : constant Module_Id := 81;
+ subtype Edge_Module_Id is Module_Id range Id_Posedge .. Id_Negedge;
-- Input signal must always be true.
- Id_Assert : constant Module_Id := 81;
- Id_Assume : constant Module_Id := 82;
+ Id_Assert : constant Module_Id := 82;
+ Id_Assume : constant Module_Id := 83;
-- Input is true when a sequence is covered.
- Id_Cover : constant Module_Id := 83;
+ Id_Cover : constant Module_Id := 84;
-- Use to cover the precedent of an assertion.
- Id_Assert_Cover : constant Module_Id := 84;
+ Id_Assert_Cover : constant Module_Id := 85;
-- Formal gates.
Id_Allconst : constant Module_Id := 90;
diff --git a/src/synth/netlists-inference.adb b/src/synth/netlists-inference.adb
index b0a660ec5..1155a6047 100644
--- a/src/synth/netlists-inference.adb
+++ b/src/synth/netlists-inference.adb
@@ -83,7 +83,7 @@ package body Netlists.Inference is
Inst : constant Instance := Get_Net_Parent (N);
begin
case Get_Id (Inst) is
- when Id_Edge =>
+ when Edge_Module_Id =>
return True;
when Id_And =>
-- Assume the condition is canonicalized, ie of the form:
@@ -160,7 +160,7 @@ package body Netlists.Inference is
Inst0 : constant Instance := Get_Net_Parent (N0);
begin
case Get_Id (Inst0) is
- when Id_Edge =>
+ when Edge_Module_Id =>
null;
when Id_And =>
Extract_Clock_And (Ctxt, Inst0);
@@ -175,7 +175,7 @@ package body Netlists.Inference is
N3 : constant Net := Get_Driver (I3);
Inst3 : constant Instance := Get_Net_Parent (N3);
begin
- if Get_Id (Inst3) = Id_Edge then
+ if Get_Id (Inst3) in Edge_Module_Id then
declare
Can_Rotate : constant Boolean :=
Has_One_Connection (N0);
@@ -213,7 +213,7 @@ package body Netlists.Inference is
Inst0 : constant Instance := Get_Net_Parent (N0);
begin
case Get_Id (Inst0) is
- when Id_Edge =>
+ when Edge_Module_Id =>
-- Swap inputs 0 and 1.
declare
I1 : constant Input := Get_Input (Inst, 0);
@@ -236,7 +236,7 @@ package body Netlists.Inference is
I3 : constant Input := Get_Input (Inst0, 0);
N3 : constant Net := Get_Driver (I3);
begin
- if Get_Id (Get_Net_Parent (N3)) = Id_Edge then
+ if Get_Id (Get_Net_Parent (N3)) in Edge_Module_Id then
declare
Can_Rotate : constant Boolean :=
Has_One_Connection (N0);
@@ -275,9 +275,8 @@ package body Netlists.Inference is
Enable := No_Net;
case Get_Id (Inst) is
- when Id_Edge =>
- -- Get rid of the edge gate, just return the signal.
- Clk := Get_Input_Net (Inst, 0);
+ when Edge_Module_Id =>
+ Clk := N;
when Id_And =>
-- Canonicalize conditions.
Extract_Clock_And (Ctxt, Inst);
@@ -287,12 +286,12 @@ package body Netlists.Inference is
I0 : constant Net := Get_Input_Net (Inst, 0);
Inst0 : constant Instance := Get_Net_Parent (I0);
begin
- if Get_Id (Inst0) = Id_Edge then
+ if Get_Id (Inst0) in Edge_Module_Id then
-- INST is clearly not synthesizable (boolean operation on
-- an edge). Will be removed at the end by
-- remove_unused_instances. Do not remove it now as its
-- output may be used by other nets.
- Clk := Get_Input_Net (Inst0, 0);
+ Clk := I0;
Enable := Get_Input_Net (Inst, 1);
return;
end if;
diff --git a/src/synth/synth-expr.adb b/src/synth/synth-expr.adb
index ef1d4cdab..a256cbe09 100644
--- a/src/synth/synth-expr.adb
+++ b/src/synth/synth-expr.adb
@@ -1510,19 +1510,19 @@ package body Synth.Expr is
Clk := Get_Net (Synth_Name (Syn_Inst, Prefix));
if Get_Kind (Expr) /= Iir_Kind_Equality_Operator then
Error_Msg_Synth (+Expr, "ill-formed clock-level, '=' expected");
- return Build_Edge (Build_Context, Clk);
+ return Build_Posedge (Build_Context, Clk);
end if;
Imp := Get_Implementation (Expr);
if Get_Implicit_Definition (Imp) /= Iir_Predefined_Enum_Equality then
Error_Msg_Synth (+Expr, "ill-formed clock-level, '=' expected");
- return Build_Edge (Build_Context, Clk);
+ return Build_Posedge (Build_Context, Clk);
end if;
Left := Get_Left (Expr);
Right := Get_Right (Expr);
if Get_Kind (Right) /= Iir_Kind_Character_Literal then
Error_Msg_Synth
(+Expr, "ill-formed clock-level, '0' or '1' expected");
- return Build_Edge (Build_Context, Clk);
+ return Build_Posedge (Build_Context, Clk);
end if;
Lit := Get_Named_Entity (Right);
if Lit = Vhdl.Std_Package.Bit_0
@@ -1542,10 +1542,11 @@ package body Synth.Expr is
Error_Msg_Synth
(+Left, "clock signal name doesn't match");
end if;
- if not Posedge then
- Clk := Build_Monadic (Build_Context, Id_Not, Clk);
+ if Posedge then
+ return Build_Posedge (Build_Context, Clk);
+ else
+ return Build_Negedge (Build_Context, Clk);
end if;
- return Build_Edge (Build_Context, Clk);
end Extract_Clock_Level;
-- Try to match: clk'event and clk = X
diff --git a/src/synth/synth-oper.adb b/src/synth/synth-oper.adb
index 4845c6237..819331e39 100644
--- a/src/synth/synth-oper.adb
+++ b/src/synth/synth-oper.adb
@@ -1500,22 +1500,17 @@ package body Synth.Oper is
case Def is
when Iir_Predefined_Ieee_1164_Rising_Edge =>
declare
- Clk : Net;
Edge : Net;
begin
- Clk := Get_Net (L);
- Edge := Build_Edge (Ctxt, Clk);
- return Create_Value_Net (Edge, Boolean_Type);
+ Edge := Build_Posedge (Ctxt, Get_Net (L));
+ return Create_Value_Net (Edge, Res_Typ);
end;
when Iir_Predefined_Ieee_1164_Falling_Edge =>
declare
- Clk : Net;
Edge : Net;
begin
- Clk := Get_Net (L);
- Clk := Build_Monadic (Ctxt, Id_Not, Clk);
- Edge := Build_Edge (Ctxt, Clk);
- return Create_Value_Net (Edge, Boolean_Type);
+ Edge := Build_Negedge (Ctxt, Get_Net (L));
+ return Create_Value_Net (Edge, Res_Typ);
end;
when Iir_Predefined_Ieee_1164_Scalar_Is_X
| Iir_Predefined_Ieee_1164_Vector_Is_X =>
diff --git a/src/synth/synth-stmts.adb b/src/synth/synth-stmts.adb
index e1d25384b..d994bc0ff 100644
--- a/src/synth/synth-stmts.adb
+++ b/src/synth/synth-stmts.adb
@@ -2934,14 +2934,12 @@ package body Synth.Stmts is
-- Check the clock is an edge and extract it.
Clk_Inst := Get_Net_Parent (Clk);
- if Get_Id (Clk_Inst) /= Id_Edge then
+ if Get_Id (Clk_Inst) not in Edge_Module_Id then
Error_Msg_Synth (+Stmt, "clock is not an edge");
Next_States := No_Net;
return;
end if;
- Clk := Get_Input_Net (Clk_Inst, 0);
-
-- build idff
States := Build_Idff (Build_Context, Clk, No_Net, Init);