In VHDL (and HDLs in general) a for
loop does not denote sequential execution like it does in a software programming language — it denotes the construction of multiple parallel instances of the hardware described in the body of the loop.
In your case, you have many assignments to the same variable BCD
/bcd
, and these are conflicting with each other. If you really intend to construct a system based on two shift registers (one binary, one bcd) that takes 14 clock periods to do the conversion, then you need to describe the hardware that way, and set up a state machine to control it.
On the other hand, if you really want to do it entirely combinatorially, then you need to create different intermediate variables (e.g., arrays that are indexed by the loop control variable) to hold the results at each stage.
In general an analysis error is associated with a line of your VHDL design description. Comments that are close don't really cut it and the actual error message can be significant.
library ieee;
use ieee.std_logic_1164.all;
entity controller is
Port (
reset: in std_logic;
clk: in std_logic;
ring_k_1: in std_logic;
b_n: in std_logic_vector(3 downto 0);
start: in std_logic;
STOP: out std_logic;
LOAD_CMD: out std_logic;
ADD_CMD: out std_logic;
BYPASS_CMD: out std_logic
);
end controller;
architecture Behavioral of controller is
--declare states
type state_typ is (IDLE, INIT, TEST, ADD, BYPASS);
signal state : state_typ;
begin
process(reset,clk)
variable i : natural := 0;
begin
if reset = '0' then
state <= IDLE;
elsif clk'event and clk = '1' then
case state is
when IDLE =>
if START = '1' then
state <= INIT;
else
state <= IDLE;
end if;
when INIT =>
state <= TEST;
when TEST =>
if ring_k_1 = '1' then
state <= IDLE;
elsif ring_k_1 = '0' and b_n(i) = '0' then
state <= BYPASS;
i := i+1;
elsif ring_k_1 = '0' and b_n(i) = '1' then
state <= ADD;
i := i+1;
-- How do you prevent b_n(i) from going outside of 3 downto 0?
end if;
when others => -- when ADD, when BYPASS must have all states
end case;
end if;
end process;
STOP <= '1' when state = IDLE else '0';
ADD_CMD <= '1' when state = ADD else '0';
BYPASS_CMD <= '1' when state = BYPASS else '0';
LOAD_CMD <= '1' when state = INIT else '0';
end Behavioral;
Besides the corrections you made there is at least one more error with the case statement, in that all the choices must be represented you are missing representation for states ADD and BYPASS:
If the expression is the name of an object whose subtype is locally
static,whether a scalar type or an array type, then each value of the
subtype must be represented once and only once in the set of choices
of the case statement, and no other value is allowed;...
(From the LRM)
I don't know enough about the intent of your design to add branches from states ADD
and BYPASS
.
Comment out the when others =>
and ghdl tells us directly that two state enumerations are represented among the choices:
ghdl -a controller.vhdl
controller.vhdl:34:13: no choices for add to bypass
ghdl: compilation error
Error messages aren't standardized in VHDL, ghdl pointed to the line the case statement begins on but did specify the range of values missing from the specified choices.
Notice the simple mechanism used to allow analysis to successfully complete doesn't handle state transitions and likely should.
There's also nothing apparent that will keep b_n(i) within the index range 3 downto 0. Scalar arithmetic operators their conventional mathematical meaning while b_n(i) evaluation will be bounds checked potentially resulting in a run time error should b_n(i)
be evaluated and i
as an index and fall outside the subtype index range.
Integer arithmetic results can be out of range for use as an index to b_n. You are only using +
so only have to limit i
to 3
(b_n'LEFT
).
If you synthesize the design you'd want to range constrain i
to specify the number of bits necessary to implement i
(as a counter in this case).
Range constraining i
for synthesis implies evaluating for 3
before assigning the new i
value to avoid an out of range error. If i = 3, set i
to 0
instead, otherwise add 1
to `i1.
In place of i := i+1;
use
if i=3 then
i := 0;
else
i:= i+1;
end if;
For synthesis declare the range of i:
variable i : integer range 0 to 3 := 0;
if b_n'LEFT
were the result of a generic or constant declaration and use you could use that instead of 3:
variable i : integer range b_n'RIGHT to b_n'LEFT := b_n'RIGHT; -- 3 downto 0
or
variable i : integer range b_n'RANGE := b_n'RIGHT; -- where b_n'RIGHT = 0
And in place of i := i+1;
in your original code use
if i = b_n'LEFT then
i := 0; -- or use i := b_n'RIGHT;
else
i:= i + 1;
end if;
Addendum
Your changed code had an else if
in place of elsif
where the clock was being evaluated:
library ieee;
use ieee.std_logic_1164.all;
entity controller is
port (
reset: in std_logic;
clk: in std_logic;
ring_k_1: in std_logic_vector(3 downto 0);
b_n: in std_logic_vector(3 downto 0);
start: in std_logic;
STOP: out std_logic;
LOAD_CMD: out std_logic;
ADD_CMD: out std_logic;
BYPASS_CMD: out std_logic
);
end controller;
architecture behavioral of controller is
--declare states
type state_typ is (IDLE, INIT, TEST, ADD, BYPASS);
signal state : state_typ;
begin
process(reset,clk)
--variable i : natural := 0;
variable i : integer range b_n'RIGHT to b_n'LEFT := b_n'RIGHT; -- 3 downto 0
begin
if reset = '1' then
state <= IDLE;
STOP <= '1';
elsif clk'event and clk = '1' then -- else if
case state is
when IDLE =>
if START = '1' then
state <= INIT;
else
state <= IDLE;
STOP <= '1';
end if;
when INIT =>
LOAD_CMD <= '1';
state <= TEST;
when TEST =>
if ring_k_1(3) = '1' then
state <= IDLE;
STOP <= '1';
elsif ring_k_1(3) = '0' and b_n(i+1) = '0' then
state <= BYPASS;
BYPASS_CMD <= '1';
-- i := i+1;
if i = b_n'LEFT then
i := 0;
else
i:= i + 1;
end if;
elsif (ring_k_1(3) = '0' and b_n(i+1) = '1') then
state <= ADD;
ADD_CMD <= '1';
if i = b_n'LEFT then
i := 0; -- or use i := b_n'RIGHT;
else
i:= i + 1;
end if;
end if;
when BYPASS =>
state <= TEST;
when ADD =>
state <= TEST;
end case;
end if; --end for the clock event
end process;
end behavioral;
The analyzer I was using complained that there should have been if
following end
instead of process (above end behavioral
). It shows among other things the value of readability as well as including the actual error messages:
cont_mod.vhdl:72:9: 'if' is expected instead of 'process'
ghdl: compilation error
Note the line number : character position wasn't particularly helpful other than to tell us something else was missing an enclosing end
statement. If I'm not mistaken this is the same problem Vladimir Craver pointed out in his answer, which I used as a starting point.
I'd suggest a separate question might be in order should you need help with the simulation results.
Now that your design description for entity controller should analyze perhaps you could ask a separate question should you have trouble with functionality.
I reformatted your second code posting to allow the error to show up a bit easier. Through indentation we don't see any missing level of end if
which leaves a syntax error implying the need for another level. else
and if
in
else if clk'event and clk = '1' then
implies a separate end if
for the else
and if
.
Best Answer
Each of the lines preceding an error is missing a semicolon at the end, e.g.