Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Valued Contributor III
724 Views

One Register of an array will not reset

I've created a register array (8x9) in VHDL and I'm resetting registers 6-0 in one process and register 7 in another. The problem is register 7 is not being recognized as getting reset and this causes the compiler to optimize all the registers out. ModelSim shows the problem so I'm sure the problem is controlling the contents of register 7 but I can't see the problem in the code. I've reduced the code to the absolute minimum below. Any thoughts would be appreciated. 

 

Thanks 

 

library IEEE;use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; Entity FIFO_TEMP is port( DATA_IN: in STD_LOGIC_VECTOR(8 downto 0); DATA_OUT: out STD_LOGIC_VECTOR(8 downto 0); -- WORD_RDY: out STD_LOGIC; -- FIFO_FULL: out STD_LOGIC; -- WORD_RD: in STD_LOGIC; -- WORD_WR: in STD_LOGIC; RESET_N: in STD_LOGIC; SYS_CLK: in STD_LOGIC); end FIFO_TEMP; Architecture FIFOXN of FIFO_TEMP is type Register_Array is array(7 downto 0) of STD_LOGIC_VECTOR(8 downto 0); signal Fifo: Register_Array; signal New_Word: STD_LOGIC_VECTOR(2 downto 0); signal Wd_Latch: STD_LOGIC; Begin process(SYS_CLK, Fifo, RESET_N) begin if RESET_N ='0' then for i in 6 downto 0 loop Fifo(i) <= (others =>'0'); end loop; New_Word <= "111"; end if; end process; process (SYS_CLK, RESET_N, Fifo) begin if RESET_N ='0' then Fifo(7) <="000000000"; Wd_Latch <= '0'; end if; end process; end FIFOXN;
0 Kudos
13 Replies
Highlighted
Valued Contributor III
3 Views

If you compile the shown snippet, all register are optimized away, because the code doesn't generate any output. Please show meaningful code.

0 Kudos
Highlighted
Valued Contributor III
3 Views

 

--- Quote Start ---  

If you compile the shown snippet, all register are optimized away, because the code doesn't generate any output. Please show meaningful code. 

--- Quote End ---  

 

 

The full code is below 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; Entity FIFO is port( DATA_IN: in STD_LOGIC_VECTOR(8 downto 0); DATA_OUT: out STD_LOGIC_VECTOR(8 downto 0); WORD_RDY: out STD_LOGIC; FIFO_FULL: out STD_LOGIC; WORD_RD: in STD_LOGIC; WORD_WR: in STD_LOGIC; RESET_N: in STD_LOGIC; SYS_CLK: in STD_LOGIC); end FIFO; Architecture FIFOXN of FIFO is -- constant Depth: Integer:=8; type Register_Array is array(7 downto 0) of STD_LOGIC_VECTOR(8 downto 0); signal Fifo: Register_Array; -- signal Shift: STD_LOGIC; signal Lead_Data: STD_LOGIC_VECTOR(2 downto 0); signal Tail_Data: STD_LOGIC_VECTOR(2 downto 0); signal New_Word: STD_LOGIC_VECTOR(2 downto 0); signal Wd_Latch: STD_LOGIC; Begin -- This section defines the registers and data motion withing the -- register set. There are two pointers, Lead_Data md Tail_Data that -- track the data in the registers; Lead_Data moves the data to the -- output of the Fifo and Tail_Data moves the input data to the last -- unfilled location. process(SYS_CLK, Fifo, Tail_Data, Lead_Data,RESET_N) -- Note: this section runs form the same clock that is used for the X4CLOCK in the send and receive -- sections of the UART. That way there is no more than one word at an unknown location in the FIfo -- at a time. begin if RESET_N ='0' then for i in 6 downto 0 loop Fifo(i) <= "111111111"; end loop; Lead_Data <= "111"; Tail_Data <= "111"; New_Word <= "111"; elsif (SYS_CLK'event and SYS_CLK ='1') then DATA_OUT <= fifo(0); -- Lead_Data Control Logic. This waits for the first word -- then shifts the word to the beginning of the register set -- If the last word count is "000" then the Lead_Data resets to -- "111" indicating the Fifo is empty. -- if (Lead_Data = "111") then if Wd_Latch ='1' then Lead_Data <=Lead_Data - 1; end if; elsif (Lead_Data =not("000")) then Lead_Data <=Lead_Data - 1; elsif (Tail_Data ="000" and WORD_RD ='1')then Lead_Data <= "111"; end if; -- This controls the Tail_Data control logic. When Lead_Data is not "111" and -- a new word is received then the Tail_Data counter shifts the new input word to -- end count +N where N is the nunber of words in the stack. N is decrumented by -- reading the head word in another section. if (Lead_Data = not("000")) then Tail_Data <=Lead_Data; elsif (Wd_Latch ='1' and WORD_RD ='0') then Tail_data <= Tail_Data +1; elsif (Wd_Latch ='1' and WORD_RD ='1') then Tail_data <= Tail_Data; elsif (Wd_Latch ='0' and WORD_RD ='0') then Tail_data <= Tail_Data -1; end if; -- This logic controls the New_Word counter. This counter tracks the new word through the -- the as is is shifted to the new tail location. The Tail_Count is incrumented when -- the new word reached the back of the line. if New_Word ="111" then if Wd_Latch ='1' then New_Word <= New_word - 1; end if; elsif New_Word =not("111") then if New_Word = Tail_Data then New_Word <= New_word - 1; else New_Word <= "111"; end if; end if; -- This section controls the register latching operations based on the conditions of Lead_Word, -- Tail_Word, and New_Word. if Lead_Data =not("111") then for i in 6 downto 1 loop Fifo(i-1) <=Fifo(i); end loop; elsif New_Word = not("111") then case New_Word is when "001" => Fifo(0) <= Fifo(1); when "010" => Fifo(1) <= Fifo(2); when "011" => Fifo(2) <= Fifo(3); when "100" => Fifo(3) <= Fifo(4); when "101" => Fifo(4) <= Fifo(5); when "110" => Fifo(5) <= Fifo(6); when "111" => Fifo(6) <= Fifo(7); when others => Fifo(0) <=Fifo(0); end case; end if; end if; end process; -- This process controls the data entry to the lead register in the array. The WORD_IN -- consists of 8 bits of data, an error bit from the receiver. process (SYS_CLK, WORD_WR, RESET_N, Fifo) begin if RESET_N ='0' then Fifo(7) <="000000000"; Wd_Latch <= '0'; elsif (SYS_CLK'event and SYS_CLK ='1') then if WORD_WR ='1' then Fifo(7) <= DATA_IN; Wd_Latch <='1'; else Fifo(7) <= Fifo(7); Wd_Latch <='0'; end if; end if; end process; --This is the garbage process for misc signals. process (SYS_CLK,WORD_WR, RESET_N) begin if RESET_N ='0' then FIFO_FULL <='0'; WORD_RDY <='0'; elsif (SYS_CLK'event and SYS_CLK ='1') then if Lead_Data <="000" then WORD_RDY <='1'; else WORD_RDY <='0'; end if; if TAIL_DATA = "111" then FIFO_FULL <='1'; else FIFO_FULL <='0'; end if; end if; end process; end FIFOXN;  

 

The code also compiles out all the registers. If you run it in the ModelSim compile and simulation, the registers are not optimized out and you can see the operation in either the snippet or the full code.In either case register Fifo(7) remains "UUUUUUUUU" even when RESET_N is '0'.
0 Kudos
Highlighted
Valued Contributor III
3 Views

According to your logic, data from fifo(7) will be never transferred down to fifo(0). Removal of all registers in synthesis is the regular behaviour in this case.

0 Kudos
Highlighted
Valued Contributor III
3 Views

your code below is suspicious: 

 

elsif New_Word = not("111") then case New_Word is when "001" => Fifo(0) <= Fifo(1); when "010" => Fifo(1) <= Fifo(2); when "011" => Fifo(2) <= Fifo(3); when "100" => Fifo(3) <= Fifo(4); when "101" => Fifo(4) <= Fifo(5); when "110" => Fifo(5) <= Fifo(6); when "111" => Fifo(6) <= Fifo(7); when others => Fifo(0) <=Fifo(0); end case;  

 

the inner condition will not occur.
0 Kudos
Highlighted
Valued Contributor III
3 Views

 

--- Quote Start ---  

your code below is suspicious 

--- Quote End ---  

 

Yes, it's one of several code parts that aren't working as probably expected.
0 Kudos
Highlighted
Valued Contributor III
3 Views

Good catch. I changed the first line of the questionable code segment to use Wd_Latch instead of New_Word. See segment below.  

elsif Wd_Latch = '1' then case New_Word is when "001" => Fifo(0) <= Fifo(1); when "010" => Fifo(1) <= Fifo(2); when "011" => Fifo(2) <= Fifo(3); when "100" => Fifo(3) <= Fifo(4); when "101" => Fifo(4) <= Fifo(5); when "110" => Fifo(5) <= Fifo(6); when "111" => Fifo(6) <= Fifo(7); when others => Fifo(0) <=Fifo(0); end case;  

This now compiles and includes all Fifo registers but Fifo(7) still does not reset. It comes up "UUUUUUUUU" and that then propagates through the rest of the registers. Can you help with the reset question? 

Thanks.
0 Kudos
Highlighted
Valued Contributor III
3 Views

looks like the tool is confused. 

 

if you move second process up it gets ok. 

process(SYS_CLK, Fifo, Tail_Data, Lead_Data,RESET_N) -- Note: this section runs form the same clock that is used for the X4CLOCK in the send and receive -- sections of the UART. That way there is no more than one word at an unknown location in the FIfo -- at a time. begin if RESET_N ='0' then Fifo(7) <= "000000000"; for i in 6 downto 0 loop Fifo(i) <= "111111111"; end loop; Wd_Latch <= '0'; Lead_Data <= "111"; Tail_Data <= "111"; New_Word <= "111"; elsif (SYS_CLK'event and SYS_CLK ='1') then DATA_OUT <= fifo(0); -- Lead_Data Control Logic. This waits for the first word -- then shifts the word to the beginning of the register set -- If the last word count is "000" then the Lead_Data resets to -- "111" indicating the Fifo is empty. -- if (Lead_Data = "111") then if Wd_Latch ='1' then Lead_Data <=Lead_Data - 1; end if; elsif (Lead_Data =not("000")) then Lead_Data <=Lead_Data - 1; elsif (Tail_Data ="000" and WORD_RD ='1')then Lead_Data <= "111"; end if; -- This controls the Tail_Data control logic. When Lead_Data is not "111" and -- a new word is received then the Tail_Data counter shifts the new input word to -- end count +N where N is the nunber of words in the stack. N is decrumented by -- reading the head word in another section. if (Lead_Data = not("000")) then Tail_Data <=Lead_Data; elsif (Wd_Latch ='1' and WORD_RD ='0') then Tail_data <= Tail_Data +1; elsif (Wd_Latch ='1' and WORD_RD ='1') then Tail_data <= Tail_Data; elsif (Wd_Latch ='0' and WORD_RD ='0') then Tail_data <= Tail_Data -1; end if; -- This logic controls the New_Word counter. This counter tracks the new word through the -- the as is is shifted to the new tail location. The Tail_Count is incrumented when -- the new word reached the back of the line. if New_Word ="111" then if Wd_Latch ='1' then New_Word <= New_word - 1; end if; elsif New_Word =not("111") then if New_Word = Tail_Data then New_Word <= New_word - 1; else New_Word <= "111"; end if; end if; -- This section controls the register latching operations based on the conditions of Lead_Word, -- Tail_Word, and New_Word. if Lead_Data =not("111") then for i in 6 downto 1 loop Fifo(i-1) <=Fifo(i); end loop; elsif Wd_Latch = '1' then case New_Word is when "001" => Fifo(0) <= Fifo(1); when "010" => Fifo(1) <= Fifo(2); when "011" => Fifo(2) <= Fifo(3); when "100" => Fifo(3) <= Fifo(4); when "101" => Fifo(4) <= Fifo(5); when "110" => Fifo(5) <= Fifo(6); when "111" => Fifo(6) <= Fifo(7); when others => Fifo(0) <=Fifo(0); end case; end if; if WORD_WR ='1' then Fifo(7) <= DATA_IN; Wd_Latch <='1'; else Fifo(7) <= Fifo(7); Wd_Latch <='0'; end if; end if; end process;
0 Kudos
Highlighted
Valued Contributor III
3 Views

Wow! I would have never tried that! 

 

I appreciate your help on this. I've been staring at this reset problem for hours and moving snippets of the reset code around to see what was wrong. Last question; how often will I have to try this type of fix on future code I generate? Is this a common solution for problems that confound people? 

 

Thanks again for your help. 

 

Mell O
0 Kudos
Highlighted
Valued Contributor III
3 Views

I have a couple of comments regarding the coding: 

 

1. Regarding your VHDL coding of a process that is describing a clocked register the sensitivity list should only include the reset signal (if it is asynchronous to the clock) and the clock signal. You only want the process to be evaluated (for an update of the output) when there is an event (change of state) on either the reset or clock signal.  

 

If the output and other inputs of the process are in the sensitivity list then the process will also evaluate and update the process outputs when there are events on the output itself and on the other inputs. This would incorrectly describe the behavior of a clocked registered function.  

 

2.Regarding the signal FIFO, that is an array, I came across a similar problem a number of years ago during simulation. I also had some elements of the array in one process with the other elements of the array in another process. When the elements in one of the processes were updated, the elements in the other process were updated incorrectly. When I showed this to Modelsim they believed that it was a Modelsim bug. However, their VHDL language expert told me that, based on the VHDL LRM, in a for loop when there is an array with a variable for an index, modelsim initializes all elements of the array including elements that are not described in the process. This may possibly have changed with VHDL 2008. 

 

When I used a Generate statement rather a For loop, I was able to have the elements of the array within separate processes. If you can, it is best to describe the behavior off all of the elements of the array within the same process.
0 Kudos
Highlighted
Valued Contributor III
3 Views

 

--- Quote Start ---  

When I showed this to Modelsim they believed that it was a Modelsim bug. However, their VHDL language expert told me that, based on the VHDL LRM, in a For Loop when there is an array with a variable for an index, Modelsim initializes all elements of the array including elements that are not described in the process. This may possibly have changed with VHDL 2008. 

--- Quote End ---  

 

 

Can you please tell which VHDL specification clause the Modelsim guys did refer to? Clearly this is pure simulation issue, but I don't yet recognize a systematical flaw in the code. 

 

 

--- Quote Start ---  

Last question; how often will I have to try this type of fix on future code I generate? Is this a common solution for problems that confound people? 

--- Quote End ---  

 

Either if it's a Modelsim bug or a systematical VHDL simulation issue, the problem is finally brought up by splitting the code into arbitrary processes. The erroneous sensitivity lists mentioned by Ron somehow fit the picture. Why don't you code the synchronous action into a single clock edge sensitive process as suggested by kaz?
0 Kudos
Highlighted
Valued Contributor III
3 Views

Regarding my post above: 

... I also had some elements of the array in one process with the other elements of the array in another process. When the elements in one of the processes were updated, the elements in the other process were updated incorrectly. When I showed this to Modelsim they believed that it was a Modelsim bug. However, their VHDL language expert told me that, based on the VHDL LRM, in a "For Loop when there is an array with a variable for an index, Modelsim initializes all elements of the array including elements that are not described in the process". This may possibly have changed with VHDL 2008. 

 

This is not a Modelsim bug. It is, unfortunately, specified in the VHDL LRM. I do not remember which part of the VHDL LRM it is in. 

 

The reason it is in the VHDL LRM, according to the Modelsim VHDL language expert, is in case the computation for the indices of the array are extremely complex, this would reduce the time required for initialization. 

 

I consider this to be a serious problem with the language specification. This may have been with VHDL 1993. I do not know if it is in VHDL 2008. If there is a VHDL LRM expert reading this please comment on it. 

 

Anyway, this issue is only when the signal array is within a For loop that only specifies some of the elements of the array. 

 

This issue does not occur when using a Generate statement rather than the For loop.
0 Kudos
Highlighted
Valued Contributor III
3 Views

 

--- Quote Start ---  

I do not remember which part of the VHDL LRM it is in. 

--- Quote End ---  

 

Too bad. But the statement doesn't sound plausible at first sight according to my knowledge of the VHDL specification. So unless somebody can confirm this, I tend to assume a Modelsim bug for the time being.  

 

Thanks so far.
0 Kudos
Highlighted
Valued Contributor III
3 Views

I have always understood it that a complex signal (like an array or record) must have ALL of it's elements updated in a single process. Otherwise it counts as multiple driver errors. Similar discussions have come up on comp.lang.vhdl previously and, IIRC, the LRM says that any process that drives a single element implicitly drives the other elements too. 

 

A generate is different because a generate does not drive anything, it just defines connectivity.
0 Kudos