In the below vhdl code though i have specified the range of variable it is counting endlessly. How to over come this problem - vhdl

the temp variable is storing data out of its range. The range is used to store the maximum final value but it is holding the previous value and goes on incrementing. The functionality of for loop which is condition based is not satisfingenter image description here
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity counter is
Port (clk,rst:in std_logic;
o:out integer range 0 to 15
);
end counter;
architecture Behavioral of counter is
signal temp2:integer range 1 to 15:=0;
begin
process(clk) is
begin
if rising_edge(clk) then
if rst='1' then
temp2<=0;
else
for i in 1 to 15
loop
temp2<=temp2+1;
end loop;
end if;
end if;
end process;
o<=temp2;
end Behavioral;

Range puts a constraint on an object (here the signal temp2) that says it is illegal, and hence, fail if this object receives a value that is outside of the range.
Your code then must take the actions (such as mod) to make this so.
Since your code assigns the value 0, I am assuming that you need to update your declaration as follows:
signal temp : integer range 0 to 15 ;
. . .
temp2<= (temp2+1) mod 16;

Related

Reading a matrix from file

I am trying to read a matrix from a file, it contains the colors of the pixels of a gray scale image. After this I will have to put the data I read into a register and perform some operations on it. When I am trying to simulate my code, the data is read alright in the "data" signal, but when I try to store an element, I read in the "test" signal to show it in the "last_elem" output it shows -2147483648. What am I doing wrong and why can't I access the data I read?
entity Main is
Port(
rstb:in std_logic;
clk:in std_logic;
row:out integer;
col:out integer;
last_elem:out integer
);
end Main;
architecture Behavioral of Main is
type matrixData is array(0 to 240, 0 to 217) of integer;
signal data:matrixData;
signal test:integer;
begin
process(clk)
file read_file:text;
VARIABLE file_line:LINE;
VARIABLE row_counter:INTEGER:=0;
variable rows:integer;
variable cols:integer;
variable read_value:integer;
begin
file_open(read_file, "D:\Faculta\An 3 Sem 2\SCS\image.txt", read_mode);
readline(read_file,file_line);
read(file_line, rows);
read(file_line, cols);
row<=rows;
col<=cols;
for i in 0 to rows-1 loop
readline(read_file,file_line);
for j in 0 to cols-1 loop
read(file_line, read_value);
data(i,j)<=read_value;
end loop;
end loop;
test<=data(0,0);
last_elem<=test;
file_close(read_file);
end process;
end Behavioral;
Providing a Minimal, Complete, and Verifiable example for your code:
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
entity main is
port (
rstb: in std_logic;
clk: in std_logic;
row: out integer;
col: out integer;
last_elem: out integer
);
end entity main;
architecture behavioral of main is
-- type matrixdata is array (0 to 240, 0 to 217) of integer;
type matrixdata is array (0 to 3, 0 to 2) of integer;
signal data: matrixdata;
signal test: integer;
begin
process (clk)
file read_file: text;
variable file_line: line;
variable row_counter: integer := 0;
variable rows: integer;
variable cols: integer;
variable read_value: integer;
begin
--file_open(read_file, "d:\faculta\an 3 sem 2\scs\image.txt", read_mode);
file_open (read_file, "image.txt", read_mode);
readline (read_file, file_line);
read (file_line, rows);
read (file_line, cols);
row <= rows;
col <= cols;
for i in 0 to rows - 1 loop
readline (read_file, file_line);
for j in 0 to cols - 1 loop
read(file_line, read_value);
data(i,j) <= read_value;
end loop;
end loop;
test <= data(0, 0);
last_elem <= test;
file_close(read_file);
end process;
end behavioral;
library ieee;
use ieee.std_logic_1164.all;
entity main_tb is
end entity;
architecture foo of main_tb is
component main is
port (
rstb: in std_logic;
clk: in std_logic;
row: out integer;
col: out integer;
last_elem: out integer
);
end component main;
signal rstb: std_logic := '1';
signal clk: std_logic := '0';
signal row: integer;
signal col: integer;
signal last_elem: integer;
begin
DUT:
main
port map (
rstb => rstb,
clk => clk,
row => row,
col => col,
last_elem => last_elem
);
WAVEFORM_DISPLAY_STIMULUS:
process
begin
wait for 0 ns;
wait for 1 ns;
wait;
end process;
end architecture;
Modified for a smaller two dimensional matrixdata type and supplied with a an input file:
images.txt
4 3
0 0 0
1 1 1
2 2 2
3 3 3
We see:
Where the matrix values appear to be read in correctly. The last_elem signal has the default value (INTEGER'LOW, -2147483648) as does test, both declarations lacking an initial value.
Neither Data nor test are in the process sensitivity list assignments will not occur in the same simulation cycle an assignment is scheduled. Every process executes at least once.
There's also an issue with the process sensitivity list. The process will execute for each event on clk, repetitively opening the file, reading in data and closing the file.
The proper fix for these two issues would be to remove the process sensitivity list and add a final wait statement (wait;) after the file_close. Also add a wait statement with zero incremental simulation time (e.g. wait for 0 ns;) prior to each signal assignment depending on a previous signal assignment value in the process.
There's also the issue of error detection during TEXTIO operations (file_open, read_line). You've gone to all the trouble to close the file. How about checking for a successful file open and ENDFILE before executing procedure read_line?
process
file read_file: text;
variable file_line: line;
variable row_counter: integer := 0;
variable rows: integer;
variable cols: integer;
variable read_value: integer;
variable open_status: FILE_OPEN_STATUS; -- ADDED
begin
--file_open(read_file, "d:\faculta\an 3 sem 2\scs\image.txt", read_mode);
-- file_open (read_file, "image.txt", read_mode);
file_open (open_status, read_file, "image.txt", read_mode);
case open_status is -- ADDED
when OPEN_OK =>
report "read_file opened for read" severity NOTE;
when STATUS_ERROR =>
report "read_file already open" severity FAILURE;
when NAME_ERROR =>
report "read_file file name not found" severity FAILURE;
when MODE_ERROR =>
report "read_file can't be opened for read" severity FAILURE;
end case;
if endfile(read_file) then -- ADDED
report "can't read first line from read_file"
severity FAILURE;
end if;
readline (read_file, file_line);
read (file_line, rows);
read (file_line, cols);
row <= rows;
col <= cols;
for i in 0 to rows - 1 loop
if endfile(read_file) then -- ADDED
report "can't read line for all rows from read_file"
severity FAILURE;
end if;
readline (read_file, file_line);
for j in 0 to cols - 1 loop
read(file_line, read_value);
data(i,j) <= read_value;
end loop;
end loop;
wait for 0 ns; -- ADDED causes a delta cycle, data is updated
test <= data(0, 0);
wait for 0 ns; -- ADDED causes a delta cycle, test is updated
last_elem <= test;
file_close(read_file);
wait; -- ADDED
end process;
This loads the array once at initialization and last_elem value will be updated after successive delta simulation cycles.
A wait statement causes an executing process to suspend until a condition is met. A wait statement without a condition assumes a timeout clause of TIME'HIGH.
A wait statement with a timeout clause (here 0 ns for the first two) will suspend the process until the condition is met. The incremental delay is equivalent to the current simulation time plus the time expression.
Because there's a further event scheduled for the current simulation time, a delta simulation cycle will occur in which the process resumes. At the beginning of each simulation cycle projected output waveform values scheduled for the current simulation time cause signal updates where the effective value of the signal can be evaluated (as in an assignment statement). This will occur for both of the first two wait statements.
Hitting the final wait statement without a timeout clause assume a timeout clause of TIME'HIGH, the process won't resume again during simulation.
You can prove the open_status and endfile tests work by manipulating the host file system (path and permissions) and image.txt file contents.
With an additional change to the testbench:
CLOCK:
process
begin
wait for 5 ns;
clk <= not clk;
if now > 40 ns then
wait;
end if;
end process;
-- WAVEFORM_DISPLAY_STIMULUS:
-- process
-- begin
-- wait for 0 ns;
-- wait for 1 ns;
-- wait;
-- end process;
You can demonstrate the code appears functional through simulation:
When simulating you'll only start the process at the first line once, only resume twice waiting on signal updates and only get one message from
report "read_file opened for read" severity NOTE;
when evaluating open_status.
As Tricky points out in a comment test is assigned the value of Data(0, 0) which is then assigned to last_element and actually contains the first element of the matrix.

VHDL record assignment through for loop

I have a for loop in process, which works fine with std_logic arrays, but not with record arrays. I use Xilinx ISE along with ISIM and the code is vhdl-93. The target will be a Spartan 3.
Here is the record definition:
TYPE spi_rx_t IS RECORD
CS : std_logic;
MOSI : std_logic;
CLK : std_logic;
END RECORD;
constant SYNC_LATCHES : integer := 2;
Here is the array definition and declaration:
type spi_rx_array_t is array (0 to SYNC_LATCHES) of spi_rx_t;
signal spi_in_array : spi_rx_array_t;
Below is the process:
spi_in_array(0).MOSI <= SPI_MOSI;
spi_in_array(0).CLK <= SPI_CLK;
spi_in_array(0).CS <= SPI_CS;
sync_p: process (clk_100)
begin
if rising_edge(clk_100) then
-- for I in 1 to SYNC_LATCHES loop
-- spi_in_array(I) <= spi_in_array(I - 1);
-- end loop;
spi_in_array(1) <= spi_in_array(0);
spi_in_array(2) <= spi_in_array(1);
end if;
end process;
The 2 lines below the commented code works exactly as expected (allowing me to synchronize external signals to clk_100), but I'd rather implement them as a for loop (such the commented one).
However, these commented lines does not produce the same result in my ISIM test bench (spi_in_array stays in unknown state when using the for loop). Why?
Please kindly help me with this.
As commented by Morten Zilmer, this is due to the VHDL concept "longest static prefix". This SO answer is similar to my issue.
In my case, the simplest way to resolve the issue was to move the assignment of the first element of the array into the same process as the for loop. I also had to decrease SYNC_LATCHES constant from 2 to 1, because spi_in_array(0) is now latched with clk_100.
sync_p: process (clk_100)
begin
if rising_edge(clk_100) then
spi_in_array(0).MOSI <= SPI_MOSI;
spi_in_array(0).CLK <= SPI_CLK;
spi_in_array(0).CS <= SPI_CS;
for I in 1 to SYNC_LATCHES-1 loop
spi_in_array(I) <= spi_in_array(I - 1);
end loop;
end if;
end process;

VHDL Delay before lighting led

I want to make a simple vhdl code which makes a delay of 20 sec before a led will be ON. i used a signal counter to make the delay of the 20 sec, but i've noticed to very strange thing, if i am not declare that the led is OFF before the delay, the led will be always ON.
look at the two codes (the clock is 50MHz):
in this code the led is always ON.
library ieee;
use ieee.std_logic_1164.all;
entity check is
port(clk : in std_logic;
led : out std_logic);
end check;
architecture arc of check is
signal counter : integer range 0 to 100e6;
begin
process(clk)
begin
if rising_edge(clk) then
if counter<500e6 then
counter<=counter+1;
else
led<='1';
end if;
end if;
end process;
end arc;
in this code the led is ON only after 20 seconds.
library ieee;
use ieee.std_logic_1164.all;
entity check is
port(clk : in std_logic;
led : out std_logic);
end check;
architecture arc of check is
signal counter : integer range 0 to 100e6;
begin
process(clk)
begin
if rising_edge(clk) then
if counter<500e6 then
counter<=counter+1;
led<='0';
else
led<='1';
end if;
end if;
end process;
end arc;
You should initialize both counter and led. In simulation, when you don't do this, value of each uninitialized signal will be 'U', which means you simply cannot be sure what value it will have in real system. Can be both 0 or 1.
You can use := '0' in port declaration.
Probably led is always on, because according to this code, if counter<500e6, the value of 'led' doesn't matter and else it's 1, so compiler simplified it, because the only one value the program sets to 'led' is '1'.

VHDL syn_looplimit and synthesis

I have a problem in synthesis with my VHDL code : I am trying to get the logarithm value of an input signal S_ink:
My code :
entity ....
....
architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;
logcalc:process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := S_ink+1; --S_ink is an input of my entity (integer)
log:=0;
loopabc:while (temp/=0) loop
temp:=temp/2;
log :=log+1;
end loop loopabc;
S_klog<=3*log;
end if;
end if;
end process;
It works very well in simulation but doesn't synthesize.
The error message is : "While loop is not terminating. You can set the maximum of loop iterations with the syn_looplimit attribute"
However, this code synthesize (but that is not what I want)
entity ....
....
architecture rtl of myEntity is
attribute syn_looplimit : integer;
attribute syn_looplimit of loopabc : label is 16384;
logcalc:process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := 3000; -- a random constant value
log:=0;
loopabc:while (temp/=0) loop
temp:=temp/2;
log :=log+1;
end loop loopabc;
S_klog<=3*log;
end if;
end if;
end process;
When the synthesis tool translates the design, it will make a circuit with a topology that does not depend on the data values, but where the wires carries the data values. The circuit must have a fixed calculation latency between each level of flip-flops, so timing analysis can determine if the amount of logic between flip-flops can fit for the specified frequency. In this process any loops are unrolled, and you can think of this as converting the loop to a long sequence of ordinary (non-loop) statements. To do this unrolling, the synthesis tool must be able to determine the number of iterations in the loops, so it can repeated the loop body this number of times when doing loop unrolling.
In the first code example the number of iterations in the loop depends on the S_ink value, so the synthesis tool can't unroll the loop to a fixed circuit, since the circuit depends on the data value.
In the second code example the synthesis tool can determine the number of iterations in the loop, thus do the unrolling to a fixed circuit.
One way to address this is make the algorithm with a fixed number of iteration, where this number of iterations can handle the worst case input data, and where any superfluous iteration on other input data will not change the result.
Solution :
process(I_clk)
variable temp : integer;
variable log : integer;
begin
if(I_clk'event and I_clk='1') then
if (IN_rst='0') then
S_klog<=0;
temp:=0;
log:=0;
else
temp := S_ink+1;
log:=0;
for I in 1 to 14 loop
temp := temp/2;
if (temp /=0) then
log :=log+1;
end if;
end loop;
S_klog<=3*log; -- 3*log because of my application
end if;
end if;
end process;

How to fix Xilinx ISE warning about sensitivity list?

I synthesized my design with Xilinx ISE 13.1. Target device is Virtex 5. Then I encountered this warning:
WARNING:Xst:819 - "F:/FRONT-END/h264/inter/src/eei/eei_mvd.vhd"
line 539: 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:
<mvd_l0<3><3>>, <mvd_l0<3><2>>, <mvd_l0<3><1>>, <mvd_l0<3><0>>, <mvd_l0<2><3>>, <mvd_l0<2><2>>,
<mvd_l0<2><1>>, <mvd_l0<2><0>>, <mvd_l0<1><3>>, <mvd_l0<1><2>>, <mvd_l0<1><1>>, <mvd_l0<1><0>>,
<mvd_l0<0><3>>, <mvd_l0<0><2>>, <mvd_l0<0><1>>, <mvd_l0<0><0>>, <mvd_l1<3><3>>, <mvd_l1<3><2>>,
<mvd_l1<3><1>>, <mvd_l1<3><0>>, <mvd_l1<2><3>>, <mvd_l1<2><2>>, <mvd_l1<2><1>>, <mvd_l1<2><0>>,
<mvd_l1<1><3>>, <mvd_l1<1><2>>, <mvd_l1<1><1>>, <mvd_l1<1><0>>, <mvd_l1<0><3>>, <mvd_l1<0><2>>,
<mvd_l1<0><1>>, <mvd_l1<0><0>>, <mvd<0>>, <mvd<1>>
Here is my source code:
proc_update_next: process(mvd_l0, mvd_l1, mvd, subMBPart_Idx, MBPart_Idx, eei_info )
begin
--// Init
next_mvd_l0 <= mvd_l0;
next_mvd_l1 <= mvd_l1;
--// Change
if eei_info.mb_type = BLK_8x8 then
for i in 3 downto 0 loop
for j in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) and j = to_integer(unsigned(subMBPart_Idx)) then
next_mvd_l0(i)(j) <= mvd(0);
next_mvd_l1(i)(j) <= mvd(1);
end if;
end loop;
end loop;
else
for i in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) then
next_mvd_l0(i)(0) <= mvd(0);
next_mvd_l1(i)(0) <= mvd(1);
end if;
end loop;
end if;
end process;
Update: I change a little bit in my code and still this warning.
The mvd_l0 and mvd_l1 is two-dimension array and it appeared on sensitivity list. I know my source code is too abstract and ISE may can not understand.
I tried with Virtex 7 (not avaiable in laboratory) then there are no error. So, my question is how to fix this warning ? I can't ignore this warning because it can lead to latch.
Use the VHDL-2008 construct process(all) to tell the tools you want the sensitivity list to include all signals which are read.
Alternatively, make it a clocked process, only sensitive to the clock, and then you don't have to worry either.
You should only set signals like next_mvd_l0 and next_mvd_l1 once for a set of conditions. The "init" section is still an issue. It may be better to use local variables if you are avoiding reseting the process.
Best option: add a reset to the sensitivity list and if its enabled, set next_mvd_* to your init values
--// Init
if (reset = '1') then
next_mvd_l0 <= mvd_l0;
next_mvd_l1 <= mvd_l1;
end if;
Second option: use a local variable
proc_update_next: process(mvd_l0, mvd_l1, mvd, subMBPart_Idx, MBPart_Idx, eei_info )
variable mvd_10_local : 2dArrayType;
variable mvd_11_local : 2dArrayType;
begin
--// Init
mvd_10_local := mvd_l0;
mvd_11_local := mvd_l1;
--// Change
if eei_info.mb_type = BLK_8x8 then
for i in 3 downto 0 loop
for j in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) and j = to_integer(unsigned(subMBPart_Idx)) then
mvd_10_local(i)(j) := mvd(0);
mvd_11_local(i)(j) := mvd(1);
end if;
end loop;
end loop;
else
for i in 3 downto 0 loop
if i = to_integer(unsigned(MBPart_Idx)) then
mvd_10_local(i)(j) := mvd(0);
mvd_11_local(i)(j) := mvd(1);
end if;
end loop;
end if;
next_mvd_l0 <= mvd_10_local;
next_mvd_l1 <= mvd_l1_local;
end process;
You use the VHDL record construct (eei_info.mb_type). You can add every record element to the sens-list to make xst happy. I just ignore this warning.

Resources