M
M. Norton
Guest
Alright, well in the interests of bettering my design process etc, I've been trying to do a lot more low level simulations, full chip simulations, fiddling with post-fit models, etc. I've got a little CPLD whose main purpose in life is to condition the reset signals a microprocessor gets and runs the configuration signals that are active while the processor is held in reset. Nothing particularly magic, nothing exotic.
My trouble is that even with good design, the simulation of this falls apart because unknowns are propagated when they really shouldn't be. I may be missing a trick with the simulator but thus far I haven't found how to control this.
So for example, my RTL code for this little reset pulse stretch runs like this:
-- All the resets that enter the CPLD are asynchronous with the clock. To
-- alleviate metastability concerns and make setup times for the counter
-- used to pulse stretch, the resets here are synchronized into the clock
-- domain.
RESET_SYNC : process (i_clk_66mhz)
begin
if rising_edge(i_clk_66mhz) then
board_por_n_meta <= i_board_por_n;
board_por_n <= board_por_n_meta;
cop_hreset_n_meta <= i_cop_hreset_n;
cop_hreset_n <= cop_hreset_n_meta;
cop_sreset_n_meta <= i_cop_sreset_n;
cop_sreset_n <= cop_sreset_n_meta;
fpga_sreset_n_meta <= i_fpga_sreset_out_n;
fpga_sreset_n <= fpga_sreset_n_meta;
end if;
end process RESET_SYNC;
-- proc_hreset_n is used throughout for the configuration and here is
-- assigned to an output port.
o_proc_hreset_n <= proc_hreset_n;
o_proc_sreset_n <= proc_sreset_n;
-- Reset control needs to conform to the reset initialization timing listed
-- in the hardware specification (Section 2.4). In short, HRESET must be
-- asserted a minimum of 25 us. SRESET must be asserted a minimum of 3
-- SYSCLK cycles (30 ns). Additionally, the input setup time for POR
-- configuration with respect to HRESET deassertion is 4 SYSCLK cycles.
-- Thus any time HRESET is asserted, it must stay in that state for at least
-- 4 clocks before it may be deasserted.
HRESET_CTRL : process (i_clk_66mhz)
begin
if rising_edge(i_clk_66mhz) then
if (board_por_n = '0' or cop_hreset_n = '0') then
-- Assertion may happen immediately, start a count to control
-- assertion minimum time. 25 us is 1667 15 ns counts.
proc_hreset_n <= '0';
else
-- Deassertion must only happen after the minimum delay was reached.
if (proc_hreset_n = '0' and hreset_count = 0) then
proc_hreset_n <= '1';
end if;
end if;
end if;
end process HRESET_CTRL;
HRESET_STRETCH_COUNTER : process (i_clk_66mhz)
begin
if rising_edge(i_clk_66mhz) then
if (proc_hreset_n = '0') then
if (hreset_count /= 0) then
hreset_count <= hreset_count - 1;
end if;
else
hreset_count <= to_unsigned(1750,12);
end if;
end if;
end process HRESET_STRETCH_COUNTER;
Of course what I'm actually simulating is the post-fit primitives, but this is the essential behavior. So, if the initial reset meets the setup conditions for its first register, the whole thing works beautifully. However I cannot be guaranteed that, so I run a simulation where the reset does NOT meet the setup conditions for the first register. Now, this is exactly why I have metastability registers emplaced on the input. The leading edge through the register will resolve high/low but be unknown, but the second clock cycle will resolve low and we're off to the races.
The problem is that this unknown propagates through the rest of the design and basically fouls up figuring anything out. So Modelsim naturally says "I don't know what this input is during this clock cycle. The counter might start counting down -- or the counter might stay put and start counting down the next cycle. The result is a big mess of red.
From one point of view, this is exactly what it ought to show, but I don't know what that means from a verification standpoint. I can demonstrate that if the input signal meets the setup time and the design works properly post-fit with backannotated timing. If the input signal does not meet the setup time, I can demonstrate from the device final schematic that there are two registers with enough delay to account for the metastability settling time and no interior registers are exposed to this unknown state. That is more of an analytical proof and it'd be nice to show a more direct proof that the design will indeed perform correctly.
So am I resigned to just having to prove the design through metastability analysis and leave simulation to the "well-behaved" cases? Or is there some trick of design or Modelsim wizardry where I can put in a badly behaved case in Modelsim and see that my design works properly regardless?
Thanks for any insight.
Best regards,
Mark Norton
My trouble is that even with good design, the simulation of this falls apart because unknowns are propagated when they really shouldn't be. I may be missing a trick with the simulator but thus far I haven't found how to control this.
So for example, my RTL code for this little reset pulse stretch runs like this:
-- All the resets that enter the CPLD are asynchronous with the clock. To
-- alleviate metastability concerns and make setup times for the counter
-- used to pulse stretch, the resets here are synchronized into the clock
-- domain.
RESET_SYNC : process (i_clk_66mhz)
begin
if rising_edge(i_clk_66mhz) then
board_por_n_meta <= i_board_por_n;
board_por_n <= board_por_n_meta;
cop_hreset_n_meta <= i_cop_hreset_n;
cop_hreset_n <= cop_hreset_n_meta;
cop_sreset_n_meta <= i_cop_sreset_n;
cop_sreset_n <= cop_sreset_n_meta;
fpga_sreset_n_meta <= i_fpga_sreset_out_n;
fpga_sreset_n <= fpga_sreset_n_meta;
end if;
end process RESET_SYNC;
-- proc_hreset_n is used throughout for the configuration and here is
-- assigned to an output port.
o_proc_hreset_n <= proc_hreset_n;
o_proc_sreset_n <= proc_sreset_n;
-- Reset control needs to conform to the reset initialization timing listed
-- in the hardware specification (Section 2.4). In short, HRESET must be
-- asserted a minimum of 25 us. SRESET must be asserted a minimum of 3
-- SYSCLK cycles (30 ns). Additionally, the input setup time for POR
-- configuration with respect to HRESET deassertion is 4 SYSCLK cycles.
-- Thus any time HRESET is asserted, it must stay in that state for at least
-- 4 clocks before it may be deasserted.
HRESET_CTRL : process (i_clk_66mhz)
begin
if rising_edge(i_clk_66mhz) then
if (board_por_n = '0' or cop_hreset_n = '0') then
-- Assertion may happen immediately, start a count to control
-- assertion minimum time. 25 us is 1667 15 ns counts.
proc_hreset_n <= '0';
else
-- Deassertion must only happen after the minimum delay was reached.
if (proc_hreset_n = '0' and hreset_count = 0) then
proc_hreset_n <= '1';
end if;
end if;
end if;
end process HRESET_CTRL;
HRESET_STRETCH_COUNTER : process (i_clk_66mhz)
begin
if rising_edge(i_clk_66mhz) then
if (proc_hreset_n = '0') then
if (hreset_count /= 0) then
hreset_count <= hreset_count - 1;
end if;
else
hreset_count <= to_unsigned(1750,12);
end if;
end if;
end process HRESET_STRETCH_COUNTER;
Of course what I'm actually simulating is the post-fit primitives, but this is the essential behavior. So, if the initial reset meets the setup conditions for its first register, the whole thing works beautifully. However I cannot be guaranteed that, so I run a simulation where the reset does NOT meet the setup conditions for the first register. Now, this is exactly why I have metastability registers emplaced on the input. The leading edge through the register will resolve high/low but be unknown, but the second clock cycle will resolve low and we're off to the races.
The problem is that this unknown propagates through the rest of the design and basically fouls up figuring anything out. So Modelsim naturally says "I don't know what this input is during this clock cycle. The counter might start counting down -- or the counter might stay put and start counting down the next cycle. The result is a big mess of red.
From one point of view, this is exactly what it ought to show, but I don't know what that means from a verification standpoint. I can demonstrate that if the input signal meets the setup time and the design works properly post-fit with backannotated timing. If the input signal does not meet the setup time, I can demonstrate from the device final schematic that there are two registers with enough delay to account for the metastability settling time and no interior registers are exposed to this unknown state. That is more of an analytical proof and it'd be nice to show a more direct proof that the design will indeed perform correctly.
So am I resigned to just having to prove the design through metastability analysis and leave simulation to the "well-behaved" cases? Or is there some trick of design or Modelsim wizardry where I can put in a badly behaved case in Modelsim and see that my design works properly regardless?
Thanks for any insight.
Best regards,
Mark Norton