- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you compile the shown snippet, all register are optimized away, because the code doesn't generate any output. Please show meaningful code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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'.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- your code below is suspicious --- Quote End --- Yes, it's one of several code parts that aren't working as probably expected.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page