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.
Related
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));
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:
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!
I don't really have any advanced sql knowledge on how to phrase if/then statements in sql (whether to use case, for example) and/or formatting variables in the same query so I was wondering if someone could help with this sas code and phrasing it in the correct format into sql:
data convert_code;
format date1 date 2 mmddyy8. code $4.;
set userid.code; (this table is pulled from oracle)
if ID='X' then P='A'; else P='B';
If CAT in ('1','2','3') then CAT_group='ONE'; else CAT_GROUP='TWO';
if CAT_2 > '0' and CAT_2A >='1' then d=1; else d=0;
date1=datepart(date1);
date2=datepart(date2);
if code='3' and type_code in ('A','B','C') THEN DO;
if P_CODE in ('1','2','3') then P='1';
if P_CODE in ('4','5','6') then P='2';
end;
if code='4' and e_code in ('A') then DO;
if B_CODE in ('11','12','13') then P='3';
if B_CODE in ('14','15','16') then P='4';
end;
run;
The example given here uses SAS' proc sql language. If you are using a different SQL implementation then the syntax may be different. However, the case expression examples should be fairly easy to adapt to any SQL implementation as it is part of the SQL standard.
proc sql;
/* Name your output table */
create table convert_code as
select
/*
Unlike the data step variables from the input data are not
selected by default, you can request them individually or
with "select *"
*/
/* Use "format =" after the column definition to set its format */
code format = $4.,
/* Use SAS functions as normal, name the output variable with "as" */
datepart(date1) as date1 format = mmddyy8.,
/* Comma separate each variable you want in your output */
datepart(date2) as date2 format = mmddyy8.,
/* A "case" expression can conditionally set a variable to a value */
case
when CAT in ('1', '2', '3') then 'ONE'
else 'TWO'
/* Close the "case" statement with "end" */
end as CAT_group,
/* You can nest case statements to emulate your "then do" */
case
when code = '3' and e_code in ('A', 'B', 'C') then
case
/* Use multiple "when then"s to emulate "else if" */
when P_CODE in ('1', '2', '3') then '1'
when P_CODE in ('4', '5', '6') then '2'
else ''
end
when code = '4' and e_code in ('A') then
case
when P_CODE in ('11', '12', '13') then '3'
when P_CODE in ('14', '15', '16') then '4'
else ''
end
when ID = 'X' then 'A'
else 'B'
end as P,
/* An alternative to case is to use the "ifn()" or "ifc()" functions */
ifn(CAT_2 > 0 and CAT_2A >= 1, 1, 2) as d
/* Choose the input data and end the query with a ";" */
from userid.code;
/*
Additional processing can be done here, some examples include:
"where": limit the input
"left join", "right join", "inner join", "outer join", ",":
combine with additional data sets
"group by": group based on column values for summary functions
"order by": specify which columns to sort the output by
*/
/* End the "proc sql" processing */
quit;
Using case expressions rather than the the SAS specific ifn() and ifc() functions would be my suggestion, as they are the standard SQL method for conditionally assigning values and will (probably) be the same in other SQL implementations. Be aware that format = and the datepart() function are SAS specific.
A brief exploration of proc sql from a data step perspective can be found here
The case expression here
The ifn() and ifc() functions here
The format = column modifier here
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;