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;
-- 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;
For example CurrOp is an enumerated type with values shown as ops enumerations. Yet you have slices of CurrOp:
case currOP(10 downto 8) is
case currOP(10 downto 7) is
And your when expressions for the case statements are string literals respectively with a length of 3 or 4.
So CurrOp isn't an array type you can't slice it and compare it to strings.
Now why analysis get's this far is without telling you this is entertaining. The expression is being evaluated at elaboration time and not analysis time unlike say the target of a signal assignment:
library ieee;
use ieee.std_logic_1164.all;
entity foo is
end entity;
architecture fum of foo is
-- 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;
begin
CurrOp(10 downto 7) <= "1001";
NextOp(10 downto 8) <= "011";
end architecture;
ghdl -a foo.vhdl
foo.vhdl:13:11: type of prefix is not an array
foo.vhdl:14:11: type of prefix is not an array
ghdl: compilation error
(-a is the ghdl analysis command)
Effectively a choice can only be an ops enumeration value. To make it more palatable you're allowed choices:
choices ::= choice { | choice }
You can also assign the default for all the signals you are guaranteed to assign in a choice right before a case statement then assign only those with different values in each case statement alternative. In the same simulation delta only the last assignment will be scheduled (there's only one future event).
Along with a plethora of errors, the major thing stopping the further analysis was an else if where and `else was appropriate.
A found lots or errors while trouble shooting, you'd want to compare these for the same syntactical position in your file:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
-- use IEEE.STD_LOGIC_UNSIGNED.all;
use ieee.numeric_std.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:
CU_addr_bus <= CurrPC when PCaEN='1' else
CurrSP when SPEN='1' else
(others=>'Z');
CU_data_bus <= CurrPC when PCdEN='1' else
(others => 'Z');
CombLogic : process(CurrState, run, CurrPC, CurrSP, CurrIR, CurrOp, CU_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 <= CU_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 <= std_logic_vector (unsigned(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 <= (others => '0');
const_out <= x"0000";
elsif currIR(14) = '1' then
case currIR(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
when others => NextOp <= nop;
end case;
else
case currIR(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 <= (others => '0');
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 <= currIR(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 <= currIR(14 downto 0) & '0';
const_out <= x"0000";
when "0111" =>
NextOP <= jmp; --set signals for jmp
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 <= currIR(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 <= currIR(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 <= currIR(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 <= currIR(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 <= currIR(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 <= currIR(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 <= currIR(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 <= currIR(14 downto 0) & '0';
const_out <= x"0000";
when others =>
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 <= (others => '0');
const_out <= x"0000";
end case;
end if;
NextState <= Execute;
when Execute => -------------------------EXECUTE-------------------------
case CurrOp is
when call => --call
NextPC <= std_logic_vector( unsigned (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 <= (others => '0');
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 <= std_logic_vector(unsigned(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 <= (others => '0'); -- "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"0080";
CurrSP <= x"FFFE";
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;
Related
I am new to VHDL and i am trying to implement CMOS CD4543 into FPGA basys 3 ,
and i am stuck because i wrote 2 modules and the output remains U and this output is supposed to be input in the second module. I've made testbenches for both of them and separatly they are working corect. I will put the code here to see what is wrong. Thanks!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity latch is
Port ( datain : in STD_LOGIC_VECTOR (3 downto 0);
load : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(3 downto 0));
end latch;
architecture Behavioral of latch is
signal data : std_logic_vector (3 downto 0);
Begin
data <= datain when (load = '1') else data;
data_out <= data;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity to7segments is
Port ( datain : in STD_LOGIC_VECTOR (3 downto 0);
bl :in std_logic;
ph :in std_logic;
seg : out STD_LOGIC_VECTOR (6 downto 0);
an : out STD_LOGIC_VECTOR (3 downto 0));
end to7segments;
architecture behavioral of to7segments is
signal data: std_logic_vector(3 downto 0);
Begin
an<="1110";
decoder: process(bl,ph)
begin
if bl= '0' then
if ph ='1' then
data <= not(datain);
end if;
data<=datain;
case data is
when "0000" => seg <="0000001" ;
when "0001" => seg <= "1001111" ;
when "0010" => seg <= "0010010" ;
when "0011" => seg <= "0000110" ;
when "0100" => seg <= "1001100" ;
when "0101" => seg <= "0100100" ;
when "0110" => seg <= "0100000" ;
when "0111" => seg <= "0001111" ;
when "1000" => seg <= "0000000" ;
when "1001" => seg <= "0000100" ;
when "1010" => seg <= "0001000" ;
when "1011" => seg <= "1100000" ;
when "1100" => seg <= "0110001" ;
when "1101" => seg <= "1000010" ;
when "1110" => seg <= "0110000" ;
when "1111" => seg <= "0111000" ;
when others => seg <= "1111111" ;
end case;
elsif bl='1' then
seg<="1111111";
end if;
end process decoder;
end behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity top is
Port ( load : in STD_LOGIC;
ph : in STD_LOGIC;
bl : in STD_LOGIC;
datain :in std_logic_vector( 3 downto 0);
seg : out STD_LOGIC_VECTOR (6 downto 0);
an : out STD_LOGIC_VECTOR (3 downto 0));
end top;
architecture behavioral of top is
component latch PORT ( datain : in STD_LOGIC_VECTOR (3 downto 0);
load : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR(3 downto 0));
end component;
component to7segments PORT ( datain : inout STD_LOGIC_VECTOR (3 downto 0);
bl :in std_logic;
ph :in std_logic;
seg : out STD_LOGIC_VECTOR (6 downto 0);
an : out STD_LOGIC_VECTOR (3 downto 0));
end component;
signal datain2 : std_logic_vector(3 downto 0);
begin
latch1: latch PORT MAP(datain=>datain,
load =>load,
data_out=>datain2);
decoder: to7segments PORT MAP(datain=>datain2,
bl=>bl,
ph=>ph,
seg=>seg,
an=>an);
end behavioral;
I have the following code. Here I am trying to bubble sort the values of an array acoording to their index .
After bubblesorting in first set of for loops , i am using second set of for loops to get the original indeces of the values which are bubble sorted in an array.
library ieee;
use ieee.std_logic_1164.all;
package array_type is
constant len: integer := 4;
type sorted is array (0 to 15) of std_logic_vector(len-1 downto 0);
end package;
library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;
entity sort is
port (
clk: in std_logic;
bit_array: in sorted;
sorted_array: out sorted
);
end entity;
architecture behaviour of sort is
use ieee.numeric_std.all;
begin
BSORT:
process (clk)
variable temp: std_logic_vector (len-1 downto 0);
variable var_array: sorted;
variable temp_array: sorted;
begin
var_array := bit_array;
if rising_edge(clk) then
for j in sorted'LEFT to sorted'RIGHT - 1 loop
for i in sorted'LEFT to sorted'RIGHT - 1 - j loop
if unsigned(var_array(i)) < unsigned(var_array(i + 1)) then
temp := var_array(i);
var_array(i) := var_array(i + 1);
var_array(i + 1) := temp;
end if;
end loop;
end loop;
for i in sorted'LEFT to sorted'RIGHT loop
j_loop:for j in sorted'LEFT to sorted'RIGHT loop
if ( (var_array(i)) = (bit_array(j)) ) then
if not( (temp_array(0)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(1)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(2)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(3)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(4)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(5)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(6)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(7)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(8)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(9)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(10)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(11)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(12)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(13)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(14)= std_logic_vector(to_unsigned(j, len))) or
(temp_array(15)= std_logic_vector(to_unsigned(j, len))) ) then
temp_array(i) := std_logic_vector(to_unsigned(j, len)); --conv_std_logic_vector(j,4);
exit j_loop;
end if;
end if;
end loop;
end loop;
sorted_array <= temp_array;
end if;
end process;
end architecture behaviour;
and the test bench is as below:
library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;
entity sort_tb is
end entity;
architecture behav of sort_tb is
use work.array_type.all;
signal clk: std_logic := '0';
signal bit_array: sorted;
signal sorted_array: sorted ;
-- Clock period definitions
constant clk_period : time := 10 ns;
begin
DUT:
entity work.sort(behaviour)
port map (clk => clk,
bit_array => bit_array,
sorted_array => sorted_array
);
-- Clock process definitions( clock with 50% duty cycle is generated here.
clk_process :process
begin
clk <= '1';
wait for clk_period/2; --for 5 ns signal is '1'.
clk <= '0';
wait for clk_period/2; --for next 5 ns signal is '0'.
end process;
process
begin
bit_array <= (x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0") ;
wait for 10 ns;
bit_array <= (x"0", x"0", x"0", x"4", x"0", x"0", x"0", x"3", x"2", x"2", x"0", x"0", x"0", x"5", x"0", x"0") ;
wait for 10 ns;
bit_array <= (x"0", x"0", x"9", x"4", x"0", x"4", x"0", x"3", x"2", x"2", x"0", x"8", x"0", x"5", x"0", x"0") ;
wait;
end process;
end architecture;
Here the problem is , the output sorted_array is not getting evaluated and updated every clock cycle as input bit_array changes. bit_array changes every clk cycle and clk is in sensitivity list of process, so sorted_array should get new values after evaluation each clk.
There are 2 for loops in the process. If i remove 2nd for loop and assign var_array to sorted_array(output), then sorted_array is evaluated according to new bit_array data and is updated every clock cycle which is correct. But the same is not happening if i include both the for loops.
I am new to VHDL , Need suggestion on this.
... i am using second set of for loops to get the original indeces of the values which are bubble sorted in an array.
(Please update your question to reflect this).
Now that you're comment has clarified the purpose of the second set of loops the functionality can be introduce by another method.
Your contents addressable method with the second two loops is missing access to the original index of bit_array in the var_array.
The easiest way to to do this create a new array type that carries the original index along with the context of an array element using a record element type. (The idea shows up in CAM memory, the index is part of the data):
library ieee;
use ieee.std_logic_1164.all;
package array_type is
constant len: natural := 4;
constant indx_size: natural := len;
type sorted is array (0 to 15) of std_logic_vector (len - 1 downto 0);
type cam is record
contents: std_logic_vector (len - 1 downto 0);
index: std_logic_vector (indx_size - 1 downto 0);
end record;
type rsorted is array (0 to 15) of cam;
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.array_type.all;
entity sort is
port (
clk: in std_logic;
bit_array: in sorted;
sorted_array: out sorted
);
end entity;
architecture behaviour of sort is
begin
BSORT:
process (clk)
variable temp: cam;
variable var_array: rsorted;
variable temp_array: rsorted;
begin
-- var_array := bit_array;
for i in bit_array'range loop
var_array(i).contents := bit_array(i);
var_array(i).index := std_logic_vector(to_unsigned(i,indx_size));
end loop;
if rising_edge(clk) then
for j in rsorted'LEFT to rsorted'RIGHT - 1 loop
for i in rsorted'LEFT to rsorted'RIGHT - 1 - j loop
if var_array(i).contents < var_array(i + 1).contents then
temp := var_array(i);
var_array(i) := var_array(i + 1);
var_array(i + 1) := temp;
end if;
end loop;
end loop;
-- for i in sorted'range loop -- the sorted contents
-- sorted_array(i) <= var_array(i).contents;
-- end loop;
-- or
for i in sorted'range loop -- the original indexes
sorted_array(i) <= var_array(i).index;
end loop;
end if;
end process;
end architecture behaviour;
library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;
entity sort_tb is
end entity;
architecture behav of sort_tb is
use work.array_type.all;
signal clk: std_logic := '0';
signal bit_array: sorted;
signal sorted_array: sorted;
-- Clock period definitions
constant clk_period: time := 10 ns;
begin
DUT:
entity work.sort (behaviour)
port map (
clk => clk,
bit_array => bit_array,
sorted_array => sorted_array
);
clk_process:
process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
end process;
process
begin
bit_array <= ( x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0",
x"0", x"0", x"0", x"0", x"0", x"0", x"0", x"0" );
wait for 10 ns;
bit_array <= ( x"0", x"0", x"0", x"4", x"0", x"0", x"0", x"3",
x"2", x"2", x"0", x"0", x"0", x"5", x"0", x"0" );
wait for 10 ns;
bit_array <= ( x"0", x"0", x"9", x"4", x"0", x"4", x"0", x"3",
x"2", x"2", x"0", x"8", x"0", x"5", x"0", x"0" );
wait;
end process;
end architecture;
You could conceivably output both the index list and the sorted contents in two different sorted arrays.
The above can do either by commenting out one output or the other.
And if you check the output waveform:
Against the input array values you'd find it's correct.
I'm a beginner at vhdl and I'm trying to make a 8 bit divider using shift and subtract method. The code for the divider is okay, I guess, but I'm having problems in simulating the inputs. When I use the Verilog test fixture, my inputs which should be (dividend=51 [00110011b], divisor=19 [00010011b]) always end up becoming (dividend=49 [00110001b], divisor=49 [00110001b])) in iSim, and then the outputs (Quotient and remainder = xxxxxxx (unknown)) instead of (quotient=2[00000010b] and remainder=13 [00001101b])...
As I mentioned before, I'm a beginner at vhdl and I've been at this for five hours, I've tried my best to search for a solution online, but failed.... so any help or alternative solution would be greatly appreciated.
I'm using Xilinx ISE 14.3 and iSim.
Here is the code for the 8 bit binary divider.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.STD_LOGIC_ARITH.all;
entity division is
generic(SIZE: INTEGER := 8);
port(reset: in STD_LOGIC; --reset
en: in STD_LOGIC; --enable
clk: in STD_LOGIC; --clock
num: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --dividend
den: in STD_LOGIC_VECTOR((SIZE - 1) downto 0); --divisor
res: out STD_LOGIC_VECTOR((SIZE - 1) downto 0); --result/quotient
rm: out STD_LOGIC_VECTOR((SIZE - 1) downto 0) --remainder
);
end division;
architecture behav of division is
signal bufreg: STD_LOGIC_VECTOR((2 * SIZE - 1) downto 0); --signal array to hold both accumulator and dividend registers as one i.e bufreg(18 bits)
signal dbuf: STD_LOGIC_VECTOR((SIZE - 1) downto 0); --signal array to hold the divisor
signal count: INTEGER range 0 to SIZE; --count to determine when to stop
alias ADreg is bufreg((2 * SIZE - 1) downto SIZE); --ADreg is is alias for top half of bufreg register(17th to 9th bit)
alias DVNDreg is bufreg((SIZE - 1) downto 0); --DVNDreg is is alias for bottom half of bufreg register(8th to 0th bit)
begin
--our process begins here
p_001: process(reset, en, clk)
begin
if reset = '1' then
res <= (others => '0');
rm <= (others => '0');
count <= 0;
elsif rising_edge(clk) then
if en = '1' then
case count is
when 0 =>
ADreg <= (others => '0');
DVNDreg <= num;
dbuf <= den;
res <= DVNDreg;
rm <= ADreg;
count <= count + 1;
when others =>
if bufreg((2 * SIZE - 2) downto (SIZE - 1)) >= dbuf then
ADreg <= '0' & (bufreg((2 * SIZE - 3) downto (SIZE - 1)) - dbuf((SIZE - 2) downto 0));
DVNDreg <= DVNDreg ((SIZE - 2) downto 0) & '1';
else
bufreg <= bufreg((2 * SIZE - 2) downto 0) & '0';
end if;
if count /= SIZE then
count <= count + 1;
else
count <= 0;
end if;
end case;
end if;
end if;
end process;
end behav;
And here is the code for the Verilog test fixture (.v file):
module BINdivisionTEST;
// Inputs
reg reset;
reg en;
reg clk;
reg [7:0] num ;
reg [7:0] den ;
// Outputs
wire [7:0] res;
wire [7:0] rm;
// Instantiate the Unit Under Test (UUT)
division uut (
.reset(reset),
.en(en),
.clk(clk),
.num(num),
.den(den),
.res(res),
.rm(rm)
);
initial begin
// Initialize Inputs
reset = 0;
en = 0;
clk = 0;
//num = 0;
//den = 0;
// Wait 100 ns for global reset to finish
#100;
en = 1;
#100;
clk=1;
num <= "00110011" ;
den <= "00010011" ;
// Add stimulus here
end
endmodule
My biggest problems seem to be initialization of the inputs and probably some mistaken assignments, misuse of the test fixture file and some bad coding.
I should also add that the divider code was compiled in vhdl, ISE 14.3.
I'm extremely sorry if this has been answered before and I don't mean to piss anyone off by uploading bad and amateur code. If this kind of problem has been addressed before could you please provide me with a link.
Again, any help is greatly appreciated.
The simulator may be treating those as strings instead of numbers. Try changing:
num <= "00110011" ;
den <= "00010011" ;
to:
num <= 8'b00110011;
den <= 8'b00010011;
I'm no expert on Verilog but it looks as if you might not be asserting Reset to your VHDL component before testing it.
That would lead "Count" in an uninitialised state so that when you use it, anything could happen and the "XXXX" outputs are a reflection of that.
The reset sequence should look like
En <= '0';
Clk <= '0';
Reset <= '1';
wait for 100 ns;
Reset <= '0';
wait for 100 ns;
-- start testing here
(in VHDL of course ... but it'll translate to Verilog easily)
This a general FPGA design question, I'm kind of new to FPGA design and have just embarked on my first large scale project, building some nice linear algebra solvers. The systems are pretty large so getting it right first time is important.
After successful simulations I am now sythensizing, but am having a nightmare, I am having to build and test it component by component as nothing behaves as it does in simulation! I'm mainly having issues with state machines where outputs are not being synchronized for example this is a data loader i'm using:
entity TriDiag_Data_Scheduler is
generic( W : integer :=16;
AW : integer := 10 -- address width
);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC; --attatched to data finished
d_ready : in STD_LOGIC;
din : in STD_LOGIC_VECTOR (W-1 downto 0);
wr_en : out STD_LOGIC_VECTOR (3 downto 0);
dout_a, dout_b, dout_c, dout_y : out STD_LOGIC_VECTOR (W-1 downto 0);
addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;
architecture Behavioral of TriDiag_Data_Scheduler is
type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');
signal wr_en_next : std_logic_vector(3 downto 0);
--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');
begin
process(clk,rst)
begin
if(clk'event and clk ='1') then
state_pr <= state_next;
d_buff_a <= d_buff_a_reg;
d_buff_b <= d_buff_b_reg;
d_buff_c <= d_buff_c_reg;
d_buff_y <= d_buff_y_reg;
addr_reg <= addr_next;
wr_en <= wr_en_next;
end if;
end process;
addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;
--Data out logic
process(state_pr, d_buff_a, d_buff_b, d_buff_c, d_buff_y, d_buff)
begin
d_buff_a_reg <= d_buff_a;
d_buff_b_reg <= d_buff_b;
d_buff_c_reg <= d_buff_c;
d_buff_y_reg <= d_buff_y;
case state_pr is
when a => --move data to a reg
d_buff_a_reg <= d_buff;
when b => --move data to b reg
d_buff_b_reg <= d_buff;
when c => --move data to c reg
d_buff_c_reg <= d_buff;
when y =>
d_buff_y_reg <= d_buff;
end case;
end process;
--next state and addr logic
process(state_pr, d_ready, rst, din)
begin
state_next <= state_pr;
addr_next <= addr_reg;
wr_en_next <= (others => '0');
if(rst = '1') then
state_next <= a;
addr_next <= (others =>'1');
wr_en_next <= (others => '0');
elsif(d_ready = '1') then
--Read in the data to the buffer
d_buff <= din;
--next state logic
case state_pr is
when a => --move data to a reg
addr_next <= addr_reg + 1;
-- d_buff_a_reg <= din;
wr_en_next <= "0001";
state_next <= b;
when b => --move data to b reg
wr_en_next <= "0010";
-- d_buff_b_reg <= din;
state_next <= c;
when c => --move data to c reg
wr_en_next <= "0100";
-- d_buff_c_reg <= din;
state_next <= y;
when y =>
-- d_buff_y_reg <= din;
wr_en_next <= "1000";
state_next <= a;
end case;
end if;
end process;
end Behavioral;
Basically when data is received via a UART module its job is to then load into the correct memory (controlled by write_en signal). The issue is that in all my designs (this is revision 7) all addr_out, wr_en and the correct data are in syn, but in synthesis I keep finding that the addr and wr_en are not in syn with the data and reads half from the preceding and half from the previous state.
What design practices should I use so that my VHDL is more syntheziable friendly because at this rate I will have to re-write all my previous hard-work for each component!
Many thanks
Sam
Working design, the old design was suffering from skew between the d_ready signal asserted from another module and this modules clk. As such the changes where not being synced as first hoped. To fixed this I but in the d_tick_next signal which asserts a locally sync signal d_tick which allowed all the correct behavior. One lesson learnt (correct me if i'm wrong) is that you can't rely on supposed externally clocked signals (such as d_ready) to be in sync with the receiving modules clk.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
-- ////////////////////////////////////////////////////////////////////
--Takes in the linear stream of data and builds up the memory structure
--INPUT DATA MUST FOLLOW SEQUENCE [a b c] x = [y] (0 if a or c do not exist) rows 0 and N respectivly
--//////////////////////////////////////////////////////////////////////
entity TriDiag_Data_Scheduler is
generic( W : integer :=16;
AW : integer := 10 -- address width
);
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC; --attatched to data finished
d_ready : in STD_LOGIC;
din : in STD_LOGIC_VECTOR (W-1 downto 0);
wr_en : out STD_LOGIC_VECTOR (3 downto 0);
dout_a, dout_b, dout_c, dout_y : out STD_LOGIC_VECTOR (W-1 downto 0);
addr_out : out STD_LOGIC_VECTOR (AW-1 downto 0));
end TriDiag_Data_Scheduler;
architecture Behavioral of TriDiag_Data_Scheduler is
type state is (a,b,c,y);
signal state_pr, state_next : state := y;
signal addr_reg, addr_next : std_logic_vector(AW-1 downto 0) :=(others =>'1');
signal wr_en_next : std_logic_vector(3 downto 0);
signal d_tick, d_tick_next : std_logic;
--data buffer
signal d_buff, d_buff_a, d_buff_b, d_buff_c, d_buff_y : std_logic_vector (W-1 downto 0) :=(others =>'0');
signal d_buff_a_reg, d_buff_b_reg, d_buff_c_reg, d_buff_y_reg : std_logic_vector (W-1 downto 0) :=(others =>'0');
begin
process(clk,rst)
begin
if(clk'event and clk ='1') then
state_pr <= state_next;
d_buff_a <= d_buff_a_reg;
d_buff_b <= d_buff_b_reg;
d_buff_c <= d_buff_c_reg;
d_buff_y <= d_buff_y_reg;
d_tick <= d_tick_next;
addr_reg <= addr_next;
wr_en <= wr_en_next;
end if;
end process;
addr_out <= addr_reg;
dout_a <= d_buff_a;
dout_b <= d_buff_b;
dout_c <= d_buff_c;
dout_y <= d_buff_y;
--Data out logic
process(state_pr,d_tick,rst)
begin
d_buff_a_reg <= d_buff_a;
d_buff_b_reg <= d_buff_b;
d_buff_c_reg <= d_buff_c;
d_buff_y_reg <= d_buff_y;
wr_en_next <= (others => '0');
if(rst = '1') then
addr_next <= (others =>'1');
else
addr_next <= addr_reg;
end if;
if(d_tick = '1') then
case state_pr is
when a => --move data to a reg
d_buff_a_reg <= d_buff;
addr_next <= addr_reg + 1;
wr_en_next <= "0001";
when b => --move data to b reg
d_buff_b_reg <= d_buff;
wr_en_next <= "0010";
when c => --move data to c reg
d_buff_c_reg <= d_buff;
wr_en_next <= "0100";
when y =>
d_buff_y_reg <= d_buff;
wr_en_next <= "1000";
end case;
end if;
end process;
--next state and d_tick
process(state_pr, d_ready, rst, din)
begin
state_next <= state_pr;
d_tick_next <='0';
if(rst = '1') then
state_next <= y;
elsif(d_ready = '1') then
--Read in the data to the buffer
d_buff <= din;
-- set sync tick
d_tick_next <= '1';
--next state logic
case state_pr is
when a =>
state_next <= b;
when b =>
state_next <= c;
when c =>
state_next <= y;
when y =>
state_next <= a;
end case;
end if;
end process;
end Behavioral;
I wrote a VHDL code for the state diagram shown(augh, couldn't post the image because I'm a new user). However, when I compile it it says that there are errors:
in line 16: process(clk) -- syntax error detected at the time of parsing
line 21: else -- syntax error detected at the time of parsing
line 23: end if; -- syntax error detected at the time of parsing.
This is my code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.ALL;
entity memory_controller is
port(clk: in std_logic;
reset: in std_logic;
bus_id: in std_logic_vector(7 downto 0);
read_write, burst: in std_logic;
oe, we, addr_1, addr_2: out std_logic
);
end memory_controller;
architecture behavioral of memory_controller is
type statetype is (idle, decision, wr, rd1, rd2, rd3, rd4);
signal present_state, next_state : statetype;
process(clk) [LINE 16]
begin
if (rising_edge(clk)) then
if (reset ='0') then
present_state <= next_state;
else [LINE 21]
present_state <= idle;
end if; [LINE 23]
end if;
end process;
process(present_state, read_write, ready, burst)
begin
case present_state is
when idle =>
oe => '0'; we=> '0'; addr_1=> '0'; addr_2=> '0';
if(bus_id = "11110011") then
next_state <= decision;
else
next_state <= idle;
end if;
when decision =>
if (read_write = '1')
then next_state <= rd1;
else next_state <= wr;
end if;
when wr =>
we = '1';
if (ready = '1')
then next_state <= idle;
else
next_state <= wr;
end if;
when rd1 =>
oe = '1';
addr_1 = addr_1 + '1';
addr_2 = addr_2 + '1';
if(ready = '0') then
next_state <= rd1;
if(burst = '0') then
next_state <= idle;
else next_state <= rd2;
end if;
when rd2 =>
oe = '1';
addr_1 = addr_1 + '1';
addr_2 = addr_2 + '1';
if(ready = '1') then
next_state => rd3;
else
next_state => rd2;
end if;
when rd3 =>
oe = '1';
addr_1 = addr_1 + '1';
addr_2 = addr_2 + '1';
if(ready = '1') then
next_state => rd4;
else
next_state => rd3;
when rd4 =>
oe = '1';
addr_1 = addr_1 + '1';
addr_2 = addr_2 + '1';
if(ready = '1')
then next_state => idle;
else next_state => rd4;
end if;
end case;
end process;
end behavioral;
The syntax is perfectly right, I don't understand why it's an error. What could be wrong?
Also, I want to use assert statements for cases when ready =0 , burst =0 and ready = 0 and burst = 1, but I'm not so sure as to how to implement them in the main code.
I have highlighted lines 16, 21 and 23.
Any help would be great.
The form of a VHDL module is typically:
entity MODULENAME is
<Port description>
end MODULENAME;
architecture behavioral of MODULENAME is
<signal declarations and similar>
begin
<synchronous and combinatorial logic statements>
end architecture behavioral;
What you are lacking is the begin after your signal declarations. That is, change
architecture behavioral of memory_controller is
type statetype is (idle, decision, wr, rd1, rd2, rd3, rd4);
signal present_state, next_state : statetype;
process(clk) [LINE 16]
begin
if (rising_edge(clk)) then
To:
architecture behavioral of memory_controller is
type statetype is (idle, decision, wr, rd1, rd2, rd3, rd4);
signal present_state, next_state : statetype;
begin
process(clk) [LINE 16]
begin
if (rising_edge(clk)) then
As Sonicwave points out, you are missing the begin keyword before your first statement.
There are several more syntax errors.
Signal assignments use a left-pointing arrow:
not oe => '0'; but oe <= '0';
not we = '1'; but we <= '1';
If you use an editor with direct compiler feedback, you'll save yourself a lot of time.