Warning about getting "X"es for 4-valued logic VHDL - vhdl

I am getting a warning that an arithmetic operation have X so the result is will always be X, although I am initializing my signals to 0s. Can anyone help?
N.B. I am getting X for Z_count and RC_count_var
--RC counter
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
Entity RC_counter2 is
Port(load, Cplus, Cminus : In Std_logic;
X: In std_logic_vector (3 downto 0) :="0000";
Z_count: Out std_logic_vector (3 downto 0) :="0000");
end Entity;
Architecture behav of RC_counter2 is
signal RC_count_var: std_logic_vector(3 downto 0):="0000";
Begin
process(Cplus, load)
--variable RC_count_var: std_logic_vector(3 downto 0):="0000";
Begin
if load = '1' then
RC_count_var <= X;
end if;
if (Cplus'EVENT and Cplus = '1') then
RC_count_var <= RC_count_var + 1;
else
RC_count_var <= RC_count_var;
end if;
end process;
process(Cminus, load)
Begin
if load = '1' then
RC_count_var <= X;
end if;
if (Cminus'EVENT and Cminus = '1') then
RC_count_var <= RC_count_var - 1;
else
RC_count_var <=RC_count_var;
end if;
end process;
Z_count <= RC_count_var;
end Architecture;

The value of RC_Count_var becomes invalid because it has multiple conflicting drivers.
In VHDL, whenever a signal is assigned in more than one process, it implies multiple drivers. These are usually not supported for synthesis and not recommended altogether. To make sure you do not have multiple drivers, simply makes all assignations to a signal in a single process.
Moreover, while not exactly wrong or problematic, I suggest you modify the following code:
if load = '1' then
RC_count_var <= X;
end if;
if (Cplus'EVENT and Cplus = '1') then
RC_count_var <= RC_count_var + 1;
else
RC_count_var <= RC_count_var;
end if;
This doesn't gives multiple drivers, but has several problems. First, successive assignments to the same signal in a process overrides previous one. Thus, if cplus is rising and load is '1', the value doesn't get loaded. It is much better and cleaner to use elsif or else. Also, synthesis target doesn't usually support asynchronous load. Asynchronous set/reset is fine, but asynchronous load to the value X, in your case, is likely problematic.

Related

Using To_signed VHDL, "No feasible entries for subprogram To_signed"

I'm working on a delay unit for a sound synthesizer on a FPGA, but when trying to compile in Modelsim to simulate i get the following error:
"No feasible entries for subprogram TO_SIGNED".
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY Delay IS
-- Delay time in ms
PORT(
Sample : in STD_LOGIC_VECTOR(11 DOWNTO 0);
Delay : in INTEGER RANGE 0 to 2000; -- Echo Delay in ms, <2s
Gain : in INTEGER Range 0 to 7; -- Gain of the Echo, 0/8 to 7/8
clk : in STD_LOGIC;
Reset : in STD_LOGIC;
Output : Out STD_LOGIC_VECTOR(11 DOWNTO 0)
);
END Delay;
ARCHITECTURE Delay_Arch OF Delay IS
BEGIN
DelayOffset <= Delay*40; -- Number of steps back in the buffer for x ms delay
Process(clk)
BEGIN
IF (Reset = '1') THEN -- Standard Reset
CircBuffer <= (OTHERS=>(OTHERS=>'0'));
Counter <= 0;
ELSIF RISING_EDGE(clk) THEN
CircBuffer(Counter) <= Sample; -- Save Data in to circBuffer
IF (DelayOffset > Counter) THEN -- Wrap around for counter
OutBuff(11 DOWNTO 0) <= CircBuffer(79999-(DelayOffset-Counter));
ELSE
OutBuff(11 DOWNTO 0) <= CircBuffer(Counter-DelayOffset); -- Load sound from previous Sample (Delay)
END IF;
OutBuffInt <= (To_integer(Signed(OutBuff)) * Gain); -- Multiply with gain
Outvect <= To_signed(OutBuffInt, Outvect'length); <----- ERROR
Output <= Outvect(14 DOWNTO 3);
IF (Counter = 79999) THEN
Counter <= 0;
ELSE
Counter <= Counter + 1;
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;
I can't find any problems in the code. Is there something that i am missing, or is just the to_signed not working correctly?
There are multiple problems here as Morten Zilmer points out. But to answer what you asked, the "No feasible entries for subprogram" error means that the types of the arguments and/or target of the function call does not match any available declarations. In your case there is only one function named to_signed visible, which is defined like this in ieee.numeric_std:
function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED;
You did not include your signal declarations, but I would guess that your Outvect signal is declared as std_logic_vector and not signed, hence the error.

Cannot create latch and counter with 2 clock signals in VHDL

I am completely new to programming CPLDs and I want to program a latch + counter in Xilinx ISE Project Navigator using VHDL language. This is how it must work and it MUST be only this way: this kind of device gets 2 clock signals. When one of them gets from HIGH to LOW state, data input bits get transferred to outputs and they get latched. When the 2nd clock gets from LOW to HIGH state, the output bits get incremented by 1. Unfortunately my code doesn't want to work....
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity counter8bit is
port(CLKDA, CLKLD : in std_logic;
D : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0));
end counter8bit;
architecture archi of counter8bit is
signal tmp: std_logic_vector(7 downto 0);
begin
process (CLKDA, CLKLD, D)
begin
if (CLKLD'event and CLKLD='0') then
tmp <= D;
elsif (CLKDA'event and CLKDA='1') then
tmp <= tmp + 1;
end if;
end process;
Q <= tmp;
end archi;
Is there any other way around to achieve this?? Please for replies. Any kind of help/suggestions will be strongly appreciated. Many thanks in advance!!
Based on the added comments on what the counter is for, I came up with the following idea. Whether it would work in reality is hard to decide, because I would need a proper timing diagram for the EPROM interface. Importantly, there could be clock domain crossing issues depending on what restrictions there are on how the two clock signals are asserted; if there can be a falling edge of CLKLD close to a rising edge of CLKDA, the design may not work reliably.
signal new_start_address : std_logic := '0';
signal start_address : std_logic_vector(D'range) := (others => '0');
...
process (CLKLD, CLKDA)
begin
if (CLKDA = '1') then
new_start_address <= '0';
elsif (falling_edge(CLKLD)) then
start_address <= D;
new_start_address <= '1';
end if;
end process;
process (CLKDA)
begin
if (rising_edge(CLKDA)) then
if (new_start_address = '1') then
tmp <= start_address;
else
tmp <= tmp + 1;
end if;
end if;
end process;
I'm not completely clear on the interface, but it could be that the line tmp <= start_address; should become tmp <= start_address + 1;
You may also need to replace your assignment of Q with:
Q <= start_address when new_start_address = '1' else tmp;
Again, it's hard to know for sure without a timing diagram.

Error(10820) and (10822) VHDL

i am trying to write a code but i get error, i dont understand that, i am new to vhdl, any help would be appreciated.
code:
entity counter is
port
(
upp_down : in std_logic;
rst : in std_logic;
pressed : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;
architecture rtl of counter is
signal count_value: std_logic_vector(3 downto 0);
begin
process (rst,pressed,upp_down)
begin
if(rst'event and rst = '0') then
count <= "0000";
else
if(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
end if;
end if;
end process;
count <= count_value;
end rtl;
Errors:
Error (10820): Netlist error at counter.vhd(28): can't infer register for count_value[1] because its behavior depends on the edges of multiple distinct clocks
Error (10822): HDL error at counter.vhd(28): couldn't implement registers for assignments on this clock edge
The first problem is that you're trying to use the edge of two different 'clocks' in one process. A particular process can only respond to one clock.
The second problem is that your code does not translate into any real-world hardware. There's nothing in the FPGA that can respond to there not being an edge of a clock, which is what you have described with your if(rst'event and rst = '0') then else structure.
Nicolas pointed out another problem (which your compiler didn't get as far as), which is that you're assigning count both inside and outside a process; this is not allowed, as signals can only be assigned in one process.
Generally the type of reset it looks like you're trying to implement would be written as in the example below:
process (rst,pressed,upp_down)
begin
if(rst = '0') then
count_value <= "0000";
elsif(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
end if;
end process;
count <= count_value;
The reason for changing the reset to affect count_value, is that without this, the effect of your reset would only last one clock cycle, after which the count would resume from where it left off (Thanks #Jim Lewis for this suggestion).
In addition to your compile errors, you should try to use the rising_edge() or falling_edge() functions for edge detection, as they behave better than the 'event style.
The reset can be more easily implemented using count_value <= (others => '0'); this makes all elements '0', no matter how long count is.
Lastly, it looks like you're using the std_logic_arith package. There are many other answers discouraging the use of this package. Instead, you should use the numeric_std package, and have your counter of type unsigned. If your output must be of type std_logic_vector, you can convert to this using a cast: count <= std_logic_vector(count_value);.
One more thing, I just noticed that your counter is not initialised; this can be done in the same way as I suggested for the reset function, using the others syntax.
"count" can't be assigned inside and outside a process.
count <= "0000"; <-- inside process
count <= count_value; <-- outside process.
You should do "count <= count_value;" inside your process :
entity counter is
port
(
upp_down : in std_logic;
rst : in std_logic;
pressed : in std_logic;
count : out std_logic_vector(3 downto 0)
);
end entity;
architecture rtl of counter is
signal count_value: std_logic_vector(3 downto 0);
begin
process (rst,pressed,upp_down)
begin
if(rst'event and rst = '0') then
count <= "0000";
else
if(pressed'event and pressed = '0' ) then
if(upp_down = '1') then
count_value <= count_value + 1;
elsif(upp_down = '0') then
count_value <= count_value - 1;
end if;
count <= count_value;
end if;
end if;
end process;
end rtl;

Out come of vhdl code not as expected

I want to take num as as an 8 bit input and then shift it on every rising edge of clock and out it on output "res". Code is shown below. But when simulated it does not give expected results.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity shiftreg is
port (
num : in std_logic_vector (7 downto 0);
clk : in std_logic;
res : out std_logic_vector (7 downto 0)
);
end entity;
architecture behav of shiftreg is
signal temp_num : std_logic_vector (7 downto 0):= "00000000";
begin
process(num)
begin
if(num' event) then
temp_num <= num;
res<=temp_num;
end if;
end process;
process(clk)
begin
if(rising_edge(clk)) then
temp_num <= shr(temp_num,"01");
res<=temp_num;
end if;
end process;
end behav;
The output res and signal temp_num are both driven from both of the
processes, thus the simulator will do resolution, which is likely to result in
X values for some or all bits.
In general, then signals and output is design modules should be driven from
only a single process, since that is also what synthesis tools expect. For
test benches, then there may be multiple drivers.
So if the intention is that any change in the num input should be reflected
immediately to the res output, and any later rising edge of clk should
result in right shift, then the two processes may be combined in a single
process and assign to res like:
process (num, clk) is
begin
if (num'event) then
temp_num <= num;
elsif (rising_edge(clk)) then
temp_num <= shr(temp_num, "01");
end if;
end process;
res <= temp_num;
This will work in simulation, but the 'event wont work in synthesis, since
there is typically no hardware that can sense value changes like 'event, so
the construction can't be mapped to hardware by synthesis.
So for a synthesizeable design, you may consider adding a load input:
load : in std_logic;
And use this for load of the internal temp_num with a process like:
process (clk) is
begin
if (rising_edge(clk)) then
if load = '1' then
temp_num <= num;
else
temp_num <= shr(temp_num, "01");
end if;
end if;
end process;
res <= temp_num;
Finally, you should consider removing the use ieee.std_logic_arith.all; and
use ieee.std_logic_unsigned.all;, since these two packages are not standard
VHDL packages, despite location in the IEEE library. Simply remove the two
lines, and then use the shift_right function from the std_logic_unsigned
like:
temp_num <= std_logic_vector(shift_right(unsigned(temp_num), 1));

VHDL variable check in clk cycle

I am trying to compare two values in a clk cycle
eg:
if(riding_edge(clk)) then
if (some signal = other) then
other<=other+1;
else other<=other;
if(other=3)then
flag=1;
end if;
end if;
The code compiles and runs fine but when I am seeing the simulation window, the flag gets set no matter what is the value of other. Am I doing something wrong or the value of other is fluctuating.
The above is a pseudo code and everything is correct syntactically.
Please Help
Thanks in advance
Without a minimal working example, I could only guess that you're inferring a latch by not specifying what happens to flag when other is not 3. To prevent this, you would specify all cases of any decision tree.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY example IS
PORT (some_signal : IN STD_LOGIC;
other : IN STD_LOGIC;
clk : IN STD_LOGIC;
flag : OUT STD_LOGIC;
);
END example;
ARCHITECTURE minimal OF example IS
BEGIN
minexample:PROCESS(clk)
BEGIN
IF (clk'EVENT and clk='1') THEN
IF some_signal = other THEN
other <= other + '1';
ELSE other <= other;
END IF;
IF(other = '1') THEN
flag <= '1';
ELSE flag <= '0'; -- always specify all cases
END IF;
END IF;
END PROCESS minexample;
END minimal;
I use the code of N8TRO and add an reset to set the signal to zero at the startup and change the signal other to integer (because you like to check on the value 3) and check on rising_edge (should be the better way).
Now the signal flag should raise to high after 4 clocks after the Reset is set to low. Is this the behavior you expect?
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY example IS
PORT (some_signal : IN STD_LOGIC;
other : IN integer range 0 to 3; --this should be an integer 2 bit widht
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
flag : OUT STD_LOGIC;
);
END example;
ARCHITECTURE minimal OF example IS
BEGIN
minexample:PROCESS(clk,reset)
BEGIN
IF (reset = '1') then --i think a reset is a good idea
flag <= '0';
other <= 0;
ELSIF (rising_edge(clk)) THEN
IF some_signal = other THEN
other <= other + 1;
ELSE
other <= other;
END IF;
IF(other = 3) THEN --other is now an integer, so you can check on 3
flag <= '1';
ELSE
flag <= '0'; -- always specify all cases
END IF;
END IF;
END PROCESS minexample;
END minimal;

Resources