I would make this code into a more conventional Finite State Machine using the 'case' statement with specific states rather than a priority tree configuration.
Every output signal (those that appear on the left hand side of <=) in your tree must be defined in
every path, you can't leave the signals as some kind of assumption. If the signals are not defined in every path, latches will be inferred and you should get some kind of warning. I'm not sure that every signal you are dealing with is actually defined in every 'elseif'. If you have an if-elseif-else structure, you need the signal defined (one way or another) in all 3 places.
Look at page 105 (PDF page 117) here:
http://freerangefactory.org/pdf/df344hdh4h8kjfh3500ft2/free_range_vhdl.pdfNotice how signals Z1 and Z2 are defined default values such that they don't need to be defined in each and every state. These default values are redefined in specific states and the last assignment in the code loop prevails. The point is: make certain that every single signal is defined under all possible conditions. Otherwise, your logic will fail spectacularly.
BTW, this code is a little pedantic because Z1 and Z2 are defined in every case and under every condition even without the default assignment. That's fine when the FSM only has a few outputs but if you get into something with 50 or 60 outputs, you really don't want to have to define them under all conditions, one line each, in a FSM with 100 states.
If you develop code with a 'stepwise refinement' approach, it is pretty easy to add a new signal to an FSM and forget to include a default value. When I do this, nothing works and I get a warning about inferring a latch. I have made that mistake more than once...
You will notice that the code is also a two-process variant. One process is synchronous and deals with next state (PS <= NS) and the other is combinatorial and does all of the real work. There are also one-process and three-process configurations.
https://vhdlwhiz.com/n-process-state-machine/I use only the two-process configuration...
Here's a small sample of a two-process FSM. Note the number of default assignments:
-- FSM Next State
process(reset,Pulse,NextState)
begin
if rising_edge(pulse) then
if reset = '1' then
State <= 18;
else
State <= NextState;
end if;
end if;
end process;
-- FSM
process(State, BEN, IR,MemReady, Immediate, PSR, Interrupt)
begin
-- set default values for all signals
GateBusSelect <= GatePC;
MIOenable <= '0';
LD_MAR <= '0';
LD_MDR <= '0';
LD_IR <= '0';
LD_BEN <= '0';
LD_PC <= '0';
LD_Reg <= '0';
LD_CC <= '0';
LD_Privilege <= '0';
LD_Priority <= '0';
LD_PSR <= '0';
LD_SavedUSP <= '0';
LD_SavedSSP <= '0';
LD_VectorAddr <= '0';
PCselect <= PCplus1;
MARSelect <= MARzext;
Addr1Select <= Addr1PC;
Addr2Select <= Addr2Zero;
SR2select <= SR2OutSel;
SR1addrSelect <= SR1usesSR1;
ALUop <= ALUpassA;
DRaddrSelect <= DRusesDR;
MemWr <= '0';
SPselect <= SPminusOnesel;
VectorMux <= "00";
Privilege <= '0';
case State is
when 0 => -- Branch Instruction
if BEN = '1' then
NextState <= 22; -- branch is taken
else
NextState <= 18; -- branch not taken
end if;
when 1 => -- ADD Instruction
if Immediate = '1' then
SR2select <= Sext5sel;
else
SR2select <= SR2outSel;
end if;
ALUop <= ALUadd;
GateBusSelect <= GateALU;
LD_Reg <= '1';
LD_CC <= '1';
NextState <= 18;
when 2 => -- LD Instruction
Addr1Select <= Addr1PC;
Addr2Select <= Addr2Sext9;
MARselect <= MARadder;
GateBusSelect <= GateMARmux;
LD_MAR <= '1';
NextState <= 25;
...and so on...
[/font]
There are about 27 default assignments that I don't have to rewrite under every condition.