kender
Joined: 19 Jun 2005 Posts: 1231 Helped: 88 Location: Stanford, SF Bay Peninsula, California, Earth, Solar System, Milky Way
|
07 Jun 2008 23:17 Counter with asynchronous edge-triggered reset in VHDL |
|
|
|
|
Colleagues,
Here’s another VHDL problem. I want to put a one-shot timer into the CPLD. It will serve a safety purpose, if it’s not reset (strobed) on time, it will cut the power. To improve fault-tolerance, I want the reset to be edge-triggered (most of the flip-flops have level-triggered resets, though). So, I wrote the following VHDL code:
| Code: |
architecture Behavioral of watch_dog_timer is
signal wdt_clk_cnt: unsigned(23 downto 0);
begin
process (wdt_clk, wdi) begin
if (wdt_clk'event and wdt_clk = '1' and wdt_clk_cnt < 16777215) then
wdt_clk_cnt <= wdt_clk_cnt + 1;
if (wdt_clk_cnt = 16777215) then
wdo <= '0';
end if;
elsif (wdi'event and wdi = '1') then -- reset on positive edge
wdt_clk_cnt <= (others => '0');
wdo <= '1';
end if;
end process;
end Behavioral; |
But Xilinx WebPack gives me an error:
| Code: |
| ERROR:Xst:827 - "E:/Relievant/Gen2/PLD_firmware/watch_dog_timer.vhd" line 41: Signal wdo cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release. |
How can I get around this problem?
Thanks,
- Nick
|
|
firefoxPL
Joined: 18 Mar 2008 Posts: 40 Helped: 5 Location: Poznan, POLAND
|
08 Jun 2008 9:24 Counter with asynchronous edge-triggered reset in VHDL |
|
|
|
|
in electronic design you basicaly can't trigger one process with more than one edge-trigger, so reset can be only asynchronous:
| Code: |
if(reset = '1')then
...
elsif(rising_edge(clk))then
...
end if;
|
or synchronous:
| Code: |
if(rising_edge(clk))then
if(reset = '1')then
...
else
...
end if;
end if;
|
Added after 2 minutes:
better way is to use synchronous reset, and one more thing
| Quote: |
| Code: |
| if (wdt_clk'event and wdt_clk = '1' and wdt_clk_cnt < 16777215) then |
|
gating clock is very bad idea you should put this like:
| Code: |
if(rising_edge(wdt_clk))then
if(wdt_clk_cnt < ...)then
...
end if;
end if;
|
|
|
FvM
Joined: 22 Jan 2008 Posts: 5160 Helped: 767 Location: Bochum, Germany
|
08 Jun 2008 9:53 Re: Counter with asynchronous edge-triggered reset in VHDL |
|
|
|
|
You are trying to control the counter from two edge sensitive expressions at the same time. That doesn't work. Flip-Flops with two clock inputs would be needed.
Assuming sufficient wdi pulse width, a synchronous edge detection for wdi can be implemented. Otherwise a second wdi edge sensitive process and a handshake would be needed. But I don't expect it's necessary here.
Another point is synchronization of wdi signal. If it's unrelated to wdt_clock, it may coincide with it. With a certain likelihood, wdt_clk_cnt would be reset only partially. Ignoring asynchrounous character of signals is a common source of nasty occasional logic errors. By synchronizing wdi before further processing, such effects are avoided.
| Code: |
architecture Behavioral of watch_dog_timer is
signal wdt_clk_cnt: unsigned(23 downto 0);
wdi_sync: std_logic;
wdi_sync_p: std_logic;
begin
process (wdt_clk) begin
if (wdt_clk'event and wdt_clk = '1' then
wdi_sync <= wdi; -- synchronized to wdt_clock
wdi_sync_p <= wdi_sync; -- remember previous state
if wdi_sync = '1' and wdi_sync_p = '0' then
wdt_clk_cnt <= (others => '0');
wdo <= '1';
elsif wdt_clk_cnt < 16777215) then
wdt_clk_cnt <= wdt_clk_cnt + 1;
wdo <= '1';
else
wdo <= '0';
end if;
end if;
end process; |
|
|