I'm attempting to model a control unit with a reduced instruction set in VHDL. I've been compiling a lot to ensure that the code still compile, but somewhere along the line, I must have done something wrong. After fleshing out the decode states for many of the instructions, I started getting the following set of errors.
Error (10500): VHDL syntax error at controlunit.vhd(164) near text "when"; expecting "end", or "(", or an identifier ("when" is a reserved keyword), or a sequential statement
Error (10500): VHDL syntax error at controlunit.vhd(176) near text "when"; expecting "end", or "(", or an identifier ("when" is a reserved keyword), or a sequential statement
Error (10500): VHDL syntax error at controlunit.vhd(183) near text "when"; expecting "end", or "(", or an identifier ("when" is a reserved keyword), or a sequential statement
Error (10500): VHDL syntax error at controlunit.vhd(190) near text "case"; expecting "if"
Error (10500): VHDL syntax error at controlunit.vhd(195) near text "Begin"; expecting ":=", or "<="
Error (10500): VHDL syntax error at controlunit.vhd(203) near text "process"; expecting "if"
Error (10500): VHDL syntax error at controlunit.vhd(204) near text "behavior"; expecting "if"
Normally, these kinds of errors would be well within my ability to fix, but I've gone through my code multiple time, and as far as I can tell, all of the process blocks and case statements are defined correctly.
I'm afraid that, since I'm rather new to VHDL, I might be missing some syntactic subtlety that I'd never spot on my own. Can any VHDL expert help me isolate the issue in my code? Thank you!
You can find my code in the code block below.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity ControlUnit is
port(
clk: IN std_logic;
Mem_rd: OUT std_logic :='1'; --signal to read from RAM/ROM
Mem_wr: OUT std_logic :='1'; --signal to write RAM
Mem_cs: OUT std_logic :='1'; --signal to select either RAM or ROM
Z: IN std_logic; --zero signal from ALU
N: IN std_logic; --negative signal from ALU
R_we: OUT std_logic; --read/write enable signal to register file
ld_op: OUT std_logic; --bus control signal for memory load operations
st_op: OUT std_logic; --bus control signal for memory read operations
ctl_wd: OUT std_logic_vector(14 downto 0); --processor control word
const_out: OUT std_logic_vector(15 downto 0); --constant value from instruction
CU_addr_bus: INOUT std_logic_vector(15 downto 0); --processor address bus connection
CU_data_bus: INOUT std_logic_vector(15 downto 0); --processor data bus connection
run: IN std_logic; --signal allowing processor to execute its program
rst: IN std_logic --system reset signal
);
end ControlUnit;
architecture Behavior of ControlUnit is
-- Control Unit states for multi-cycle instruction execution
type states is (Reset, Fetch, Decode, Execute, WB);
signal CurrState, NextState : states;
-- Instruction set types
type ops is (nop, subx, orx, jmp, addx, andx, notx, srlx, sllx, ld, st, hlt, ret, addi, ba, bn, bz, sethi, call);
signal CurrOp, NextOp : ops;
-- Internal signal declarations
signal CurrPC, CurrSP, CurrIR, CurrDisp : std_logic_vector(15 downto 0);
signal NextPC, NextSP, NextIR, NextDisp : std_logic_vector(15 downto 0);
signal PCaEN, SPEN, PCdEN : std_logic;
signal currStatus, nextStatus : std_logic_vector(1 downto 0); --N & Z
begin
-- tri-state enables:
addr_bus <= CurrPC when PCaEN='1' else
CurrSP when SPEN='1' else
(others=>'Z');
data_bus <= CurrPC when PCdEN='1' else
(others => 'Z');
CombLogic : process(CurrState, run, CurrPC, CurrSP, CurrIR, CurrOp, data_bus)
begin
case CurrState is
when Reset => -------------------------RESET-------------------------
NextPC <= x"0080"; NextSP <= x"04FE";
NextIR <= x"0000"; NextOp <= nop;
NextStatus <= "00"; NextDisp <= x"0000";
PCaEN <= '1'; SPEN <= '0'; PCdEN <= '0'; -- setup fetch
mem_cs <= '0'; mem_rd <= '0'; mem_wr <= '1'; -- active low; setup fetch
if run = '0' then NextState <= Reset; -- active low run
else NextState <= Fetch;
end if;
when Fetch => -------------------------FETCH-------------------------
NextPC <= currPC; NextSP <= currSP;
NextIR <= data_bus; NextOp <= currOP;
PCaEN <= '1'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '0'; mem_rd <= '0'; mem_wr <= '1'; -- active low
R_we <= '0'; ctl_wd <= (others => '0'); const_out <= x"FFFF";
NextState <= Decode;
when Decode => ------------------------DECODE-------------------------
--fill in decode logic
if currIR(15) = '1' then NextOp <= call;
NextPC <= CurrPC+1; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0'; -- store CurrPC to M[SP]
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '0'; ctl_wd <= "0000"; const_out <= x"0000";
else if currIR(14) = '1' then
case currOP(10 downto 8) is
when "000" => NextOP <= hlt; --set signals for hlt
when "001" => NextOP <= ret; --set signals for ret
when "011" => NextOP <= addi; --set signals for addi
when "100" => NextOP <= ba; --set signals for ba
when "101" => NextOP <= bn; --set signals for bn
when "110" => NextOP <= bz; --set signals for bz
when "111" => NextOP <= sethi; --set signals for sethi
end case;
else
case currOP(10 downto 7) is
when "1010" => NextOP <= nop; --set signals for nop
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '0'; ctl_wd <= x"0000"; const_out <= x"0000";
when "1001" => NextOP <= subx; --set signals for subx
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "1000" => NextOP <= orx; --set signals for orx
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0111" => NextOP <= jmp; --set signals for jmp
NextPC <= CurrPCL; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '0'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0110" => NextOP <= addx; --set signals for addx
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0101" => NextOP <= andx; --set signals for andx
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0100" => NextOP <= notx; --set signals for notx
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0011" => NextOP <= srlx; --set signals for srlx
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0010" => NextOP <= sllx; --set signals for sllx
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0001" => NextOP <= ld; --set signals for ld
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '0'; mem_rd <= '0'; mem_wr <= '1';
R_we <= '1'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
when "0000" => NextOP <= st; --set signals for st
NextPC <= CurrPC; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '0'; mem_rd <= '1'; mem_wr <= '0';
R_we <= '0'; ctl_wd <= currOP(14 downto 0)&'0'; const_out <= x"0000";
end case;
end if;
NextState <= Execute;
when Execute => -------------------------EXECUTE-------------------------
case CurrOp is
when call => --call
NextPC <= CurrPC+1; NextSP <= CurrSP; NextIR <= CurrIR; nextStatus <= currStatus; nextDisp <= currDisp;
PCaEN <= '0'; SPEN <= '1'; PCdEN <= '1'; -- store CurrPC to M[SP]
mem_cs <= '0'; mem_rd <= '1'; mem_wr <= '0';
R_we <= '0'; ctl_wd <= "0000"; const_out <= x"0000";
--for bn and bz, execution of operation is dependent on signals N and Z
when others => null;
end case;
NextState <= WB;
when WB => -------------------------WB-------------------------
NextPC <= '0'&currIR(6 downto 0); NextSP <= CurrSP - 1; NextIR <= CurrIR; NextOp <= CurrOp;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0'; -- setup fetch
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1'; -- active low; setup fetch
R_we <= '0'; ctl_wd <= "0000"; const_out <= x"0000";
NextState <= Fetch;
when others => -------------------------OTHERS-------------------------
-- Should never be in this state!
NextPC <= x"00"; NextSP <= x"00"; NextIR <= x"00"; NextOp <= call;
PCaEN <= '0'; SPEN <= '0'; PCdEN <= '0';
mem_cs <= '1'; mem_rd <= '1'; mem_wr <= '1'; -- active low
R_we <= '0'; ctl_wd <= "00"; const_out <= x"FF";
NextState <= Reset;
end case;
end process;
-- Sequential Logic (asynchronous reset; registers update at positive-edge clock)
Regs : process(clk,rst)
Begin
if rst = '0' then CurrState <= Reset; -- Active Low Reset
CurrOp <= sethi; CurrPC <= x"80"; CurrSP <= x"FF"; CurrIR <= (others=>'0');
CurrStatus <= "00";
elsif (rising_edge(clk)) then CurrState <= NextState;
CurrOp <= NextOp; CurrPC <= NextPC; CurrSP <= NextSP; CurrIR <= NextIR;
CurrStatus <= NextStatus;
end if;
end process Regs;
end behavior;