Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VHDL STD_LOGIC_VECTOR Wildcard Values

I've been trying to write a Finite State Machine in VHDL code for a simple 16-bit processor I'm implementing on an Altera DE1 board. In the Finite State Machine, I have a CASE statement that handles the different 16-bit instructions, which are brought into the FSM by a 16-bit STD_LOGIC_VECTOR. However, I'm having a little trouble in the decode state where the Finite State Machine decodes the instruction. One of the instructions is an ADD which takes two registers as operands and a third as the destination register. However, I also have an ADD instruction which takes a register and a 5-bit immediate value as operands and a second register for the destination. My problem is that in the CASE statement, I need to be able to differentiate between the two different ADD instructions. So, I thought that if I use wildcard values like "-" or "X" in the CASE statement, I would be able to differentiate between the two with just two cases instead of listing all of the possible register/immediate value combinations. For example:

    CASE IR IS --(IR stands for "Instruction Register")
      WHEN "0001------0-----" => (Go to 3-register add);
      WHEN "0001------1-----" => (Go to 2-register/immediate value add);
      WHEN OTHERS => (Do whatever);
    END CASE;

These aren't the only two instructions I have, I just put these two to make this post a little shorter. When I compile and run this code, the processor stops executing when it gets to the "decode" state. Also, Quartus gives many, many warnings saying things like "VHDL choice warning at LC3FSM.vhd(37): ignored choice containing meta-value ""0001------0-----""" I am at a loss as to how to go about accomplishing this. I REALLY do not and probably don't need to define every single 16-bit combination, and I hope there's a way to use wildcards in a STD_LOGIC_VECTOR to minimize the number of combinations I will have to define.

Does anybody know how to accomplish this?

Thanks

like image 761
Eric Townsend Avatar asked Feb 09 '12 05:02

Eric Townsend


2 Answers

That can't be done unfortunately. Rather unexpectedly for most users, the comparison operator = and the case comparison perform a literal comparison. This is because the std_logic type is just a set of characters, which happen to perform like logic values due to the way other functions (eg and and or) are defined.

VHDL-2008 introduces a new case statement case? which performs as you expect - you'll need to tell your compiler to operate in VHDL 2008 mode. In addition, there is a ?= operator in VHDL 2008 which compares two values, taking account of -s.

If you are lumbered with a compiler which still doesn't support VHDL 2008, complain to the supplier. There is also a std_match function allows you to perform comparisons in older VHDL revisions, but nothing that I am aware to make the case statement work that way.

like image 84
Martin Thompson Avatar answered Nov 11 '22 06:11

Martin Thompson


Assuming you don't need the other bits in the instruction you could hack your way around this by masking the other bits with a pre-check process. (Or just ensure the other bits are reset when you write the instruction?)

This really is a bit of a hack.

assuming IR is stored as a variable

if IR(15 downto 12) == "0001" then
    IR := IR_in(15 downto 12) & "0000000" & IR_in(5) & "00000";
else
    IR := IR_in
end if;

CASE IR IS --(IR stands for "Instruction Register")
  WHEN "0001000000000000" => (Go to 3-register add);
  WHEN "0001000000100000" => (Go to 2-register/immediate value add);
  WHEN OTHERS => (Do whatever);
END CASE;

Alternatively assuming your instruction is cleverly thought out (are the first four bits the command word or something along those lines?) you could do nested case statements and do the differentiation as needed in those sub blocks.

like image 1
Paul Seeb Avatar answered Nov 11 '22 08:11

Paul Seeb