How to write elegantly, when sync. and async. reset should do the same? I thought about that:
process(sys_clk_i, rst_i) begin if rst_i = '1' or (rising_edge(sys_clk_i) and srst_i = '1') then -- Reset operations elsif rising_edge(sys_clk_i) then -- Normal operation end if; end process;
However, the synthesis tools (Vivado & Synplify) complain about that (they think that srst_i must also be in the sensitivity list) I just do not want to write the reset operations twice... Thanks for the help & Happy Xmas!
: Edited by Moderator
St. D. wrote: > I just do not want to write the reset operations twice... So, only use a synchronous reset. Why should you use two ways of reset? What kind of flipflop can handle that? Simply write it like all others around the world:
process(sys_clk_i) begin if rising_edge(sys_clk_i) then if srst_i = '1' then -- Reset operations else -- Normal operation end if; end if; end process;
> However, the synthesis tools (Vivado & Synplify) complain about that Indeed, there is NO such a flipflop with two clock inputs inside a FPGA. Read the synthesizers user guide to figure out, whats allowed and how you must wirte it. > (they think that srst_i must also be in the sensitivity list) They do not care a little bit about that incomplete sensitivity list. They tell you just with a short warning or info, that with an incomplete the simulation will not match the real hardware. The sensitivity list is for the simulator ONLY.
You can also do something like this: R_MAIN : process (i_clk, i_rst_n) procedure p_hw_init is begin s_sig1 <= '1'; s_sig2 <= '0'; s_sig3 <= (others => '0'); s_sig4 <= (others => '1'); end procedure; begin if (i_rst_n = '0') then p_hw_init; elsif (rising_edge(i_clk)) then if (i_rst_sync = '1') then p_hw_init; else -- Functional implementation goes here end if; end if; end process; A word of warning though, some linting tools have rules that don't like the use of procedures as above, some are DO254 relevant. But maybe you can just disable the rules in your project if you ever run into problems and document why you think its ok. I have never really understood what the problem is supposed to be. Calling the procedure makes sure you 1) specify the action just once 2) Don't accidently have different behaviour in the syn and async reset paths. If you want different behaviour of course then that's a different story. And I think it is definitely more readable than the macros in Verilog.
By the way, just to clarify a possible misunderstanding above (since I missed the 60min window to update the post), the procedure p_hw_init will give you two different logic results when synthesised. Calling p_hw_init from the asynchronous path will connect the asynchronous flip-flop set or clr inputs to the asynchronous reset source, adding buffers and inverters as needed. Calling p_hw_init from the synchronous path will infer a multiplexer in front of the Flip-Flop D-input. The MUX is switched by the synchronous reset signal. If the sync_reset is active, the D-input will receive the reset values, otherwise the functional values. Optimisation and logic collapsing can blur this a bit of course, particularly in the synchronous path.
: Edited by User
Lothar M. wrote: > So, only use a synchronous reset. Why should you use two ways of reset? > What kind of flipflop can handle that? Dear Lothar, I am aware that the async. reset is a pain in the neck for Xilinx/Altera (RAM-based) FPGAs. However, the Flash-based Microsemi FPGAs require an explicit async. reset, since they do not have configuration phase & GSR. We use both types FPGAs and I want to write the VHDL code as generic as possible. I could connect the unused reset port to static '0' or '1' and get rid of it by optimizations. Dear Charles, thanks a lot for the tip. It is an elegant solution.