In VHDL, how to check a case statement value partially meets some signal values and the rest don't matter? - vhdl

case (my_state_val & val_q) is
when ("000" & "00") => do something;
when ("001" & "00") => do something else;
when ("010" & "10") => do a 3rd thing;
when ("100" & "DONT CARE") => do a non-default thing because my_state_val is valid;
when others => default state or null;
end case;
If it was an if check, I could do: val_q /= "11" because I know my counter will never reach the top value. How can I do this in a case statement?
The reason why I want a case statement is because I don't want a 30+ depth branches.
if 1 then
elsif 2 then
...
elsif 25 then
elsif 26 then
elsif 27 then
else
end if;

I would suggest either this:
case (my_state_val & val_q) is
when ("000" & "00") => do something;
when ("001" & "00") => do something else;
when ("010" & "10") => do a 3rd thing;
when others =>
if my_state_val == "100" then
do a non-default thing because my_state_val is valid
else
default state or null;
end if;
end case;
Or this:
case (my_state_val) is
when ("000") => Evaluate val_q;
when ("001") => Evaluate val_q;
when ("010") => Evaluate val_q;
when ("100") => Evaluate val_q;
when others => default state or null;
end case;

I initially attempted this:
case (my_state_val & val_q) is
when ... => ....;
...
when ("100" & "--") => do something;
when others => null;
end case;
Simulation worked. However, my mentors are used to non-2008 VHDL and even if it was synthesize-able, it could raise questions by other engineers. So I want something that passes our coding guidelines.
I used an if-else wrapped around this case statement.
if my_state_val = "100" then
my do something here;
else
case (my_state_val & val_q) is
when ... => ....;
...
-- removed "--"
when others => null;
end case;
end if;

Related

To Add if else statement into While loop VHDL

I am trying to work on inserting if else to loop but it is still expecting some syntax. I cant figure out why this if/else statement wont compile. I am new to VHDL, please help. This is one of the steps along the way and i am stuck.
variable i : integer := 0;
begin
while i < 10 loop
report "i=" & integer'image(i);
i := i + 1;
if i = 6 then
report "okay good job";
else i = 5 then
report " okay nice work";
else
report " not equal to 5 and 6";
end loop;
wait;
end process;
end architecture;
In VHDL, the keywords are if, elsif and else
if condition_1 then
-- do something
elsif condition_2 then
-- do something else
else
-- do something when all other conditions are false
end if;

Making a single-input DeMultiplexer

I wrote a code to make a 3-1 multiplexer with 1 selector which works by selector pulses,and Here's the code i wrote below.
However, the the output assigns to the input and its chance ONLY During the if condition. How to make it always assigns to that value whenever it changes ?
library ieee;
use ieee.std_logic_1164.all;
entity selector is
port( ip,selec: in std_logic;
a,b,c: inout std_logic);
end selector;
architecture Behaviour of selector is
signal temp : std_logic;
begin
process(selec)
begin
if (selec'EVENT and selec ='1') then
if(a = ip) then
temp<= b;
elsif (b = ip) then
temp <= c;
else
temp <= a;
end if;
end if;
end process;
end if;
end Behaviour;
I'm using only ModelSim since i don't have access to hardware to test on :(
In your process you have only included selec in the sensitivity list. Therefore the assignment to temp only takes place upon event on selec.
This would be much better suited to a conditional assignment.
https://www.ics.uci.edu/~jmoorkan/vhdlref/cond_s_a.html
signal_name <= expression_1 when condition_1 else
expression_2 when condition_2 else
expression_3 ;

VHDL fsm error - near "when": (vcom-1576) expecting END

I am trying to make a fsm in vhdl using modelsim but when i try and compile my code i have this errors
** Error: C:/Users/manor/Desktop/ldh/mult_fsm.vhd(34): near "when": (vcom-1576) expecting END.
** Error: C:/Users/manor/Desktop/ldh/mult_fsm.vhd(60): near "when": (vcom-1576) expecting END.
** Error: C:/Users/manor/Desktop/ldh/mult_fsm.vhd(72): near "else": (vcom-1576) expecting END.
And this is my code
library ieee;
use ieee.std_logic_1164.all;
entity mult_fsm is
port(ck,adx,m: in std_logic;
adsh,sh,cm,mdone: out std_logic);
end entity mult_fsm;
architecture ideal of mult_fsm is
type StateType is (S0, S1, S2, S3, S4);
signal CurrentState, NextState: StateType;
begin
NS_CS: process( ck)
begin
if ck'event and ck='1' then
case CurrentState is
when S0=>
if (adx='0') then
NextState <= S0;
else
NextState <= S1;
end if;
when S1=>
NextState <= S2;
when S2=>
if (m='1') then
NextState<=S3;
else if (m='0') then
NextState<=S2;
end if;
when S3=>
NextState <= S4;
when S4=>
NextState <= S0;
end case;
end if;
end process NS_CS;
OL: process (CurrentState)
begin
case CurrentState is
when S0=>
if (adx = '0') then
adsh<='0';
sh<='0';
cm<='0';
mdone<='0';
else if (adx = '1') then
if (m='1') then
adsh<='1';
else if (m='0') then
sh<='1';
end if;
end if;
when S1=>
if (m='1') then
adsh<='1';
else if (m='0') then
sh<='1';
end if;
when S2=>
if (m='0') then
adsh<='0';
sh<='0';
cm<='0';
mdone<='0';
else if (m='1') then
adsh<='1';
end if;
when S3=>
if (m='0') then
sh='1';
else if (m='1') then
cm<='1';
adsh<='1';
end if;
when S4=>
mdone<='1';
end case;
end process OL;
end architecture ideal;
I tried fixing the code myself but i just can't figure out what is the problem with it.
Replace your else ifs with elsifs.
In VHDL, each if needs an end if. If you write
if ... then
...
else if ... then
you need two end ifs - one for each if:
if ... then
...
else IF ... THEN
...
END IF;
end if;
VHDL has an elsif statement. That does not start a new if statement, but instead is part of the if statement it follows. If you replace else IF in the above example, you only need one end if:
if ... then
...
elsif ... then
...
end if;
Looking at the following code:
if (m='1') then
NextState<=S3;
else if (m='0') then
NextState<=S2;
end if;
I think you meant elsif instead of else if. Alternatively, since m is an std_logic, you may be able to simplify this block down to:
if (m='1') then
NextState<=S3;
else
NextState<=S2;
end if;

Ruby interpreter ignors conditions of elsif statements

I wroe this method in a class :
def OpCodes
if #asm[0] == "ADD"
opcode = "111"
elsif #asm[0] == "CMP"
opcode = "110"
elsif #asm[0] == "SHL"
opcode = "101"
elsif #asm[1] == "SHR"
opcode = "100"
elsif #asm[1] == "NOT"
opcode = "011"
elsif #asm[1] == "XOR"
opcode = "010"
elsif #asm[1] == "OR"
opcode = "001"
elsif #asm[1] == "AND"
opcode = "000"
else
opcode = "ERROR"
end
#opcode = opcode
return #opcode
end
And when I run the code, and for example I give it "ADD 1, 3" string, it works and returns "111". But, when I use other commands, it returns "ERROR"
You could rewrite this to use a simple lookup table:
OPCODES = {
ADD: 0b111,
CMP: 0b110,
SHL: 0b101,
SHR: 0b100,
NOT: 0b011,
XOR: 0b010,
OR: 0b001,
AND: 0b000
}.freeze
OPCODE_ERROR = "ERROR".freeze
def opcode(instruction)
OPCODES[instruction.to_sym] or OPCODE_ERROR
end
Note it's much better to use native binary numbers than string representations of same, so I'm using the 0bNNN notation here. 0b001 is 1, 0b010 is 2. You can convert back to a string if you want using n.to_s(2) for base-2.
Additionally you should never name methods CamelCase style, those are reserved for class and module names. Instead use underscore_style.
It looks like you're not parsing your input properly. Try with a regular expression:
instruction, a, b = input.scan(/\A(\S+)\s+(\S+),\s*(\S+)/)[0]
For something like "ADD 1,2" you will get those values broken out into three variables you can use.

change signal inside a process with if statement - VHDL

I have this code in VHDL. What I want is to rise rst when sw'event and afterwards, the rst is to fall by itself. But when I simulate this, rst never falls!
process(rst,clk,sw)
begin
if (clk'EVENT and clk='1') then
if (rst='1') then
rst<='0';
elsif (sw'event) then
rst<='1';
elsif (my_counter="11") then
deb_sw<=sw;
end if;
end if;
end process;
sw'event is very unlikely to be true at exactly the same time as clk'event is.
This is because signals are usually driven by another process which is also doing a clk'event, so the signal will be updated after the clk event.
If you want to detect when sw changes from '0' to '1' (or vice versa), you have to keep track of its previous value:
if sw /= last_sw then
-- do what you need to do when it changes
end if;
last_sw := sw;
finally i solved it like this
process(rst,clk,sw)
begin
if (clk'EVENT and clk='1') then
if (rst='1' and rst'last_value='0') then
rst<='0';
elsif (sw='1') then
rst<='1';
deb_sw<=sw;
elsif (my_counter="1010") then -- clock cycles=10*f
deb_sw<=sw;
end if;
end if;
end process;

Resources