Declaring multiple cases with the same function? - function

I am a beginner to VHDL, started coding for a class I am in. I am working on a digital-alarm-bike lock, I am trying to find an efficient way to call this code, but I am currently getting a syntax error.
PROCESS (Clk, H)
BEGIN
CASE current_state IS
WHEN s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s63=>
IF H = "0" THEN
current_state <= s0;
END If;
WHEN s12,s13,s14,s15,s16,s17,s18,s19,s20,s21,s22,s23,s24,s25,s26,s27,s28,s29,s30,s31,s32,s33,s34,s35,s36,s37,s38,s39,s40,s41,s42,s43,s44,s45,s46,s47,s48,s49,s50,s51,s52,s53,s54,s55,s56,s57,s58,s59,s60,s61,s62=>
IF H = "0" THEN
current_state <= s52;
Elsif (rising_edge(Clk) THEN
current_state <= next_state;
END IF;
END CASE
END PROCESS;
Basically, those are state types, and I want to basically call all those states, and check them for the value of H, and certain condition will be called. However, I am getting this error:
ERROR:HDLParsers:164 - "(Directory///)" Line 50. parse error, unexpected COMMA, expecting PIPE or ROW
I can't use a comma, but does any experienced VHDL code know how to work around this so we do not have to explicitly repeat the code for each s-state?

If you'd looked a little harder, you could have found
WHEN s0 to s11|s63 =>
...
WHEN s12 to s62 =>
...

I found the solution for my own question hahaha.
There is a "pipe" symbol that allows for this operation.
PROCESS (Clk, H)
BEGIN
CASE current_state IS
WHEN s0|s1|s2|s3|s4|s5|s6|s7|s8|s9|s10|s11|s63=>
IF H = '0' THEN
current_state <= s0;
END If;
WHEN s12|s13|s14|s15|s16|s17|s18|s19|s20|s21|s22|s23|s24|s25|s26|s27|s28|s29|s30|s31|s32|s33|s34|s35|s36|s37|s38|s39|s40|s41|s42|s43|s44|s45|s46|s47|s48|s49|s50|s51|s52|s53|s54|s55|s56|s57|s58|s59|s60|s61|s62=>
IF H = '0' THEN
current_state <= s52;
Elsif (rising_edge(Clk)) THEN
current_state <= next_state;
END IF;
END CASE;
END PROCESS;

Related

Why mysql workbench 8.0 is throwing error for not closing if's, though all "if's" are closed properly?

Though my procedure code has proper "if"s (that is "if"s that are opened and closed properly), mysql workbench 8.0 is throwing an error that all "if"s are not closed properly. I can't find any other mistake too. Please help me out.
If I am adding extra "if"s in the end, the errors are gone. But it is not correct since those "end if"s do not have any if so that they can be closed.Though it is not showing any error, while applying the procedure with the additional "end if"s, it is not getting applied instead throws some other error.
IF(Ser ='search') THEN
IF(Value = 0) THEN
IF EXISTS(SELECT Role FROM U WHERE Name = name) THEN
IF(O = 0) THEN
IF(F1 <> NULL AND F1V <> NULL AND
F2 = NULL AND F2V = NULL
) THEN
IF EXISTS (SELECT * FROM Com ) THEN
SET V=0;
END IF;
ELSE IF (F1<> NULL AND F1V <> NULL AND
F2 <> NULL AND F2V <> NULL
) THEN
IF EXISTS ( SELECT * FROM Com ) THEN
SET V=1;
END IF;
END IF;
ELSE IF(O = 1) THEN
SET A=0;
END IF;
END IF;
END IF;
END IF;
I changed the else if condition to if and it started working.

MYSQL trigger with if statements

I can't seem to make this trigger work.
CREATE TRIGGER class_check BEFORE INSERT ON Category
DECLARE x VARCHAR(1);
SET x = (SELECT Type1 FROM Category);
IF (x<>'A') THEN
CALL `'ERROR'`;
END IF;
IF (NEW.MxLen > 3 AND x ='M') THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 3 FOR M CLASS LICENSE'`;
ELSEIF (NEW.MxLen > 5 AND x ='G') THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 5 FOR G CLASS LICENSE'`;
ELSEIF (NEW.MxLen > 30) THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 30 FOR A,B,C,D,E CLASS LICENSE'`;
END IF;
The trigger above doesn't work the way i want it to and I can't seem to find the problem.
Basically, I want it to check if the type1 in the Category table is Not A then shoot an error. Everytime I try to add A, it will still shoot the error.
Any help would be appreciated. I have the same for BEFORE UPDATE as well.
The backticks are escaping the name of whatever is between them, saying that it is an identifier. I doubt that you actually have any identifiers with these names. Just use the single quotes for the strings:
Normally, call would have stored procedure name after it. I am guessing that you really want signal to raise an error:
CREATE TRIGGER class_check BEFORE INSERT ON Category
DECLARE x VARCHAR(1);
SET x = (SELECT Type1 FROM Category);
IF (x <> 'A') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR';
END IF;
IF (NEW.MxLen > 3 AND x ='M') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 3 FOR M CLASS LICENSE';
ELSEIF (NEW.MxLen > 5 AND x ='G') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 5 FOR G CLASS LICENSE';
ELSEIF (NEW.MxLen > 30) THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 30 FOR A,B,C,D,E CLASS LICENSE';
END IF;
Also, it is not clear what this line does:
SET x = (SELECT Type1 FROM Category);
It is likely to return an error if more than one row is in Category.

VHDL internal signal to change output - not working?

I have this PC module, very simple (Code at the end). I first generate some input signal port_int and at the end of the process say pc_out <= port_int. My goal is to either increment or add or subtract from PC, depending on input signals.
In the simulation, the internal port_int signal works fine, but pc_out doesn't. Why is this happening? Look at the simulation:
Look how port_int changes as it should, while pc_out is late. Later in the simulation, pc_out gets even worse, changing irregularly, not even just being late.
What am I doing wrong? Is there another way to change pc_out? Bcoz you can't change out signals, and I've been told that inout is extremely bad practice..
Here's the code:
entity PC is
Port ( clk : in STD_LOGIC;
enable : in STD_LOGIC;
reset : in STD_LOGIC;
pc_out : out STD_LOGIC_VECTOR (3 downto 0);
data : in STD_LOGIC_VECTOR (3 downto 0); -- jump value
zero : in STD_LOGIC; -- jump condition
jmp_en : in STD_LOGIC; -- jump enable
jmp_dir : in STD_LOGIC; -- jump direction
ctrl_en : out STD_LOGIC); -- output signal
end PC;
architecture Behavioral of PC is
type state_type is (s0, s1, s2, s3);
signal reg_state, next_state : state_type;
signal port_int : std_logic_vector(3 downto 0);
begin
state_transition: process(clk, reset)
begin
if (reset = '1') then
reg_state <= s0;
elsif(rising_edge(clk)) then
reg_state <= next_state;
end if;
end process;
next_state_logic: process(reg_state, enable)
begin
case reg_state is
when s0 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s1 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s2 =>
next_state <= s3;
when s3 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
end case;
end process;
output_logic: process(reg_state, zero, jmp_en, jmp_dir, data)
begin
case reg_state is
when s0 =>
pc_out <= "0000";
port_int <= "0000";
ctrl_en <= '0';
when s1 =>
ctrl_en <= '0';
when s2 =>
if(zero = '1' and jmp_en = '1' and jmp_dir = '1')then
port_int <= port_int + data; -- jump forward
elsif(zero = '1' and jmp_en = '1' and jmp_dir = '0')then
port_int <= port_int - data; -- jump backward
else -- nije ispunjen uslov skoka
port_int <= port_int + '1'; -- increment PC
end if;
pc_out <= port_int;
when s3 =>
ctrl_en <= '1';
end case;
end process;
end Behavioral;
EDIT:
When I import the module in a whole processor, this happens:
the same pc_out signal acts strangely, adn all the inputs are the same. I use the pc_out signal just in one place, to select memory.
Why isn't it behaving normally? What could have caused this?
The second process (output_logic: process), which computes the output values, has some problems.
First, recall that it implements a combinational circuit (therefore, memoryless), so equations like port_int <= port_int + data can only be computed if the value of port_int is stored somewhere. By the way, after fixing the code, you can drop the internal signal port_int and use pc_out directly.
Second, being this process a combinational circuit, its full truth table must be specified; otherwise, latches will be inferred. Note, for example, that only the value of ctrl_en is specified in state s1. You must either specify all output values (same list) in all states or, equivalently, you can make a list of output values before the case statements, so the compiler will use them as default values when the values are not explicitly declared.
If I understand what you're trying to do correctly, you just need a single statement outside the process blocks:
pc_out <= port_int;
Take all other statements assigning something to pc_out out of your design. I think you're getting tripped up by the <= operator, which waits until the next simulation delta to actually update the signal driver.

Using 2 cursors, one to get a parameter for the other

I am doing an exercies that requires me to use 2 explicit cursors. One cursor is to get a parameter for the second. The end goal is to find the most recent 'rental date' for each car based on registration. For example, registration 345JKL was rented on the 01/06/2010, 07/09/2011 and 08/09/2013. I want this to only return the most recent date which is 08/09/2013 and I want it to provide a most recent date for every registration in the table.
I am aware that there are better ways to do this such as MAX, subqueries etc (both of which I am not allowed to use), but as a 'lateral thinking exercise' I am required to do it without inbuilt functions, subqueries and the rest of the things that make life easy.
I am a little stuck with this one.
This is what I have so far which is getting me nowhere:
declare
v_maxdate DATE;
v_reg VARCHAR2(20);
cursor reg_cur IS
SELECT * FROM i_car;
v_car reg_cur%ROWTYPE;
cursor c_reg (reg i_booking.registration%TYPE) IS
SELECT date_reserved from i_booking
WHERE registration = reg;
v_date c_reg%ROWTYPE;
begin
FOR v_date IN c_reg (v_car.registration) LOOP
v_maxdate := '01/JAN/90';
If v_date > v_maxdate THEN
v_maxdate := v_date;
end if;
end loop;
end;
It is throwing me this error:
If v_date > v_maxdate THEN
*
ERROR at line 17:
ORA-06550: line 17, column 11:
PLS-00306: wrong number or types of arguments in call to '>'
ORA-06550: line 17, column 1:
PL/SQL: Statement ignored
I figured rather than continuing to bang my head on the desk I would ask for guidance.
Your help is appreciated.
The v_date variable is a record, so you have to use the dot to actually access some of its fields - date_reserved in your case:
begin
v_maxdate := '01/JAN/90';
FOR v_date IN c_reg (v_car.registration) LOOP
If v_date.date_reserved > v_maxdate THEN
v_maxdate := v_date;
end if;
end loop;
end;
I have also moved initialization of v_maxdate outside of the loop.

How much statement can be made conditional in MySQL?

the MySQL manual says that a CASE statement (the WHEN part) can contain a statement_list.
How much statement is that to be exact? I need to perform a pretty big query which I would like to parametrize. However this also implies that I need to change tables that are being joined. I've read that this cannot be done using CASE statements, so I'm looking for a solution to not have to re-create the stored procedure for every parameter value that there is...
UPDATE
I tried to solve it using a CURSOR. I have defined a CURSOR for every object I have. I would like to use IF-ELSE-statements to choose which cursor to open, loop and close. However I cannot get the syntax right...
All cursors and variables (usb, obj, mm, stamp) are declared with different names, but I've shortened them for reading....
if OBJECTTYPE = 1 then
open CUR_1_BUILDING;
LOOP1: loop
fetch CUR_1_BUILDING into usb, obj, mm, stamp;
if no_more_rows then
close CUR_1_BUILDING;
leave loop1;
end if;
INSERT INTO ObjectCache (usb, obj, mm, date_checked) VALUES (usb, obj, mm, now());
end loop LOOP1;
CLOSE CUR_1_BUILDING;
else if OBJECTTYPE = 2 then
open CUR_2_CITY;
LOOP2: loop
fetch CUR_2_CITY into usb, obj, mm, stamp;
if no_more_rows then
close CUR_2_CITY;
leave loop2;
end if;
INSERT INTO ObjectCache (usb, obj, mm, date_checked) VALUES (usb, obj, mm, now());
end loop LOOP2;
close CUR_2_CITY;
end if;
Is this is any way possible to do using CASE statements?
BEGIN
CASE
when OBJECTTYPE = 1
INSERT INTO ObjectCache SELECT id FROM Building
when OBJECTTYPE = 2
INSERT INTO ObjectCache SELECT id FROM City
END CASE;
END
You could use IF ELSE or you could build and execute dynamic SQL.