VHDL Dual Port RAM unexpected latches generated - warnings

I wrote a register file for my 16-bit MIPS architecture, here I make sure that my register0 contains all zeros, There are no syntax errors but I have some questions
Have I done the typecasting right? Because I get some warnings about latches being generated. What have I done wrong here?
Also what is the difference between conv_integer and to_integer(unsigned((w_addr))? Because when I used to_integer(unsigned(r_addr1)=0) I experienced errors.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
entity regfile is
generic(
N: integer:=4; --number of bits for address
W: integer:=16 --number of bits
);
Port ( clk : in STD_LOGIC;
w_en : in STD_LOGIC;
r_addr1,r_addr2,w_addr : in STD_LOGIC_VECTOR (N-1 downto 0);
w_data: in STD_LOGIC_VECTOR (W-1 downto 0);
r_data1, r_data2 : out STD_LOGIC_VECTOR (W-1 downto 0));
end regfile;
architecture Behavioral of regfile is
type regfile_type is array (W-1 downto 0) of STD_LOGIC_VECTOR (W-1 downto 0);
signal RegisterFile: regfile_type;
begin
process(clk)
begin
if (clk = '1') then
if (w_en = '1') then
RegisterFile(to_integer(unsigned(w_addr))) <= w_data;
end if;
end if;
end process;
process (r_addr1, r_addr2)
begin
if (conv_integer(r_addr1)=0) then
r_data1 <= X"0000";
else r_data1<=RegisterFile(to_integer(unsigned(r_addr1)));
end if;
if (conv_integer(r_addr2)=0) then
r_data2 <= X"0000";
else r_data2 <= RegisterFile(to_integer(unsigned(r_addr2)));
end if;
end process;
end Behavioral;
these are the warnings I am getting
WARNING:Xst:819 - "E:/Xilinx Projects/regfile/regfile.vhd" line 49: One or more signals are missing in the process sensitivity list. To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. Please note that the result of the synthesis may differ from the initial design specification. The missing signals are:<w_en>, <w_data>
WARNING:Xst:819 - "E:/Xilinx Projects/regfile/regfile.vhd" line 58: One or more signals are missing in the process sensitivity list. To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. Please note that the result of the synthesis may differ from the initial design specification. The missing signals are: <RegisterFile>
WARNING:Xst:737 - Found 16-bit latch for signal <RegisterFile_15>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegisterFile_14>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegisterFile_13>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegisterFile_12>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
WARNING:Xst:737 - Found 16-bit latch for signal <RegisterFile_11>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

1. The line:
if (clk = '1') then
should be either:
if (clk'event and clk = '1') then
or:
if rising_edge(clk) then
This is where your latches are being created. While it may seem that the event should be implied by the sensitivity list, it needs to be explicit for the synthesis tool to properly infer a flip-flop.
2. to_integer(unsigned(r_addr1)=0) - did you mean to_integer(unsigned(r_addr1))=0 (which should work just fine)? Be careful to match your parentheses. Incidentally, unsigned compares just fine to integer literals, so you don't need the to_integer here. Just unsigned(r_addr1)=0 is fine.

Your clocked process isn't written correctly. The tools don't realize that clk is actually a clock. You need to either use clk'event or better yet use rising_edge(). The tools are creating a combinational process, rather than a sequential one. Since there's no else condition on the if statement, it makes your RegisterFile a latch. Here's some more information on what is a latch and how to avoid latches in your FPGA
process(clk)
begin
if rising_edge(clk) then
if w_en = '1' then
RegisterFile(to_integer(unsigned(w_addr))) <= w_data;
end if;
end if;
end process;

Related

Register allocation for code generator in MIPS

program main();
a,b: integer;
function p(name x: integer; var y,z: integer): integer;
a: integer;
function f(y: integer): integer;
b,c: integer;
a := a+1;
if (g(y<=0)) then return 2;
return 2*x + p(y--/2,b,c) – b*c;
end function;
function g(name i: integer): integer;
if (b < 3) then return 1;
return i;
end function;
a := b++;
y := f(x);
z := y*f(x) – a;
return a;
end function;
a := 1;
b := 6;
p(a+b--,a,b);
print(a,b);
end program
This is the programm, in which I want to allocate registers for code generator in MIPS. I have troubles with the nested functions.
My registers are: $2- $25.
The registers $4- $7 are used for passing arguments, $3 is for passage access link when calling a function, $2 for results of function. Registers $16-$23 must retain their value when calling a function, so if they are bound, they must be stored in auxiliary positions in the stack by entering the function and
to be reloaded before exiting the function. If the word size is 4 bytes, which is the activation record size for each of the code units,including parameter by reference evaluation subprograms?
Also, how many registers and which are needed to allocate?
Since this programming language is hypothetical, we have to make some assumptions as to the immediacy of the visibility of modifications to var parameters.  Let's assume such changes (to var parameters) are immediately visible, and thus, they are effectively passed by address.
Therefore, for all practical purposes, actual arguments passed in var positions must be memory variables and their address is passed instead of their current value (as would otherwise be the case).
(Sure, there are other ways to do this: advanced optimization might inline some of these functions (p is recursive so that makes it rather difficult to fully inline, though tail recursion could potentially be applied along with further modifications to make it iterative instead of recursive), or else, custom generating the code per particular call sites is another possibility.)
Thus, under these assumptions, main.a and main.b are both "forced" to (stack) memory because of p(a+b--,a,b);  Further, because of p(y--/2,b,c), p.b & p.c are also both "forced" to memory.
Other than these variables being assigned stack memory locations, you can do the register allocation normally.
Also complicating matters due to the undocumented nature of the hypothetical programming language, is the order of evaluation of expressions.  This code example is rich with ambiguity, using variables and modifications of them (e.g. b-- in the same expression as using b), which in C would lead to the territory of dragons: undefined behavior.
One reasonable assumption would be that order of evaluation is left-to-right, and that side effects (such as post-decrement) are observed immediately.
But we don't know the language.  So, suffice it to say that this code is filled with language-specific land-mines and we don't know the language.

VHDL warning: PAR will not attempt to route this signal

I am learning VHDL and I am on the quest to implement my own FIFO buffer, but I have some problems. Since I want to deploy the code on a Xilinx Spartan 6 device I am using the Xilinx WebPack ISE with the associated VHDL compiler, but I am getting very weird warnings:
WARNING:Par:288 - The signal Mram_buf_mem1_RAMD_D1_O has no load. PAR will not attempt to route this signal.
WARNING:Par:283 - There are 1 loadless signals in this design. This design will cause Bitgen to issue DRC warnings.
Here is my code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity FIFO_buffer is
generic ( BUFFER_SIZE : positive := 4; -- # of words
WORD_WIDTH : positive := 8); -- # of bits per word
port ( data_in : in STD_LOGIC_VECTOR (WORD_WIDTH - 1 downto 0);
full : out STD_LOGIC := '0';
write : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (WORD_WIDTH - 1 downto 0);
empty : out STD_LOGIC := '1';
read : in STD_LOGIC);
end FIFO_buffer;
architecture arch of FIFO_buffer is
type ram_t is array (0 to BUFFER_SIZE - 1) of std_logic_vector(WORD_WIDTH - 1 downto 0);
signal buf_mem : ram_t := (others => (others=>'0'));
signal read_idx : integer range 0 to BUFFER_SIZE - 1 := 0;
signal write_idx : integer range 0 to BUFFER_SIZE - 1 := 0;
signal buf_full : std_logic := '0';
signal buf_empty : std_logic := '0';
begin
writing_data: process(write)
begin
if(rising_edge(write)) then
if(buf_full = '0') then
buf_mem(write_idx) <= data_in;
write_idx <= write_idx + 1;
if(write_idx = read_idx)
then buf_full <= '1';
else buf_full <= '0';
end if;
end if;
end if;
end process;
reading_data: process(read)
begin
if(rising_edge(read)) then
if(buf_empty = '0') then
data_out <= buf_mem(read_idx);
read_idx <= read_idx + 1;
if(read_idx = write_idx)
then buf_empty <= '1';
else buf_empty <= '0';
end if;
end if;
end if;
end process;
full <= buf_full;
empty <= buf_empty;
end arch;
The error seems to be caused by the data_out <= buf_mem(read_idx); line in the reading_data process. Could anyone explain to me the reason for the warning? (I know that my code has some functional problems, but that should not affect the reason for the warning)
P.S. Since I have the code here let me ask one more question. How unwise is it to have a component (such as that FIFO buffer) which is not synchronised with the global clock?
I'll address your second question first, i.e. " How unwise is it to have a component (such as that FIFO buffer) which is not synchronised with the global clock?"
It depends on your requirements. Usually, you should clock your components, so you have synchronous logic and no weird glitches caused by asynchronous paths.
However, consider what you did here. You have clocked your component: rising_edge(read) and rising_edge(write). You will find in your synthesis report the following:
Primitive and Black Box Usage:
------------------------------
<snip>
# Clock Buffers : 2
# BUFGP : 2
<snip>
Clock Information:
------------------
-----------------------------------+------------------------+-------+
Clock Signal | Clock buffer(FF name) | Load |
-----------------------------------+------------------------+-------+
read | BUFGP | 11 |
write | BUFGP | 6 |
-----------------------------------+------------------------+-------+
This is because you're not using a combinational process. This will lead to all kinds of problems. You mention a Xilinx Spartan-6. You will get the following message along the line (usually an ERROR), assuming you did not accidentally place read and write at an optimal IOB/BUFG site pair:
Place:1109 - A clock IOB / BUFGMUX clock component pair have been found
that are not placed at an optimal clock IOB / BUFGMUX site pair. The clock
IOB component <write> is placed at site <A5>. The corresponding BUFG
component <write_BUFGP/BUFG> is placed at site <BUFGMUX_X2Y9>. There is only
a select set of IOBs that can use the fast path to the Clocker buffer, and
they are not being used. You may want to analyze why this problem exists and
correct it.
What this message explains in great verbosity is the following. FPGAs have dedicated routing networks for clocks, which assure low skew. (Check Xilinx UG382 for more). However, there are specific pins on the FPGA that can directly access this clock network. There, IOB (I/O Buffer) and BUFG[MUX] ([Multiplexed] Global [Clock] Buffer) are close-by, ensuring that the signal from the pin can be distributed really fast across the whole FPGA using dedicated clocking resources. You can check placement with the FPGA Editor. For instance, my write pin has to cross half the FPGA before being able to get routed using a global clock buffer. That's 3.878ns delay in my case.
The same applies for read, of course. So you see this is a bad idea. You should use dedicated clocking resources for your clocks and synchronize inputs and outputs to that.
Now, on to your main question. You have to be aware what your HDL actually describes.
You have two distinct processes, each with their own clock (read; write) that access the same memory. You have two distinct addresses as well (write_idx; read_idx).
Hence, the XST Synthesizer (that ISE uses) inferred a dual-port RAM. Because the depth as well as element width are both small, it inferred a distributed dual-port RAM. Check your synthesis report, it will say
Found 4x8-bit dual-port RAM <Mram_buf_mem> for signal <buf_mem>.
<snip>
INFO:Xst:3231 - The small RAM <Mram_buf_mem> will be implemented on LUTs in order to maximize performance and save block RAM resources. If you want to force its implementation on block, use option/constraint ram_style.
-----------------------------------------------------------------------
| ram_type | Distributed | |
-----------------------------------------------------------------------
| Port A |
| aspect ratio | 4-word x 8-bit | |
| clkA | connected to signal <write> | rise |
| weA | connected to signal <full> | low |
| addrA | connected to signal <write_idx> | |
| diA | connected to signal <data_in> | |
-----------------------------------------------------------------------
| Port B |
| aspect ratio | 4-word x 8-bit | |
| addrB | connected to signal <read_idx> | |
| doB | connected to internal node | |
-----------------------------------------------------------------------
When you now look at the technology schematic, you will see XST inferred three instances: Mram_buf_mem1, Mram_buf_mem21, Mram_buf_mem22. In my case anyway, yours might differ.
Mram_buf_mem1 is the input buffer for data_in(5:0), data_in(6) and data_in(7) are actually using Mram_buf_mem21 resp. Mram_buf_mem22. This is just an artifact of the design not being properly constrained (what's the clock period of read and write? etc.)
So, basically your message above
WARNING:Par:288 - The signal Mram_buf_mem1_RAMD_D1_O has no load. PAR will not attempt to route this signal.
means that some output signal the inferred dual-port distributed RAM provides (D1_O) is not being used (it drives no logic/flip flops). Therefore, the Place and Route (PAR) step will not even attempt to route it. With all this information we gathered, we can safely assume that this doesn't matter and won't affect your FIFO at all.
However, what will matter is the following: You did nothing to constrain paths between your two clock domains (read domain and write domain). This means, you might run into issues where write_idx is changing while read is performed and vice-versa. This might leave you stuck in one state with full not being deasserted or empty not being asserted, because you lack synchronization logic for signals that need to cross the clock domain.
XST will not insert this logic for you. You can check for these types of errors using the Asynchronous Delay Report and Clock Region Report.
Now, if you're just getting started with the world of FPGAs, you might want to play around a bit with inference of primitives vs. instantiation of primitives. Check the Spartan 6 HDL library guide to see what VHDL language construct will cause XST to infer a e.g. RAM, FIFO, flip flop, and which constructs will cause it to infer weird and cryptic logic constructs because of some unrealistic inferred timing/area constraints.
Finally, try to have synchronous logic as much as possible and properly constrain your design. Also, sorry for the long write-up if you were just looking for an easy two-liner...

VHDL Full adder test bench output U

I'm a vhdl newbie.i wrote codings for a full adder using only AND and OR gates. I created a testbench to test my code and had it configured to stimulate all of eight logic combinations for A,B and Cin. when i run the simulation wave forms are correct for the inputs but the sum out put(H in my case) shows just "U".any ideas please.
library ieee;
use ieee.std_logic_1164.all;
--This program describes behaviour of a full adder constructed using
-- AND and OR gates. It employs component method which describes behaviour of
--AND,OR and NOT gates and use them to build the final object
--Entity description of the full adder
entity full_add is
port (a,b,c:IN BIT; h:OUT BIT);
end entity full_add;
--Description the 3 input And Gate
entity And2 is
port (j,k,l:in BIT; m:out BIT);
end entity And2;
architecture ex1 of And2 is
begin
m <= (j AND k AND l);
end architecture ex1;
--Description of the four input OR gate
entity Or2 is
port (d,e,f,g:IN BIT; h:OUT BIT);
end entity Or2;
architecture ex1 of Or2 is
begin
h <= (d or e or f or g);
end architecture ex1;
--Description of the NOT gate
entity Not1 is
port(x:in BIT; y:out BIT);
end entity Not1;
architecture ex1 of Not1 is
begin
y <= not x;
end architecture ex1;
--Components and wiring description
architecture netlist of full_add is
signal s,u,v,s2,u2,v2,w2:BIT;
begin
g1:entity WORK.Not1(ex1) port map(a,s);
g2:entity WORK.Not1(ex1) port map(b,u);
g3:entity WORK.Not1(ex1) port map(c,v);
g4:entity WORK.And2(ex1) port map(s,u,c,s2);
g5:entity WORK.And2(ex1) port map(s,b,v,u2);
g6:entity WORK.And2(ex1) port map(a,u,v,v2);
g7:entity WORK.And2(ex1) port map(a,b,v,w2);
g8:entity WORK.Or2(ex1) port map (s2,u2,v2,w2,h);
end architecture netlist;
You are going to have to debug the implementation : this will be quite a good exercise in using the simulator!
You see that "H" has value 'U' but you don't yet know why. Trace all the drivers of H back : in the posted code I can only see one, which is derived from inputs S2, U2, V2, W2.
In the simulator, add these signals to the Wave window and re-run the simulation : is one of them stuck at 'U'? If so, trace that signal back to find out why. If they all have valid values, that points to something else driving 'U' onto signal H.
Learn the "Drivers" command for your simulator (i.e. find and read the manual!) to identify all the signals driving H, and their values at a given time. There may be a driver in the (hidden to us) testbench. If so, change its driving value (perhaps with an H <= 'Z';" assignment) and re-run the simulation.
Essentially : learn and practice basic simulation debugging skills : one of these skills is likely to resolve the problem. And edit the question with what you have learned from them : if the problem persists, these results will point closer to it.

error in Assigning values to bytes in a 2d array of registers in Verilog .Error

Hi when i write this piece of code :
module memo(out1);
reg [3:0] mem [2:0] ;
output wire [3:0] out1;
initial
begin
mem[0][3:0]=4'b0000;
mem[1][3:0]=4'b1000;
mem[2][3:0]=4'b1010;
end
assign out1= mem[1];
endmodule
i get the following warnings which make the code unsynthesizable
WARNING:Xst:1780 - Signal mem<2> is never used or assigned. This unconnected signal will be trimmed during the optimization process.
WARNING:Xst:653 - Signal mem<1> is used but never assigned. This sourceless signal will be automatically connected to value 1000.
WARNING:Xst:1780 - Signal > is never used or assigned. This unconnected signal will be trimmed during the optimization process.
Why am i getting these warnings ?
Haven't i assigned the values of mem[0] ,mem[1] and mem[2]!?? Thanks for your help!
Your module has no inputs and a single output -- out1. I'm not totally sure what the point of the module is with respect to your larger system, but you're basically initializing mem, but then only using mem[1]. You could equivalently have a module which just assigns out1 to the value 4'b1000 (mem never changes). So yes -- you did initialize the array, but because you didn't use any of the other values the xilinx tools are optimizing your module during synthesis and "trimming the fat." If you were to simulate this module (say in modelsim) you'd see your initializations just fine. Based on your warnings though I'm not sure why you've come to the conclusion that your code is unsynthesizable. It appears to me that you could definitely synthesize it, but that it's just sort of a weird way to assign a single value to 4'b1000.
With regards to using initial begins to store values in block ram (e.g. to make a ROM) that's fine. I've done that several times without issue. A common use for this is to store coefficients in block ram, which are read out later. That stated the way this module is written there's no way to read anything out of mem anyway.

Does Fortran preserve the value of internal variables through function and subroutine calls?

After much painful debugging, I believe I've found a unique property of Fortran that I'd like to verify here at stackoverflow.
What I've been noticing is that, at the very least, the value of internal logical variables are preserved across function or subroutine calls.
Here is some example code to illustrate my point:
PROGRAM function_variable_preserve
IMPLICIT NONE
CHARACTER(len=8) :: func_negative_or_not ! Declares function name
INTEGER :: input
CHARACTER(len=8) :: output
input = -9
output = func_negative_or_not(input)
WRITE(*,10) input, " is ", output
10 FORMAT("FUNCTION: ", I2, 2A)
CALL sub_negative_or_not(input, output)
WRITE(*,20) input, " is ", output
20 FORMAT("SUBROUTINE: ", I2, 2A)
WRITE(*,*) 'Expected negative.'
input = 7
output = func_negative_or_not(output)
WRITE(*,10) input, " is ", output
CALL sub_negative_or_not(input, output)
WRITE(*,20) input, " is ", output
WRITE(*,*) 'Expected positive.'
END PROGRAM function_variable_preserve
CHARACTER(len=*) FUNCTION func_negative_or_not(input)
IMPLICIT NONE
INTEGER, INTENT(IN) :: input
LOGICAL :: negative = .FALSE.
IF (input < 0) THEN
negative = .TRUE.
END IF
IF (negative) THEN
func_negative_or_not = 'negative'
ELSE
func_negative_or_not = 'positive'
END IF
END FUNCTION func_negative_or_not
SUBROUTINE sub_negative_or_not(input, output)
IMPLICIT NONE
INTEGER, INTENT(IN) :: input
CHARACTER(len=*), INTENT(OUT) :: output
LOGICAL :: negative = .FALSE.
IF (input < 0) THEN
negative = .TRUE.
END IF
IF (negative) THEN
output = 'negative'
ELSE
output = 'positive'
END IF
END SUBROUTINE sub_negative_or_not
This is the output:
FUNCTION: -9 is negative
SUBROUTINE: -9 is negative
Expected negative.
FUNCTION: 7 is negative
SUBROUTINE: 7 is negative
Expected positive.
As you can see, it appears that once the function or subroutine is called once, the logical variable negative, if switched to .TRUE., remains as such despite the initialization of negative to .FALSE. in the type declaration statement.
I could, of course, correct this problem by just adding a line
negative = .FALSE.
after declaring the variable in my function and subroutine.
However, it seems very odd to me that this be necessary.
For the sake of portability and code reusability, shouldn't the language (or compiler maybe) require re-initialization of all internal variables each time the subroutine or function is called?
To answer your question: Yes Fortran does preserve the value of internal variables through function and subroutine calls.
Under certain conditions ...
If you declare an internal variable with the SAVE attribute it's value is saved from one call to the next. This is, of course, useful in some cases.
However, your question is a common reaction upon first learning about one of Fortran's gotchas: if you initialise an internal variable in its declaration then it automatically acquires the SAVE attribute. You have done exactly that in your subroutines. This is standard-conforming. If you don't want this to happen don't initialise in the declaration.
This is the cause of much surprise and complaint from (some) newcomers to the language. But no matter how hard they complain it's not going to change so you just have to (a) know about it and (b) program in awareness of it.
This isn't too different from static function-scoped variables in C or C++.
Programming language design was in its infancy, back when FORTRAN was
developed. If it were being designed from scratch today, no doubt many of the design
decisions would have been different.
Originally, FORTRAN didn't even support recursion, there was no dynamic memory
allocation, programs played all sorts of type-punning games with COMMON blocks
and EQUIVALENCE statements, procedures could have multiple entry points....so the
memory model was basically for the compiler/linker to lay out everything, even local
variables and numeric literal constants, into fixed storage locations, rather than on
the stack. If you wanted, you could even write code that changed the value of "2" to
"42"!
By now, there is an awful lot of legacy FORTRAN code out there, and compiler writers go to great lengths to preserve backward-compatible semantics. I can't quote chapter and verse from the standard that mandates the behavior you've noted, nor its rationale, but it seems reasonable that backward compatibility trumped modern language design sensibilities, in this instance.
This has been discussed several times here, most recently at Fortran assignment on declaration and SAVE attribute gotcha
You don't have to discover this behavior by experimentation, it is clearly stated in the better textbooks.
Different languages are different and have different behaviors.
There is a historical reason for this behavior. Many compilers for Fortran 77 and earlier preserved the values of ALL local variables across calls of procedures. Programmers weren't supposed to rely upon this behavior but many did. According to the standard, if you wanted a local variable (non-COMMON) to retain its value you needed to use "SAVE". But many programmers ignored this. In that era programs were less frequently ported to different platforms and compilers, so incorrect assumptions might never be noticed. It is common to find this problem in legacy programs -- current Fortran compilers typically provide a compiler switch to cause all variables to be saved. It would be silly for the language standard to require that all local variables retain their values. But an intermediate requirement that would rescue many programs that were careless with "SAVE" would be to require all variables initialized in their declarations to automatically have the SAVE attribute. Hence what you discovered....