Hi Walter,
Thanks a lot indeed for bringing this interesting subject !
I noticed a while ago that some synthesis tools made attempts in implementing signal
initialization at declaration, and I didn't like the idea very much.
You mention ISE, and it is among those who try (and, to some extend, succeed).
However, I just checked and it missed the tristate ! So, for me, it's still a no-go.
I've written a complete test so that anyone can try with any technology and any
synthesis tool and take an educated decision... (and let me know !)
Anyway, it's a too potentially dangerous practice, and I know that this fails with
some synthesizers, P&R, and FPGAs, so I will keep my rule set unchanged, and once
again mention that, with good reasons and experience, any rule (almost) can be bent.
For example, we don't deliver code to our customers which isn't ASIC-friendly (as
much as possible), so this tule is enforced.
I will change the rule when :
- it will be normalized in 1076.6 (is it ? I didn't check the future version)
- all synthesis tools will pass this test
- all tech mappers will pass this test
- all physical synthesis tools will keep the functioanlity
- all FPGAs will implement this flawlessly
- it will be considered as ASIC-friendly code.
until then I will consider this practice as an exception which requires justification
and verification.
Here comes the test. ISE fails at Q4 (tristate) but does a good job on the rest.
If anyone tests other tools and technologies, please send me the results !
(i_n_f_o at alse-fr with no underscore. Add dot com indeed)
Bert Cuzeau
--------------
-- SigInit.vhd
-- ---------------------------------------------
-- Testing Initialized Signals implementation
-- ---------------------------------------------
-- (c) ALSE
http://www.alse-fr.com
-- Author : Bert Cuzeau
-- THIS STYLE IS NOT RECOMMENDED !
-- You may use this to check your FPGA technology and tools.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
-- ---------------------------------------
Entity SigInit is
-- ---------------------------------------
Port ( Clk : In std_logic;
--Rst : In std_logic; -- not anymore
En : In std_logic;
Din : in std_logic;
Q : Out std_logic_vector (8 downto 0) );
end ;
-- ---------------------------------------
Architecture questionable of SigInit is
-- ---------------------------------------
type State_t is (A, B, C, Idle, Dead);
-- Things NOT to do IMO !!! >>>>>
signal InitZ : std_logic := 'Z';
signal Init0 : std_logic := '0';
signal Init1 : std_logic := '1';
signal Initd : std_logic := '-';
signal count : unsigned(3 downto 0) := "1010";
signal Bool : boolean; -- initialized to false at t=0.
signal Bool2 : boolean; -- initialized to false at t=0.
signal State : State_T := Idle;
signal Q5 : std_logic := '1';
signal Q6 : std_logic := '0';
-- <<<<<
signal Q7 : std_logic;
begin
------
process (Clk)
begin
if rising_edge (Clk) then
if En='1' then
case State is
when A => State <= B;
when B => State <= C;
when C => if not Bool then State <= Idle; end if;
when Idle => State <= A; Q6 <= not Q6;
When Dead => null;
end case;
end if;
end if;
end process;
process (Clk)
begin
if rising_edge (Clk) then
if Bool then
Bool <= not Bool;
Q7 <= not Q7; -- should be undriven
Bool2 <= not Bool; -- shoudl generate no logic
end if;
end if;
end process;
process (Clk)
begin
if rising_edge (Clk) then
if not Bool then
Q5 <= not Q5; -- should toggle
Q(8) <= Initd; -- could be anything after synthesis : 0 or 1 or nothing or ...
end if;
end if;
end process;
process (Clk)
begin
if rising_edge (Clk) then
count <= count + 1;
end if;
end process;
Q(3 downto 0) <= std_logic_vector(count);
Q(4) <= InitZ; -- should be a tristated output !
Q(5) <= Q5;
Q(6) <= Q6 and Init1; -- expect toggling at F/8
Q(7) <= Init1; -- expected 1
end questionable;
------test Bench-----------------------------
-- synopsys translate_off
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.math_real.all;
entity TB_SigInit is end;
architecture test of TB_SigInit is
constant Period : time := 400 ns; -- 1st rising edge must be away from timesim
internal reset
signal Qrtl,Qpost : std_logic_vector(8 downto 0);
signal Clk,En,Din : std_logic := '0'; -- here we can initialize signals
signal Done : boolean;
begin
UUT1: entity work.SigInit(BAD) port map (Clk,En,Din,Qrtl);
-- change arch name below to timesim model
UUT2: entity work.SigInit(Structure) port map (Clk,En,Din,Qpost);
Clk <= '0' when Done else not Clk after Period / 2;
En <= '1' after 5 * Period;
Done <= true after 32 * Period;
assert not(falling_edge(Clk) and Qrtl(3 downto 0)/=Qpost(3 downto 0))
report "Q3..0: RTL vs Simulation mismatch!" severity error;
assert not(falling_edge(Clk) and Qrtl(4)/=Qpost(4))
report "Q4: RTL vs Gates mismatch!" severity error;
assert not(falling_edge(Clk) and Qrtl(5)/=Qpost(5))
report "Q5: RTL vs Gates mismatch!" severity error;
assert not(falling_edge(Clk) and Qrtl(6)/=Qpost(6))
report "Q6: RTL vs Gates mismatch!" severity error;
assert not(falling_edge(Clk) and Qrtl(7)/=Qpost(7))
report "Q7: RTL vs Gates mismatch!" severity error;
end test;
----- Simu.do --------
-- vlib work
-- vcom -93 siginit_timesim.vhd
-- vcom -93 siginit.vhd
-- #vcom -93 tb_siginit.vhd
-- vsim -noglitch -sdftyp /uut2=siginit_timesim.sdf tb_siginit
-- add wave clk
-- add wave en
-- add wave din
-- add wave uut1/state
-- add wave qrtl
-- add wave qpost
-- run -a
-- ---------------------------------------------