I'm new to VHDL and I've been trying to finish my combinatorial code in an assignment, however I don't know how to make cases account for specific combinations of the two 1-bit outputs: Permit and ReturnChange. My concern is is with the WHEN statements. Looking at this block, for example, does that WHEN line work?
WHEN NoBill => Permit <= '0'; ReturnChange <= '0';
IF (Input = "000") THEN NextState <= NoBill;
ELSIF (Input = "001") THEN NextState <= Rec5;
ELSIF (Input = "010") THEN NextState <= Rec10;
ELSIF (Input = "100") THEN NextState <= Rec20;
END IF;
The ReturnChange <= '0'; part is what I'm unsure about. Because I know that WHEN NoBill => Permit <= '0'; would work. However I needed those if-statements to apply when that combination of Permit and ReturnChange outputs are both 0. I wasn't sure how to include both, so I kind of just guessed the ReturnChange <= '0'; part. If my guess is incorrect, how would I properly do it?
I'm unsure if seeing the entire file or my state diagram would be helpful, but if it can help you understand anything better, just let me know. Thanks in advance!
Related
I am trying to implement the controller for a simple CPU in VHDL. The controller is modeled as an ASM that waits in a decode state until it receives the start signal. The next state that it progresses into depends on the machine code received and determines what operations the CPU performs.
I was intending to implement subtraction as a multicycle instruction. The first step would be to go to the SUB state, where 2's comp would be performed on one of the registers. Then, the controller would progress to the ADD state to perform the subtraction (addition on negative number). The process to implement the state machine in this way is shown below.
ASM: process(CLK, RESET_L) begin
if (RESET_L = '0') then
cur_state <= S_Decode;
DONE <= '0';
elsif (rising_edge(CLK)) then
case cur_state is
when S_Decode =>
if (START = '1' and (DEST(1) /= '1')) then
case instr is
when "000" => cur_state <= S_Load;
when "001" => cur_state <= S_Tab;
when "010" => cur_state <= S_And;
when "011" => cur_state <= S_Or;
when "100" => cur_state <= S_Add;
when "101" => cur_state <= S_Sub;
when "110" => cur_state <= S_Srl;
when "111" => cur_state <= S_out;
end case;
DONE <= '0';
else
DONE <= '0';
end if;
DONE <= '0';
when S_Sub =>
debug_sig <= '1';
cur_state <= S_Add;
when others =>
cur_state <= S_Decode;
DONE <= '1';
end case;
end if;
end process;
However, in simulation, my design appears to be skipping the SUB state all together and progressing directly to the ADD state.
I attached a screenshot of the simulation below. The OP signal shows the opcode passed to the datapath. The opcode circled in blue is the ADD opcode. I would be expecting the 2's comp opcode. The setting of this opcode is done in a separate process, which is sensitive to the cur_state. I didn't include it here because I don't believe the issue lies in the mapping of the opcode to the current state but in the state machine itself.
I also included a debug signal which will go high once the state machine transitions from SUB to ADD. As can be seen in the simulation, this signal goes high as soon as the start signal goes high. From this, I assume that the case statement is executing both the "when S_Decode" block and the "when S_Sub" block together. It appears that as soon as the controller enters the SUB state, it immediately transitions to the ADD state.
Any feedback or help is appreciated. Please let me know if I can provide any more clarification. Thanks in advance.
While implementing a state machine on VHDL I was wondering how can I set the output / current state initial condition. I read on one of the questions on here.
One of the answers said we do the initialization before the case structure:
process(currentstate, a)
begin
b <= '1';
c <= '1';
case currentstate is
when s1 =>
if (a = '1') then
c <= '0';
end if;
nextstate <= s2;
However doesn't that make us automatically set b<='1' and c<='1' whenever we get into the process? So if we are at a state say A and we are at the conditions of moving to B whenever we enter the process this directly puts b<='1' and c<='1' isn't that true ?
Or does it actually just run once we start the program and then gets bounded in the case structure ?
Also check this link.
In their FSM implementation they did not specify the initial state how does the compiler or FPGA determine the start state ?
The lines you are looking at are not performing initialization.
b <= '1';
c <= '1';
Remember that VHDL is a hardware description language, not a programming language. What those two assignments do is to set a default assignment for those signals, unless something else contradicts these assignments later in the process. You can assign to the same signal several times in one process, and whichever assignment happens last will take priority. This saves having to write code like:
case State is
when s1 =>
a <= '0';
b <= '1';
c <= '1';
when s2 =>
a <= '1';
b <= '0';
c <= '1';
when s2 =>
a <= '1';
b <= '1';
c <= '0';
end case;
It can end up being quite repetitive and error prone to have the same assignments in many states, so default assignments can really tidy it up:
a <= '1';
b <= '1';
c <= '1';
case State is
when s1 =>
a <= '0';
when s2 =>
b <= '0';
when s2 =>
c <= '0';
end case;
The same pattern works for if statements where you don't want to cover every output signal in every logical branch.
If you want an initial state, there are two approaches that may be applicable depending on the scenario. Here you would assert reset at start-up to set the initial state. Note that the case statement is inside a clocked process:
process (clk)
begin
if (rising_edge(clk)) then
if (reset = '1') then
State <= s1;
else
case State is
when s1 =>
State <= s2;
when s2 =>
State <= s1;
end case;
end if;
end if;
end process;
The other option is to define your state signal with an initial value:
signal State : state_type := s1;
I won't go into the pros and cons of using initial values as there are existing questions that explore this.
i am currently in the midst of writing a VHDL description of the unit(s) controlling a Sitronix ST7066U and LCD Module 1602A-1 for Xilinx Virtex-7, using Vivado Suite as my environment.
the Message Processing Unit is modeled with a 2-states (next state and outputs/conditions) FSM, but I have a huge issue.
Since the display has its own "operating times", as in the datasheet, I need to realize synthetizable delays inside my FSM when it reaches the states where the display itself is doing its things, and we cannot proceed with more character sending.
Such part was originally written like this:
when count_i => --waits for I_MAX cycles for the internal setup of the display
if (I = I_MAX_tb) then
I <= 0;
TRIGGER <= '1';
op_flag <= '1';
else
I <= I + 1;
end if;
if op_flag = '1' then
op_flag <= '0';
next_state <= init_state;
else
next_state <= count_i;
end if;
but, in simulation, the state machines stays in count_i state and doesn't realize that a new state assignment has happened.
I have tried the following construct
if (state'event) then
I<=I+1;
if (I = I_MAX_tb) then
I <= 0;
TRIGGER <= '1';
op_flag <= '1';
end if;
end if;
but it doesn't come close to working.
I am pretty sure it is a simple implementation issue, but, still...
(might be something related to my process' sensitivity list also?)
I'm writing a design in VHDL and after synthesis I observed that the number of multiplexers (dedicated) used is high. My code has a lot of if-else staments, so it seems logical.
But I wanna know if it is possible to implement if-else (or similar staments) in another way to reduce the number of multiplixers resources used.
Thanks!
You can try to use simple logic elements like and or or. For example:
if (a and b) = '1' then
out_0 <= '1';
else
out_0 <= '0';
end if;
if (c or d) = '1' then
out_1 <= '1';
else
out_1 <= '0';
end if;
This is construction can be replaced with following:
out_0 <= a and b;
out_1 <= c or d;
And so on...
say I have the following state machine:
....
if state_a then
output_a <= '0';
next_state <= state_b;
elsif state_b then
output_a < '0';
if cond then
output_b <= '1';
next_state <= state_a;
else
next_state <= state_b;
end if;
end if;
......
I don't want output_b to change except when being assigned again in state_b. However, when I try to synthesise this code, most synthesis tools will say something along this line:
warning: found 1-bit latch for signal "output_b". latches aren't
recommended for FPGA design because it might result in timing
problems.
Should I worry about this at all? If so, why and what are the alternatives?
Following Xilinx:
If latch inference is intended, you can safely ignore this message. However, some inefficient coding styles can lead to accidental latch inference. You should analyse your code to see if this result is intended.
Some techniques to avoid latch inference:
Make sure any "if / else if" statements have a concluding "else" clause,
Assign to all the same outputs in each case,
Include all possible cases in the case statement (but be aware that WHEN OTHERS clause always works, but can create extraneous logic).
if you have incomplete if/elsif or case statement in a clocked process, it's absolutely harmless.
if rising_edge(clk)
if a then
out <= b;
end if;
end if;
It means that you have flip-flop with some sort of feedback, or, like in this case, you have flip-flop with clock enable pin used, which is even better.
If you have incomplete if/elsif or case statement in not clocked process - it's a latch and it's in most cases:
something you don't really want;
something that point out on a poor design and can be avoided with redesign.
If you complete your little example, someone can help you redesign it. Now it is not enough information.
The problem you have stems from the FSM coding style you're (presumably) using. As other pointed it is not possible to guess what you want the code to do, since you did not provide enough code to figure that out, so I present one possible interpretation, assuming you really wanted to change output_a somehow and that one time (after reset) latching of output_b should happen at the same time FSM state transitions.
Using 2 processes per FSM style, we have code that is not giving latch warnings:
----
signal CLK, RESET, cond : std_logic;
type state_t is (a,b);
signal state, state_next : state_t;
signal ouput_a, output_b, output_b_next : std_logic;
----
FSM_clock: process(all)
begin
if rising_edge(CLK) then
if RESET then
state <= a;
output_b <= '0';
else
state <= state_next;
output_b <= output_b_next;
end if;
end if;
end process;
FSM_next: process(all)
begin
state_next <= state;
output_b_next <= output_b;
output_a <= '0';
case state is
when a =>
state_next <= b;
when b =>
output_a <= '1';
if cond then
output_b_next <= '1';
state_next <= a;
else
state_next <= b;
end if;
end case;
end process;