I'm programming a N-bit non-restoring divider, but I faced a little problem.
I have an Operative Part (combinatorial) and a Control Part (Finite State Machine).
The Control Part has a 2 processes FSM, 1 for updating the next state and 1 for the "state sequence".
update: process(clk_in, next_state)
begin
if rising_edge(clk_in) then
current_state <= next_state;
end if;
end process;
And this is the second process:
control: process(current_state, start, S_in, counted)
variable sub_tmp : STD_LOGIC := '0';
begin
[...]
sub <= sub_tmp; -- sub is an output signal of my entity that goes in the Operative Part
case current_state is
when idle =>
if start='1' then
next_state <= init;
else
next_state <= idle;
end if;
when init =>
-- [...]
next_state <= subtract;
when subtract =>
en_A <= '1';
sub_tmp := '1';
next_state <= test;
when test => -- shift
en_Q <= '1';
if S_in='0' then
sub_tmp := '1';
else
sub_tmp := '0';
end if;
if counted=N/2-1 then
next_state <= finished;
else
next_state <= operation;
end if;
when operation =>
en_A <= '1';
next_state <= test;
when finished =>
stop <= '1';
next_state <= idle;
end case;
end process;
As you can see, I need to change the value of the sub ONLY in 2 cases (subtract and test), while I don't have to change in the other cases.
The problem is that when I try to synthesize this code it turns out that sub_tmp is a LATCH, but I don't want a latch.
I need to do something like this:
state 1 => set sub to '1' or '0' (depending on another input)
state 2 => do other operations (but sub must remain the value set before) and return to state 1
etc...
To clarify more: in certain states of my FSM (not all of them) I set the value of a variable (let's call it sub_tmp). In other states I don't change its value. Then let's say I have an output PIN called "sub_out". Now, independently of the variable value, I want to output its value to this pin (sub_out <= sub_tmp; or similar).
What am I missing?
What you are missing is the behavior you describe IS a latch. Anything with memory (ie: "in other states I don't change it's value") is either a latch or a register (flip-flop). If you don't want a latch or a register, you need to assign a specific value to the signal in each and every code path, and not let it 'remember' it's previous state.
Related
I am new to VHDL and have had some difficulty in performing the assignment of two different values to the same signal inside a process. For example,
process(CLK)
if rising_edge(CLK) then
OUTPUT0 <= X(0);
OUTPUT1 <= X(1);
OUTPUT2 <= X(2);
LED0 <= VALUE;
OUTPUT0 <= Y(0);
OUTPUT1 <= Y(1);
OUTPUT2 <= Y(2);
LED1 <= VALUE;
end if;
end process;
Note that VALUE is an output dependent on the values assigned to OUTPUT0, OUTPUT1, OUTPUT2.
From what I understand in a process is that the last assignment to the same signal is always applied. What I am trying to do is apply two different sets of values to one set of inputs, map the output and it be done sequentially. I have tried separate processes tied to the same clock, a FSM to attempt to move sequentially and so on. At this point I have exhausted my knowledge of things to try.
My question is: What would be the best way to sequentially assign two values to one input and map its output in order?
EDIT:
As per Brian's suggestion on the state machine I had went ahead and implemented one again and found my error and fixed it. This gave the sequential assignment I was looking for.
I was reading 2 addresses from one instance of 32x1 distributed RAM which is the reason for a sequential assignment. Apologies for not providing the best example. Below is my final implementation:
RAM_READ_FSM : process(CLOCK) -- FSM to read the RAM addresses sequentially
begin
if rising_edge(CLOCK) then
case curr_state is
when S0 => if SW2 = '1' then
RAMADDR0 <= XYVEC(5); -- Y addresses
RAMADDR1 <= XYVEC(6);
RAMADDR2 <= XYVEC(7);
RAMADDR3 <= XYVEC(8);
RAMADDR4 <= XYVEC(9);
LED1 <= RAMOUT;
curr_state <= S1;
else
curr_state <= S0;
end if;
when S1 => if SW2 = '1' then
RAMADDR0 <= XYVEC(0); -- X addresses
RAMADDR1 <= XYVEC(1);
RAMADDR2 <= XYVEC(2);
RAMADDR3 <= XYVEC(3);
RAMADDR4 <= XYVEC(4);
LED2 <= RAMOUT;
curr_state <= S0;
else
curr_state <= S1;
end if;
end case;
end if;
end process;
The signals should be driven from the same process : multiple drivers would interfere with each other..
See Is process in VHDL reentrant? on signal assignment semantics.
now you can see there is need for some delay (even just 2 delta cycles, if the logic calculating VALUE is just a simple signal assignment) between the X and LED0 assignments.
You were on the right lines with a state machine but you didn't say anything about how it failed. Worth adding that to the Q to get a fuller answer.
Meanwhile there is a simple way to add delay :
like
LEDS : process is
begin
wait until rising_edge(CLK);
OUTPUT0 <= X(0);
OUTPUT1 <= X(1);
OUTPUT2 <= X(2);
wait until rising_edge(CLK);
LED0 <= VALUE;
wait until rising_edge(CLK);
OUTPUT0 <= Y(0);
-- etc
end process LEDS;
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.
We are using OR1200 for our project and we would like to assign an interrupt to the 8th button of FPGA Board. Here is the code to generate interrupt:
inrpt: process(CLK_I, RST_I)
begin
if RST_I = '1' then
butt_int_pul <= '0';
butt_int_tmp <= '0';
elsif rising_edge(CLK_I) then
if(DATA_I(8) = '1' and butt_int_tmp = '0') then
butt_int_pul <= '1';
else
butt_int_pul <= '0';
end if;
butt_int_tmp <= DATA_I(8);
end if;
end process inrpt;
process(CLK_I, RST_I)
begin
if RST_I = '1' then
butt_int <= '0';
elsif butt_int_pul = '1' then
butt_int <= '1';
elsif clear_int = '1' then
butt_int <= '0';
end if;
end process;
We only want this interrupt to be handled only once (holding the button should not call the interrupt again), that's why we included a flag to check this (butt_int_tmp).
The problem is that the interrupt call is not stable. It does not call each time we press the button. When we remove the flag, it works, but in this case, it is handled as many as we hold the button.
What are we doing wrong?
To start with, that second process is not properly written. It should have a structure equivalent to the first process (i.e., if(rising_edge(CLK_I)) surrounding all but the reset logic). You are currently describing a latch with multiple enable signals and wrong sensitivity list.
Moving on, there's no real reason you need that second process at all. You just need one register to act as interrupt (butt_int), and one to keep track of the previous state of the button (butt_prev). The interrupt is triggered for one cycle when DATA_I(8) is '1' while butt_prev is '0' (i.e., the button changed from not-pressed to pressed).
process(CLK_I, RST_I) begin
if(RST_I='1') then
butt_prev <= '0';
butt_int <= '0';
elsif(rising_edge(CLK_I)) then
if(DATA_I(8)='1' and butt_prev='0') then
butt_int <= '1';
else
butt_int <= '0';
end if;
butt_prev <= DATA_I(8);
end if;
end process;
Note that this will only work if your button is properly debounced, otherwise you are likely to get multiple interrupts triggered when you press (or even release) the button.
Its best not to think about interrupts. As you're targetting an FPGA, you're describing digital logic, not a software processor.
There a numerous way to build a circuit with the behaviour you want.
The simplest is probably a re-timed latch
signal latched_button : std_logic;
signal meta_chain : std_logic_vector(2 downto 0);
p_async_latch: process(rst_i,data(8))
begin
if rst_i = '1' then
latched_button <= '0';
elsif data(8) = '1' then
latched_button <= '1';
end if;
end process;
p_meta_chain: process(rst_i,clk_i)
begin
if rst_i = '1' then
meta_chain <= (others => '0');
elsif rising_edge(clk_i) then
meta_chain <= meta_chain(1 downto 0) & latched_button;
end if;
end process;
button_int <= '1' when meta_chain(2 downto 1) = "01" else '0';
This causes the button press to be latched asynchronously. The latched signal is then clocked along a shift register, and the interrupt is only valid for one cycle, which is the first clock cycle that the latch is seen on the clock domain.
I have problems on communicating between the processes. I used to use flag and clearFlag to tackle this, but it's kind of annoying and not looking good. What is the best practice to handle this? Here is a sample code on how I did it before:
Proc_A : process (clk, reset, clrFlag)
begin
if clrFlag = '1' then
flag <='0';
elsif reset = '0' then
A <= (others => '0');
elsif rising_edge (clk) then
A <= in;
flag <= '1';
end if;
end process;
Proc_B : process (clk, reset)
begin
if reset = '0' then
B <= (others => '0');
elsif rising_edge (clk) then
if flag = '1' then
B <= data;
clrFlag <= '1';
else
clrFlag <= '0';
end if;
end if;
end process;
This way works but I don't think it is nice method. I have to write a flag and clrFlag couple to do this task. All I want to do is when something happened (e.g. A <= in;), it triggers another proc, Proc_B for example, to run once or a number of times. What is the best practice to this problem? Thanks!
For simulation, you can make a process wait on a signal:
Proc_B : process
begin
wait until flag'event;
B <= data;
end process;
and just write the flag with its inverse every time you need something to happen.
In synthesisable logic, you either have to exchange flag signals, as you do, or use some other higher-level communication (like a FIFO, messagebox, or similar).
However, if all your proc_b logic takes place in a single cycle - so you can guarantee not to miss a flag, and to be able to keep up even if flag is asserted all the time (as it looks like you do) - you can do this (and combine the two processes):
Proc : process (clk, reset, clrFlag)
begin
flag <='0';
if reset = '0' then
A <= (others => '0');
B <= (others => '0');
elsif rising_edge (clk) then
if some_trigger_event = '1' then
A <= in;
flag <= '1';
end if;
-- recall that due to VHDL's scheduling rules, this "if" will take place
-- one clock cycle after the flag is written to, just as if it were in a
-- separate process
if flag = '1' then
B <= data;
end if;
end if;
end process;
Side note - your code is not ideal for synthesis... you really only want the reset part outside the clocked part:
Proc_A : process (clk, reset)
begin
if reset = '0' then
A <= (others => '0');
elsif rising_edge (clk) then
if clrFlag = '1' then
flag <='0';
else
A <= in;
flag <= '1';
end if;
end process;
Fellow SO users,
I'm programming my ADC (ADC0804 which is mounted on a breadboard connected to a Spartan-3 FPGA board). Now, I'm using this ADC to provide digital output for my humidity sensor. The ADC outputs an 8-bit value which I'm displaying on the LEDs on the FPGA board.
Now, I'm writing the state machine in such a way that the ADC would always continue to keep outputting values even when I vary the humidity level. But as for the current implementation I have, eventhough I'm looping back to the first state, I'm not getting a continuous stream of values. I'm only getting one 8-bit value at a time (I.E.; I have to keep pressing the reset button to update the value displayed on the LEDs). The following is my code.
FSM_NEXT_STATE_INIT : PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
CURR_STATE <= STARTUP;
ELSIF (CLK'EVENT AND CLK = '1') THEN
CURR_STATE <= NEXT_STATE;
END IF;
END PROCESS;
START_FSM : PROCESS (CURR_STATE, INTR)
BEGIN
CASE CURR_STATE IS
WHEN STARTUP =>
NEXT_STATE <= CONVERT;
WR <= '0';
READ_DATA <= '0';
WHEN CONVERT =>
IF (INTR = '0') THEN
NEXT_STATE <= READ1;
ELSE
NEXT_STATE <= CONVERT;
END IF;
WR <= '1';
READ_DATA <= '0';
WHEN READ1 =>
NEXT_STATE <= READ2;
WR <= '1';
READ_DATA <= '1';
WHEN READ2 =>
NEXT_STATE <= STARTUP;
WR <= '1';
READ_DATA <= '0';
WHEN OTHERS =>
NEXT_STATE <= STARTUP;
END CASE;
END PROCESS;
PROCESS (CLK, RST)
BEGIN
IF (RST = '1') THEN
Y <= (OTHERS => '0');
ELSIF (CLK'EVENT AND CLK = '1') THEN
IF (READ_DATA = '1') THEN
Y <= D7&D6&D5&D4&D3&D2&D1&D0; --Concatenate the 8-bit ADC output
END IF;
END IF;
END PROCESS;
You'll notice that in state 'READ2', I'm looping back to the beginning (so that I can keep reading values continuously as the states transition) but somehow I don't think this is working. Could anyone please provide some assistance on how to go about solving this?
After a look on the data sheet for the ADC0804 I found following which could be the/a possible reason:
Note: Read strobe must occur 8 clock periods (8/fCLK) after assertion of interrupt to guarantee reset of INTR.
Inserting a WAIT state between CONVERT and READ1 might fix the problem.