Undefined relational operator for two objects of the same type - VHDL - operators

I currently have a project in VHDL to make a simple vending machine. I have a std_logic signal to determine if the cash in is greater than or equal to the price of the item. The cost is an unsigned constant and the cash is an unsigned signal, but despite them both being unsigned numbers of equal bit length, it tells me the >= operator is undefined. I've looked in multiple reference guides, and all I can find is that the two arguments must be the same type (which they are...) so I'm not sure why it's throwing this error
I have included the proper numeric_std library.
type STATE_TYPE is (RDY, CLCT, VND);
signal state : STATE_TYPE;
signal next_state : STATE_TYPE;
signal cash : unsigned (7 downto 0);
signal cashnew : unsigned (7 downto 0);
signal candy : std_logic;
signal candy_vend : std_logic;
constant cost_candy : unsigned := to_unsigned(60, 8);
signal chips : std_logic;
signal chips_vend : std_logic;
constant cost_chips : unsigned := to_unsigned(50, 8);
begin
candy <= candy1 or candy2 or candy3;
chips <= chip1 or chip2;
candy_vend <= candy and (cash >= cost_candy);
chips_vend <= chips and (cash >= cost_chips);

As in other languages, VHDL has a boolean type. It is a integral type and provided in package std.standard. Thus this type is always visible, because this package is referenced by default.
Also like in other languages, a relational operator results in a boolean value. Neither the integral type bit nor the digital logic type std_logic is a boolean. Boolean has values true and false, where as bit has 0 and 1. The std_logic type supports 9 values (9-valued logic, including e.g. error values).
Most operators are defined to accept the right and left operands of the same type, while returning that type again.
So you need to convert your expression at some point back to std_logic, because candy_vend is expecting that type.
Solution 1:
candy_vend <= candy and ('1' when (cash >= cost_candy) else '0');
Solution 2:
candy_vend <= '1' when ((candy = '1') and (cash >= cost_candy)) else '0';
Solution 3:
function to_sl(value : boolean) return std_logic is
begin
if value then
return '1';
else
return '0';
end if;
end function;
Usage:
candy_vend <= candy and to_sl(cash >= cost_candy);
candy_vend <= to_sl((candy = '1') and (cash >= cost_candy));

Related

Why the procedure doesn't see the variable?

I'm using Xilinx ISE to create a VHDL project.
I'm trying to add values to an integer variable.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity vending2_mod is
Port ( button1 : in STD_LOGIC;
button2 : in STD_LOGIC;
button3 : in STD_LOGIC;
button4 : in STD_LOGIC;
coin : in integer;
disp : out string(1 to 16);
prodOut : out integer);
shared variable credits : integer := 0;
procedure addCredits ( c : in integer ) is
begin
credits := credits + c; -- Signal is not defined : 'credits'.
end addCredits;
-- additional code
end vending2_mod;
architecture Behavioral of vending2_mod is
begin
acceptCredit: process (coin)
begin
addCredits(coin);
end process;
end Behavioral;
Yet when I try to Synthesize (XST) the project, I'm getting an error to the line I've written it as a comment. The credits is not a signal, it is a variable; what gives the error?
Saving gives no errors, since the syntax seems to be correct.
Entity-statements must be -passive statements, that is, they must not
assign values to any signals.
Don't use shared variables.
In simulation, variables update immediately upon assignment, as opposed to signals, which are updated only at the end of a simulation cycle. In combinational code, signals immediately take the value of their assignment. In sequential code, signals are used to create flip-flops, which inherently do not immediately take the value of their assignment.
it is better to use signal+clock instead.
Try this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity vending2_mod is
port(
Clock: in std_logic;
Reset: in std_logic;
coin : in integer;
prod_out : out integer
);
end vending2_mod;
architecture Behavioral of vending2_mod is
signal credits : integer := 0;
begin
process(Clock,Reset)
begin
if Reset='1' then
credits <= 0;
elsif(rising_edge(Clock)) then
credits <= credits + coin;
end if;
end process;
prod_out <= credits;
end Behavioral;
See elaborated design:
Don't try this (synthesis OK, note: You need clock):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity vending2_mod is
Port (
coin : in integer;
prod_out : out integer);
end vending2_mod;
architecture Behavioral of vending2_mod is
signal credits : integer := 0;
begin
credits <= credits + coin;
prod_out <= credits;
end Behavioral;
See elaborated design:

Crossing clock domain for rarly changing data

I need to connect a configuration module (running at slower clock) to a worker which runs at higher speed. Standard answer seems to be a FIFO but I thought I come up with a simpler solution which consumes less resources - with drawback of having much higher latency. Benefit for me is that I don't need to regenerate FIFO IP for each possible size of data. In RTL simulation it seems to work (I run into troubles using post-synthesis one unrelated to question).
Am I missing something or is the following code correct:
module fifo_int#( // This is bad name. I haven't come up with better yet
parameter type DATA = logic [31:0]
)(
input logic rst,
input logic clk_in,
input DATA din,
input logic clk_out,
output DATA dout
);
DATA dreg;
enum logic [1:0] {
IN,
STABLE,
WAIT_OUT
} in_state;
enum logic [1:0] {
WAIT_IN,
WRITE,
INV
} out_state;
logic in_output[3], out_output[3];
initial begin
in_state <= IN;
out_state <= WAIT_IN;
for (int i = 0; i < 3; i++) begin
in_output[i] <= 0;
out_output[i] <= 0;
end
end
always #(posedge clk_in)
begin
case (in_state)
IN: begin
dreg <= din;
in_state <= STABLE;
end
STABLE: begin
in_state <= WAIT_OUT;
in_output[0] <= ~in_output[0];
end
WAIT_OUT: begin
in_state <= (in_output[0] == out_output[2]) ? IN : WAIT_OUT;
end
endcase
out_output[1] <= out_output[0];
out_output[2] <= out_output[1];
end
always #(posedge clk_out)
begin
case (out_state)
WAIT_IN: begin
out_state <= (in_output[2] == out_output[0]) ? WAIT_IN : WRITE;
end
WRITE: begin
dout <= dreg;
out_state <= INV;
end
INV: begin
out_output[0] <= ~out_output[0];
out_state <= WAIT_IN;
end
endcase
in_output[1] <= in_output[0];
in_output[2] <= in_output[1];
end
endmodule
If your clocks are asynchronous, you're going to need synchronization.
For synchronous clocks, since your slow side is the one producing the data, you don't need any buffering. Data is anyway held stable for multiple (fast) clock cycles, so you don't really need any logic between the domains.

Counter inside FSM in VHDL

I have got a small problem with my finite state machine which I have
written in VHDL recently. I tried to create "intelligent" counter
triggered by clock with frequency 2 Hz.
This counter is built in one state of FSM and is started by pushing a
button on DE2 board.
Firstly, whole system is in IDLE state and if I push this button, state is
changed to COUNTING and counter begin to be incremented and his current
value is shown on LED display. After it reach value of modulo, the state
COUNTING is left back to IDLE and the counter is set up to zero.
My problem is that the counter doesn´t work correctly - the counting
value was too great. So I tried to solve it with this construction: if
(clk_tick´event and clk_tick = 1) then.... , there are some errors by
synthesis:
Error (10822): HDL error at Citac_FSM.vhd(57): couldn't implement
registers for assignments on this clock edge
Error (10821): HDL error at Citac_FSM.vhd(62): can't infer register for
"AUTOMAT:flg" because its behavior does not match any supported register
model
Please, does somebody have an idea to solve it? And what is it correct way
to write clock triggered FSM with two (or more) clock sources?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
ENTITY Counter_FSM IS
GENERIC (
REGSIZE : integer := 8; -- range of counter
MODULO : natural := 50 -- modulo value
);
PORT (
CLK : IN STD_LOGIC; -- puls 50 MHz
CLK_tick : IN STD_LOGIC; -- puls 2 Hz
RESET : IN STD_LOGIC; -- reset
READY : OUT STD_LOGIC; -- counter is ready to start
START_C : IN STD_LOGIC; -- start of counting
DOUT : OUT STD_LOGIC_VECTOR(REGSIZE - 1 downto 0) --out
);
END Counter_FSM;
ARCHITECTURE Behavior OF Counter_FSM is
type counterState is (IDLE, COUNTING); -- states of FSM
signal currCounterState : counterState; -- current state
signal nextCounterState : counterState; -- next state
signal cnt : std_logic_vector(REGSIZE - 1 downto 0); -- counter
begin
UPDATE: process(RESET, CLK)
begin
if (RESET = '0') then
currCounterState <= IDLE;
elsif (CLK'event and CLK = '1') then
currCounterState <= nextCounterState;
end if;
end process;
COMBI: process (clk_tick, start_c, currCounterState)
variable flg : std_logic := '0';
begin
if (clk_tick'event and clk_tick = '1') then
flg := '1';
end if;
case currCounterState is
when IDLE =>
cnt <= (others => '0'); -- counter value = zero
READY <= '1'; -- we can start
if (start_c = '1') then -- if button is pushed
nextCounterState <= COUNTING; -- go to COUNTING
end if;
when COUNTING =>
READY <= '0';
if (flg = '1') then -- Was there impuls of 2 Hz?
cnt <= cnt + 1; -- yes -> incrementing
flg := '0';
if (cnt = MODULO) then -- if cnt = MODULO
cnt <= (others => '0'); -- then cnt = zero
nextCounterState <= IDLE;
end if;
end if;
when others =>
nextCounterState <= IDLE;
end case;
-- OUTPUT
douT <= cnt;
end process;
end Behavior;
Thank you very much.
Mirek
P.S.: I am sorry my English is not so good.
First of all you should not use clk_tick as a second clock signal.
What you should do is to save the previous value of clk_tick, then compare the current value of clk_tick to the previous value to detect a rinsing edge. Depending on how clk_tick is generated you might need to synchronize clk_tick to the clock domain of CLK.
You could write something like this:
when COUNTING =>
nextCounterState <= COUNTING;
READY <= '0';
if (prev_clk_tick = '0' and clk_tick = '1') then
next_cnt <= cnt + 1; -- yes -> incrementing
if (cnt = MODULO) then
next_cnt <= (others => '0');
nextCounterState <= IDLE;
end if;
end if;
I will leave it to you to add the extra registers.
I have already solved my problem :-). I have moved the counter into separate process and then attached witch signals to FSM. So, it works very well.
By reading of button I am using two D flip-flops to synchronize it at the moment.
I have to make an observation on style of VHDL programming - it is too different to "normal" programming like C language :-D
Nice day!

Value U is missing in select

Below is a few lines of code extracted from source.
When I try to build the code, the "Enumerated value U is missing in select." error appears and I have no idea why. I know though, that STD_LOGIC has 9 states ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'). Dunno how to cover U.
entity cpu is
port (
DATA_ADDR : out std_logic_vector(12 downto 0);
-- a few more ports
);
end cpu;
architecture behavioral of cpu is
signal prog_data : STD_LOGIC_VECTOR(12 downto 0);
signal uk_data : STD_LOGIC_VECTOR(12 downto 0);
signal sel : STD_LOGIC;
-- a few more signals
begin
with sel select
DATA_ADDR <= prog_data when '0', -- error in this section
uk_data when '1';
--a few lines of code
end behavioral;
Two (easier) choices:
Handle it explicitly if you care about the other states (maybe for sim?):
with sel select
DATA_ADDR <= prog_data when '0',
uk_data when '1',
(others => 'X') when others;
Make an assumption if you don't:
with sel select
DATA_ADDR <= prog_data when '0',
uk_data when others,
or for even easier code, use conditional assignment instead of selected assignment:
DATA_ADDR <= prog_data when sel = '0' else uk_data;
Selected assignment is akin to a sequential case statement - every possible value must be covered, and others can be used to catch the ones you don't need to handle explicitly. Conditional assignment is akin to a sequential if ... else, where you can handle whatever condition(s) you feel like - there is no requirement that you have branches for every conceivable condition.

Signals and Variables in VHDL

I want to ask about the signals and variables in VHDL, I know the difference between them, but I want to see the difference at simulation.
I used this simple program in Quartus Tool to see the difference between them:
ENTITY test IS PORT (
a : IN bit;
y : OUT bit);
END test;
ARCHITECTURE beh OF test IS
SIGNAL x : BIT;
BEGIN
PROCESS (a)
BEGIN
x <= '1';
IF x = '1' THEN y <= '0' AFTER 8 ns;
ELSE y <= '1' AFTER 5 ns;
END IF;
END PROCESS;
END BEH;
for signals and this for variables:
entity test1 is port (
a : IN bit;
y : OUT bit);
end test1;
architecture beh of test1 is
begin
process (a)
variable x : bit;
begin
x := '1';
if x = '1' then y <= '0' after 8 ns;
else y <= '1' after 5 ns;
end if;
end process;
end beh;
the i created waveform to see the difference in the first program (y)value should be set to 1 at 5ns,but it doesn't change..Why?
Thank you in advance.
You don't see the difference in waveforms, as the waveform viewer only shows the values of variables at the end of a delta cycle (ie when some real time passes). If you single-step the code, or add report statements mid process, you can see intermediate values on a variable:
signal s:integer := 0;
process
variable v:integer := 0;
begin
report "Signal="&integer'image(s)&" variable="&integer'image(v);
s <= 1; v := 1;
report "Signal="&integer'image(s)&" variable="&integer'image(v);
wait for 0 ps; -- end the delta cycle, even 0ps counts as "time passing"
report "Signal="&integer'image(s)&" variable="&integer'image(v);
wait;
end process;
You put signal "a" on sensitive list then it lead to a "latch".
For update y, you should put "x" on sensitive list or change "a" like a trigger signal.
In your case, signal and variable is similar because you fixed it as a constant.
For addition, you should upload your testbench with behaviour of signal "a".
Edit: I'm wrong about put "x" in sensitive list. Thanks to #damage
This piece of code should illustrate the difference b/w signals and variables.
I inserted the processes directly into the testbench, so the code can be directly simulated with a HDL simulator of your choice.
After 10 ns the start event is fired and both processes are evaluated.
You should then see the expected result, namely sig_outgoing high after another 20 ns, whereas var_out should be high after only 10 ns.
library ieee;
use ieee.std_logic_1164.all;
entity sigvartest is
end entity sigvartest;
architecture behav of sigvartest is
signal start : std_logic := '0'; -- event to start simulation
signal x_sig : std_logic := '0'; -- signal tested in SIGPROCESS
signal sig_out : std_logic := '0'; -- output of SIGPROCESS
signal var_out : std_logic := '0'; -- output of VARPROCESS
begin
start <= '0', '1' after 10 ns; -- pretty self-explanatory, start goes high after 10 ns
SIGPROCESS:
process(start) is
begin
if(rising_edge(start)) then
x_sig <= '1'; -- signal is scheduled to be assigned its new value, no immediate change!
if(x_sig = '1') then
sig_out <= '1' after 10 ns;
else
sig_out <= '1' after 20 ns; -- this part will execute
end if;
end if;
end process;
VARPROCESS:
process(start) is
variable x_var : std_logic := '0';
begin
if(rising_edge(start)) then
x_var := '1'; -- variable is assigned immediately
if(x_var = '1') then
var_out <= '1' after 10 ns; -- this part will execute
else
var_out <= '1' after 20 ns;
end if;
end if;
end process;
end architecture;