Incrementing a seven segment display in a state machine for de1 board - vhdl

I am using a state machine to create a countdown timer that on startup, displays 00:00 and when Key1 is pressed, you can input a time by incrementing/decrementing minutes by 1 and if the up/down button is held for 5 cycles it will go up/down by 5. Thanks to some awesome help (#DavidKoontz) I have finished the code. There is no need to debounce the buttons in my code b/c my altera board seems to pick up the low signals just fine.Since I am only using one clock the buttons react slowly b/c the Clock is set to 1Hz.
Library ieee;
USE ieee.std_logic_1164.ALL;
ENTITY CountDownTimer IS
PORT(
CLK,RESET: IN STD_LOGIC;
a1, b1, c1, d1, e1, f1, g1 : OUT STD_LOGIC;
a2, b2, c2, d2, e2, f2, g2 : OUT STD_LOGIC;
a3, b3, c3, d3, e3, f3, g3 : OUT STD_LOGIC;
a4, b4, c4, d4, e4, f4, g4 : OUT STD_LOGIC;
--All 4 buttons for timer
BUTTON0, BUTTON1, BUTTON2, BUTTON3: IN STD_LOGIC;
--LEDR9
ON_OFF_LED: OUT BIT;
--LEDR9-R6
INPUT_LED1, INPUT_LED2, INPUT_LED3, INPUT_LED4: OUT BIT;
--LEDR0
DONE_LED: OUT BIT);
END CountdownTimer;
ARCHITECTURE Counter OF CountDownTimer IS
--Define state machine
TYPE STATE_TYPE IS (A_ON_OFF, B_INPUT, C_COUNTDOWN, D_DONE);
SIGNAL State : STATE_TYPE;
--Buttons produce 0 when pressed, signal for 1 when pressed
SIGNAL B3D0, B3D1, B3D2, B3D3: STD_LOGIC := '0';
SIGNAL B2D0, B2D1, B2D2, B2D3: STD_LOGIC := '0';
SIGNAL CLOCK: STD_LOGIC := '0';
SIGNAL Count: INTEGER:= 1;
--SIGNAL for range of integer values
SIGNAL Minute1 : INTEGER RANGE 0 TO 6;
SIGNAL Minute2 : INTEGER RANGE 0 TO 9;
SIGNAL Second1 : INTEGER RANGE 0 TO 5;
SIGNAL Second2 : INTEGER RANGE 0 TO 9;
--Output for the seven segment displays
SIGNAL OUTPUT_HEX0 : STD_LOGIC_VECTOR(6 DOWNTO 0);
SIGNAL OUTPUT_HEX1 : STD_LOGIC_VECTOR (6 DOWNTO 0);
SIGNAL OUTPUT_HEX2 : STD_LOGIC_VECTOR (6 DOWNTO 0);
SIGNAL OUTPUT_HEX3 : STD_LOGIC_VECTOR (6 DOWNTO 0);
SIGNAL B3_HOLD: STD_LOGIC := '0'; --Gets 1 if button3 was held
SIGNAL B2_HOLD: STD_LOGIC := '0'; --Gets 1 is button2 was held
BEGIN
--Segment 1 display pins
a1 <= OUTPUT_HEX0(6);
b1 <= OUTPUT_HEX0(5);
c1 <= OUTPUT_HEX0(4);
d1 <= OUTPUT_HEX0(3);
e1 <= OUTPUT_HEX0(2);
f1 <= OUTPUT_HEX0(1);
g1 <= OUTPUT_HEX0(0);
--Segment 2 display pins
a2 <= OUTPUT_HEX1(6);
b2 <= OUTPUT_HEX1(5);
c2 <= OUTPUT_HEX1(4);
d2 <= OUTPUT_HEX1(3);
e2 <= OUTPUT_HEX1(2);
f2 <= OUTPUT_HEX1(1);
g2 <= OUTPUT_HEX1(0);
--Segment 3 display pins
a3 <= OUTPUT_HEX2(6);
b3 <= OUTPUT_HEX2(5);
c3 <= OUTPUT_HEX2(4);
d3 <= OUTPUT_HEX2(3);
e3 <= OUTPUT_HEX2(2);
f3 <= OUTPUT_HEX2(1);
g3 <= OUTPUT_HEX2(0);
--Segment 4 display pins
a4 <= OUTPUT_HEX3(6);
b4 <= OUTPUT_HEX3(5);
c4 <= OUTPUT_HEX3(4);
d4 <= OUTPUT_HEX3(3);
e4 <= OUTPUT_HEX3(2);
f4 <= OUTPUT_HEX3(1);
g4 <= OUTPUT_HEX3(0);
WITH Second2 SELECT
--One's second place, 0 to 9
OUTPUT_HEX0 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0100000" WHEN 6,
"0001101" WHEN 7,
"0000000" WHEN 8,
"0001100" WHEN 9,
"0000001" WHEN OTHERS;
WITH Second1 SELECT
--Tens second place, 0 to 5
OUTPUT_HEX1 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0000001" WHEN OTHERS;
WITH Minute2 SELECT
--Ones minute place, 0 to 9
OUTPUT_HEX2 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0100000" WHEN 6,
"0001101" WHEN 7,
"0000000" WHEN 8,
"0001100" WHEN 9,
"0000001" WHEN OTHERS;
WITH Minute1 SELECT
--Tens minute place, 0 to 6
OUTPUT_HEX3 <= "0000001" WHEN 0,
"1001111" WHEN 1,
"0010010" WHEN 2,
"0000110" WHEN 3,
"1001100" WHEN 4,
"0100100" WHEN 5,
"0100000" WHEN 6,
"0000001" WHEN OTHERS;
PROCESS(CLK)
BEGIN
IF RISING_EDGE(CLK) THEN
Count <= Count + 1;
IF (Count = 30000000) THEN
CLOCK <= NOT(CLOCK);
Count <= 1;
END IF;
END IF;
END PROCESS;
PROCESS(CLOCK)
BEGIN
IF RISING_EDGE(CLOCK) THEN
B3D0 <= BUTTON3;
B3D1 <= NOT B3D0;
B3D2 <= B3D1;
B3D3 <= B3D2;
B2D0 <= BUTTON2;
B2D1 <= NOT B2D0;
B2D2 <= B2D1;
B2D3 <= B2D2;
B3_HOLD <= B3D1 AND B3D2 AND B3D3;
B2_HOLD <= B2D1 AND B2D2 AND B2D3;
END IF;
END PROCESS;
PROCESS(CLOCK)
BEGIN
IF RESET = '1' THEN --Async Reset
State <= A_ON_OFF;
ELSIF RISING_EDGE(CLOCK) THEN
CASE State IS
---------------------------------A_ON_OFF---------------------------------
WHEN A_ON_OFF =>
--Red LED9
ON_OFF_LED <= '1';
Minute1 <= 0;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
IF (BUTTON0 = '0') THEN
ON_OFF_LED <= '0';
State <= B_INPUT;
END IF;
---------------------------------B_INPUT/PAUSE---------------------------------
WHEN B_INPUT =>
--Light up LEDs
INPUT_LED1 <= '1';
INPUT_LED2 <= '1';
INPUT_LED3 <= '1';
INPUT_LED4 <= '1';
IF (Minute1 = 6) THEN
Minute2 <= 0;
Second1 <= 0;
Second2<= 0;
State <= B_INPUT;
END IF;
--Count up button
IF (BUTTON3 = '0' AND B3_HOLD = '0') THEN
IF (Minute1 = 6 AND Minute2 >= 0) THEN
Minute1 <= 0;
Minute2 <= 1;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
ELSIF (Minute2 < 9) THEN
Minute2 <= (Minute2 + 1);
State <= B_INPUT;
ELSIF (Minute2 = 9) THEN
Minute1 <= (Minute1 + 1);
Minute2 <= 0;
State <= B_INPUT;
END IF;
END IF;
IF (BUTTON3 = '0' AND B3_HOLD = '1') THEN
IF (Minute1 = 6 AND Minute2 >= 0) THEN
Minute1 <= 0;
Minute2 <= 5;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
ELSIF (Minute2 < 5) THEN
IF (Minute2 = 0) THEN
Minute2 <= (Minute2 + 5);
State <= B_INPUT;
ELSE
Minute2 <= (Minute2 + 1);
State <= B_INPUT;
END IF;
ELSIF (Minute2 = 5) THEN
Minute2 <= 0;
Minute1 <= (Minute1 + 1);
State <= B_INPUT;
ELSIF (Minute2 > 5) THEN
IF (Minute2 = 9) THEN
Minute2 <= 0;
Minute1 <= (Minute1 + 1);
State <= B_INPUT;
ELSE
Minute2 <= (Minute2 + 1);
State <= B_INPUT;
END IF;
END IF;
END IF;
--Count down button
IF (BUTTON2 = '0' AND B2_HOLD = '0') THEN
IF ((Minute1 = 0) AND (Minute2 = 0)) THEN
Minute1 <= 6;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
ELSIF (Minute2 = 0) THEN
Minute2 <= 9;
Minute1 <= (Minute1 - 1);
ELSE
Minute2 <= (Minute2 - 1);
END IF;
State <= B_INPUT;
END IF;
IF (BUTTON2 = '0' AND B2_HOLD = '1') THEN
IF (Minute1 = 0 AND Minute2 = 0) THEN
Minute1 <= 6;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
ELSIF (Minute2 = 0 AND Minute1 > 0) THEN
Minute1 <= (Minute1 - 1);
Minute2 <= 5;
State <= B_INPUT;
ELSIF (Minute2 < 5) THEN
IF (Minute2 = 0) THEN
Minute1 <= (Minute1 - 1);
Minute2 <= 5;
State <= B_INPUT;
ELSE
Minute2 <= (Minute2 - 1);
State <= B_INPUT;
END IF;
ELSIF (Minute2 = 5) THEN
Minute2 <= (Minute2 - 5);
State <= B_INPUT;
ELSIF (Minute2 > 5) THEN
Minute2 <= (Minute2 - 1);
State <= B_INPUT;
END IF;
END IF;
--Clear button
IF (BUTTON1 = '0') THEN
Minute1 <= 0;
Minute2 <= 0;
Second1 <= 0;
Second2 <= 0;
State <= B_INPUT;
END IF;
--Start Button
IF (BUTTON0 = '0') THEN
--Turn off LEDs
INPUT_LED1 <= '0';
INPUT_LED2 <= '0';
INPUT_LED3 <= '0';
INPUT_LED4 <= '0';
State <= C_COUNTDOWN;
END IF;
---------------------------------C_COUNTDOWN---------------------------------
WHEN C_COUNTDOWN =>
IF (Second2 > 0) THEN
Second2 <= (Second2 - 1);
ELSIF (Second2 = 0) THEN
IF (Second1 > 0) THEN
Second2 <= 9;
Second1 <= (Second1 - 1);
ELSIF (Second1 = 0) THEN
IF (Minute2 > 0) THEN
Second1 <= 5;
Minute2 <= (Minute2 - 1);
IF (Second2 = 0) THEN
Second2 <= 9;
END IF;
ELSIF (Minute2 = 0) THEN
IF (Minute1 > 0) THEN
IF (Second1 = 0) THEN
Second1 <= 5;
Minute2 <= (Minute2 - 1);
IF (Second2 = 0) THEN
Second2 <= 9;
END IF;
END IF;
Minute2 <= 9;
Minute1 <= (Minute1 - 1);
ELSIF (Minute1 <= 0) THEN
State <= D_DONE;
END IF;
END IF;
END IF;
END IF;
--Reset Button
IF (BUTTON1 = '0') THEN
STATE <= A_ON_OFF;
--Input button
ELSIF (BUTTON0 = '0') THEN
STATE <= B_INPUT;
END IF;
---------------------------------D_DONE---------------------------------
WHEN D_DONE =>
--LEDR0
DONE_LED <= '1';
--Reset button
IF (BUTTON1 = '0') THEN
DONE_LED <= '0';
STATE <= A_ON_OFF;
--Input button
ELSIF (BUTTON0 = '0') THEN
DONE_LED <= '0';
STATE <= B_INPUT;
END IF;
END CASE;
END IF;
END PROCESS;
END Counter;

In choice when b_input in the case statement you'll increment minute2 for every clk button3 is low, it's an enable. It needs to be converted to an event unless your counting on a real slow clk (noting you're also producing a slow clock). This enable isn't synchronous to clk, it can cause metastability for a setup or hold time violation.
In the process
PROCESS(BUTTON3)
BEGIN
IF RISING_EDGE(BUTTON3) THEN
FF3 <= NOT(BUTTON3);
END IF;
END PROCESS;
This will assign ff3 low but never high. Rising edge means a transition from '0' to '1' on button3. In other words your driving ff3 low only.
This is why your counter doesn't change. Besides the potential metastability issue the enable should occur for a single clk.
For simulation integer range bound counters (e.g. minute2) will overflow. VHDL doesn't do range bound modular arithmetic.
signal minute2 : integer range 0 to 9;
When minute2 reaches 10 in state b_input simulation will quit because of a range error.
That increment in choice b_input should look something like:
if minute2 = 9 then
minute2 <= 0;
else
minute2 <= minute2 + 1;
end if;
(And there's a subtle hint you should simulate this thing.)
You need to use a single clk enable from the button(s) for incrementing counters.
The way to do this is a) debounce the buttons, b) detect the rising edge in the clk domain for one clk.
All this is complicated because you're using both 'clkandclock` as a clock.
A recommendation on how to implement de-bounce, edge detect and single clk enables is dependent on what your clock rate actually is.
Alternatively you could contemplate a bunch of clock ORing where you use buttons to increment things and gate clock for c_countdown.
You didn't include the context clause before the entity declaration:
library ieee;
use ieee.std_logic_1164.all;
One question, should I use Falling_Edge of button 3 for ff3 because doing that my code also had issues
It would seem likely that if you had falling edge issues you'd also have rising edge issues. The root of all problems would likely be contact bounce.
And no I don't advocate using the falling edge of button 3 in this case.
The issue here is to produce a single clock enable from button 3 (or alternatively use it as a clock). It also needs debouncing. The duration of a switch or button bounce is dependent on several things - mass of the contacts, how hard it's operated and how springy the switch arm is come to mind.
There are several ways to get rid of bounce. For instance you can use a normally open and normally closed pair of contacts to operate an RS latch, requiring two switch or button signals to be in opposite binary states. You can temporally filter (with a clock interval in the 10's of milliseconds range) requiring N number of stable samples. This also filters out metastability from going from an asynchronous domain to a synchronous (clocked) domain.
To use the equivalent of FF3 as an enable for clk, you need to debounce the button, and detect the rising edge in the 'clk` domain.
Because your buttons are almost guaranteed to be single pole switches you need some sort of temporal filtering. If the clock for that is related to 'clk' you could simply use a long interval enable produced by a counter to sample a button successively. This allows you to use an additional flip flop in the clk domain to detect it used to be low and it's now high, the output of that gate used where FF3 is used now.
If clk is 50 MHz as you say, debouncing could entail generating an enable from the Count counter.
Let's call that debounce_en.
Note this is setup to sample some time after the falling edge of button3. An old high and either one or two succesive lows. This is milliseconds after the fall of button3 so it should be safe.
50 Mhz divided by 4000000 gives a clock baud of the reciprocal of 12.5 or 8 ms. That's a good starting rate for a temporal filter for debouncing button3:
signal debounce_en: std_logic;
signal button3_d0, button3_d1, button3_d2:
begin
...
UNLABELLED1:
process(clk)
begin
if rising_edge(clk) then
debounce_en <= '0'; -- one ping only.
count <= count + 1;
if count = 4000000 then
clock <= not clock;
debounce_en <= '1'; -- for one clk every 4000000
count <= 1;
end if;
end if;
end process;
We can use debounce_en to sample button3 instead of producing FF3:
process (clk)
begin
if rising_edge(clk) and debounce_en = '1' then
button3_d0 <= button3;
button3_d1 <= button3_d0;
button3_d2 <= button3_d1;
end if;
button3_enable <= not button3_d1 and button3_d2 and debounce_en;
And the reason this would work is because more than likely 8 ms is long enough an interval to debounce one of these switches. (And if it's not add another stage and:
button3_enable <= not_button3_d1 and not button3_d2 and button3_d3 and debounce_en;
Which requires no 'ringing' be captured by three successive flip flops (30 ms).
'button3_enable would be used in place of FF3, all three (or more) of the new signals are type std_logic and the flip flops are used as a shift register.
Using a temporal filter requiring known values for so long can potentially filter out short pulses on the buttons, you'd be hard pressed to pulse a button that fast.
And as far as operating `minute2 in the case statement:
when b_input =>
if button3_enable = '1' then -- count up button
if minute2 = 9 then
minute2 <= 0;
else
minute2 <= minute2 + 1;
end if;
input_led <= '1'; --green led7
end if;
And how you were to derive debounce_en from Count might be subject to change should you change clock's clock rate (I'd be tempted to get it to run real time myself). You don't have C_COUNTDOWN finished, but it looks like ideally it would operate with a one second rate enable and have the seconds, and minutes counters cascaded.
Notes on DE1 claim of debouncing buttons
I found a DE1-SoC board manual and in figure 3-14 and section 3.6.1 it claims the use of a 74HC245 schmidt trigger buffer (nominally bidirectional, undoubtedly used unidirectionally) is sufficient to use buttons as clocks. That would depend on board layout, capacitance and inductance of one of the buttons, the size of the pull up resistors, and if they say so... (and it's likely it works, they've offered it in several generations of board designs), how does this impact the above description?
Well you still need to synchronize to clk and produce a one clk period enable. So not much.

Related

DE0 Nano LEDs consecutively on and off

Please understand my very low skill-set on the code. I am trying to learn to be better.
Using DE0 Nano board, I am trying to write VHDL to simulate all available LEDs on the board (8 of them)
I labeled them LED0 ~ LED7. Using 50 MHZ and 1/2 s counter, I wanted to operate individual LEDs in order.
For example, if these individual bits represents on and off of the LEDs.
1|0|0|0|0|0|0|0 -> 0|1|0|0|0|0|0|0 -> 0|0|1|0|0|0|0|0 and so on. At the end, counter would reset back to 0 to repeat the sequence again.
Please view my code below with these questions/issues.
1) I get one 1/2 s pause after 8th LED. Why? How do I fix this?
2) Even if i put the variable counter as 8, it repeats as 16 thus I had to implement the reset of the counter to 0. (marked as question 2 in the code)
3) Is there any better way to write these codes? It is completely messy. Could you give tips on any other function or method I can use to shorten this codes?
Please let me know if any questions!
THANKS A LOT FOR THE HELP.
entity ledtest is
port(
clk_50mhz : in std_logic ;
reset_btn : in std_logic;
green_led : out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of ledtest is
signal clk_1hz : std_logic ;
signal scaler : integer range 0 to 25000000 ;
signal counter : integer range 0 to 8;
signal LED : std_logic_vector(7 downto 0);
begin
clk_1hz_process : process( clk_50mhz , reset_btn )
begin
if (reset_btn = '0') then
clk_1hz <= '0';
scaler <= 0;
counter <= 0;
elsif(rising_edge(clk_50mhz)) then
if (scaler < 25000000) then
scaler <= scaler + 1 ;
clk_1hz <= '0';
else
scaler <= 0;
clk_1hz <= '1';
counter <= counter + 1;
if (counter >= 8) then --------question 2
counter <= 0;
end if;
end if;
end if;
end process clk_1hz_process;
blinking_process : process (clk_1hz,reset_btn)
begin
if (reset_btn = '0') then
LED(0) <= '0';
elsif rising_edge(clk_1hz) AND counter = 1 then
LED(0) <= not LED(0) ;
LED(7) <= '0' ;
elsif rising_edge(clk_1hz) AND counter = 2 then
LED(1) <= not LED(1) ;
LED(0) <= not LED(0) ;
elsif rising_edge(clk_1hz) AND counter = 3 then
LED(2) <= not LED(2) ;
LED(1) <= not LED(1) ;
elsif rising_edge(clk_1hz) AND counter = 4 then
LED(3) <= not LED(3) ;
LED(2) <= not LED(2) ;
elsif rising_edge(clk_1hz) AND counter = 5 then
LED(4) <= not LED(4) ;
LED(3) <= not LED(3) ;
elsif rising_edge(clk_1hz) AND counter = 6 then
LED(5) <= not LED(5) ;
LED(4) <= not LED(4) ;
elsif rising_edge(clk_1hz) AND counter = 7 then
LED(6) <= not LED(6) ;
LED(5) <= not LED(5) ;
elsif rising_edge(clk_1hz) AND counter = 8 then
LED(7) <= not LED(7) ;
LED(6) <= not LED(6) ;
end if;
end process blinking_process;
green_led(0) <= LED(0);
green_led(1) <= LED(1);
green_led(2) <= LED(2);
green_led(3) <= LED(3);
green_led(4) <= LED(4);
green_led(5) <= LED(5);
green_led(6) <= LED(6);
green_led(7) <= LED(7);
end behave;
If your readers squint real hard they can treat the original post as one question and two issues. (A questions is singular.)
Please view my code below with these questions/issues.
1) I get one 1/2 s pause after 8th LED. Why? How do I fix this?
There are 9 counter values (0 to 8) and only 8 LEDs (7 downto 0). No assignments occur in the half second between assigning counter to 0 and incrementing by 1 again.
2) Even if i put the variable counter as 8, it repeats as 16 thus I had to implement the reset of the counter to 0. (marked as question 2 in the code)
This issue is tied in with 1). The requirement for evaluating counter greater than or equal to 8 is caused by assigning counter to 8, again there are 9 values and only 8 LEDs. Note that's a synchronous load to 0 and not an asynchronous reset.
3) Is there any better way to write these codes? It is completely messy. Could you give tips on any other function or method I can use to shorten this codes?
Because you're attempting to go directly to FPGA instead of simulating the focus on tips should relate to the question 1) and how to fix it. There are also some synthesis issues, here gating clocks by adding enables to the conditions in if statement elsif alternatives. There's also the issue of design specification complexity and the amount of debugging effort associated with the number of lines of code.
First there are flip flops for all LED elements as well a counter. We can reduce the number of flip flops to one for each LED element by using a ring counter (not to be confused with a Johnson counter).
Assignments to green_led (the std_logic_vector) can be from LED (the std_logic_vector) instead of element by element. There's a one to one correspondence between element indices on both side of the assignment(s).
Also to allow simulation you could virtualize the time interval of a half second loaded into scalar. This has the effect of having fewer clocks represent a half second. The idea is simulation doesn't have to take the 10+ seconds of 100 million clock transitions per second (rising and falling edges).
Throw all these together and the code is changed to look like:
library ieee;
use ieee.std_logic_1164.all;
entity ledtest is
generic (half_second: integer := 24999999); -- zero identity
-- the generic allows fewer clocks per second for simulation
port (
clk_50mhz: in std_logic;
reset_btn: in std_logic;
green_led: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of ledtest is
signal clk_1hz: std_logic;
signal scaler: integer range 0 to half_second;
-- signal counter: integer range 0 to 8; -- DELETED
signal ring_counter: std_logic_vector (7 downto 0); -- ADDED
signal LED: std_logic_vector (7 downto 0);
signal LED0I: std_logic; -- ADDED
begin
LED0I <= '1' when LED = "00000000" else
'0';
clk_1hz_process:
process (clk_50mhz, reset_btn)
begin
if reset_btn = '0' then
clk_1hz <= '0';
scaler <= 0;
-- counter <= 0;
elsif rising_edge(clk_50mhz) then
if scaler /= half_second then
scaler <= scaler + 1;
clk_1hz <= '0';
else
scaler <= 0;
clk_1hz <= '1';
-- counter <= counter + 1;
-- if counter >= 8 then --------question 2
-- counter <= 0;
-- end if;
end if;
end if;
end process clk_1hz_process;
blinking_process:
process (clk_1hz, reset_btn)
begin
if reset_btn = '0' then
LED <= (others => '0');
-- LED(0) <= '0';
elsif rising_edge(clk_1hz) then
LED <= LED(6 downto 0) & (LED(7) or LED0I);
-- ring counter with a roulette ball lauch after reset
-- elsif rising_edge(clk_1hz) AND counter = 1 then
-- LED(0) <= not LED(0);
-- LED(7) <= '0';
-- elsif rising_edge(clk_1hz) AND counter = 2 then
-- LED(1) <= not LED(1);
-- LED(0) <= not LED(0);
-- elsif rising_edge(clk_1hz) AND counter = 3 then
-- LED(2) <= not LED(2);
-- LED(1) <= not LED(1);
-- elsif rising_edge(clk_1hz) AND counter = 4 then
-- LED(3) <= not LED(3);
-- LED(2) <= not LED(2);
-- elsif rising_edge(clk_1hz) AND counter = 5 then
-- LED(4) <= not LED(4);
-- LED(3) <= not LED(3);
-- elsif rising_edge(clk_1hz) AND counter = 6 then
-- LED(5) <= not LED(5);
-- LED(4) <= not LED(4);
-- elsif rising_edge(clk_1hz) AND counter = 7 then
-- LED(6) <= not LED(6);
-- LED(5) <= not LED(5);
-- elsif rising_edge(clk_1hz) AND counter = 8 then
-- LED(7) <= not LED(7);
-- LED(6) <= not LED(6);
end if;
end process blinking_process;
green_led <= led;
-- green_led(0) <= LED(0);
-- green_led(1) <= LED(1);
-- green_led(2) <= LED(2);
-- green_led(3) <= LED(3);
-- green_led(4) <= LED(4);
-- green_led(5) <= LED(5);
-- green_led(6) <= LED(6);
-- green_led(7) <= LED(7);
end architecture behave;
(Also note the default generic value scalar is reset and loaded to has been decremented to include the unity 0 in the 250,000,000 clocks be half second. The equality test for half_second is simpler than using magnitude comparison.)
Using a ring counter reduces complexity and side steps the issue of a counter range of 9.
The ring counter has a flourish added, the reset value is all '0's which are detected by signal LED0I which is used to start the ring counter after reset. It prevents all the LEDs from being lit during reset.
You can use a testbench with the number of clocks comprising a half second to a much smaller number allowing fast simulation with small waveform dump files:
library ieee;
use ieee.std_logic_1164.all;
entity ledtest_tb is
end entity;
architecture foo of ledtest_tb is
signal clk: std_logic := '0';
signal reset_btn: std_logic := '1';
signal green_led: std_logic_vector (7 downto 0);
begin
DUT:
entity work.ledtest
generic map (half_second => 7)
port map (
clk_50mhz => clk,
reset_btn => reset_btn,
green_led => green_led
);
CLOCK:
process
begin
wait for 0.5 sec / 7;
clk <= not clk;
if now > 19 sec then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 0.5 sec;
reset_btn <= '0';
wait for 0.5 sec;
reset_btn <= '1';
wait;
end process;
end architecture;
And that gives:
You could eliminate the generic map in the testbench instantiation of ledtest to demonstrate the difference in simulation time and dump file size inherent with simulating every clock transition with a 50 MHz clock. The idea here is it's easier to troubleshoot a simulation than it is to guess from what you can see (here the LEDs). Because the code description was simplified there was debugging required using the original code as a starting point. It did rely on a knowledge of digital electronics and VHDL.
The simulation was done with ghdl and gtkwave.

Signal parameter in a subprogram is not supported error

My code is about a ping pang game using VHDL and maxplus2. I can't get it complied.
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
-- use ieee.std_logic_arith.all;
entity center is
port (
clk: in std_logic;
ca: in std_logic;
cb: in std_logic;
enable: in std_logic;
a: in std_logic;
b: in std_logic;
ball: out std_logic_vector(16 downto 0);
sa: out std_ulogic;
sb: out std_ulogic;
over: inout std_ulogic
);
end center;
architecture behavior of center is
signal direction : integer range 0 to 2;
signal num : integer range -1 to 17;
begin
process (enable,ca,cb,a,b,clk)
begin
if enable = '0' then
over <= '0';
sa <= '0';
sb <= '0';
elsif enable = '1' and rising_edge(clk) then
if direction = 2 then
if ca = '1' then
direction <= 0;
num <= 1;
elsif cb = '1' then
direction <= 1;
num <= 16;
else
direction <= 2;
num <= 8;
end if;
elsif direction = 0 and num > 0 then
if b = '1' then
if num < 2 then
num <= num - 1;
direction <= 1;
else
direction <= 2;
sa <= '1' after 10 ns;
sb <= '0' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
elsif direction = 1 and num <= 16 then
if a = '1' then
if num >= 14 then
num <= num + 1;
direction <= 2;
else
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
elsif direction = 0 and num = -1 then
num <= 8;
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
elsif direction = 0 and num = -1 then
num <= 8;
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
end process;
end architecture behavior;
But I get a error:
signal parameter in a subprogram is not supported
I am confused, I don't know why I get this error.
I think as David also said you need to provide more information.
What it looks like for me is that your are writing a test bench the above code cannot be synthesized correctly. ISE will tell you that your syntax is ok but the delays are ignored IE the after keyword. The after keyword is only used in simulation.
That said i would also clean up the code there are a lot of redundancies. FX
The last two elsif statements. only one is needed. and the sensitivity list. only clk and enable should be there.
I've tried to clean up your code:
process (enable,clk)
begin
if enable = '0' then
over <= '0';
sa <= '0';
sb <= '0';
elsif rising_edge(clk) then
case( direction ) is
when 0 =>
if num > 0 then
if b = '1' then
if num < 2 then
num <= num - 1;
direction <= 1;
else
direction <= 2;
sa <= '1' after 10 ns;
sb <= '0' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
elsif num = -1 then
num <= 8;
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
when 1 =>
if num <= 16 then
if a = '1' then
if num >= 14 then
num <= num + 1;
direction <= 2;
else
direction <= 2;
sa <= '0' after 10 ns;
sb <= '1' after 10 ns;
over <= not over after 10 ns;
end if;
end if;
end if;
when 2 =>
if ca = '1' then
direction <= 0;
num <= 1;
elsif cb = '1' then
direction <= 1;
num <= 16;
else
direction <= 2;
num <= 8;
end if;
when others => NULL;
end case ;
end if;
end process;
Try and remove your after keywords and see if it will compile then.

VHDL traffic lights FSM using LPM counter: where to set/reset counter?

This one has been boggling my mind for the last two days so i've came to the internets for help.
Bit of background info first...
I'm working on a traffic lights project for uni using an Altera DE0 board. I'm a complete n00b with regards to VHDL and this first assignment was more or less a case of "here's an example of a finite state machine and an example of an LPM counter, go make some traffic lights". I think the idea's just to get a feel for using VHDL and mess about with the code to get something working.
We were given an example from a textbook (Free Range VHDL p93 iirc) on an FSM then shown how to make an LPM counter using the Megawizard Plugin Manager in Quartus and basically just had to merge/expand them. Its the first thing i've done using VHDL.
The traffic lights are supposed to be for an intersection of a major road and minor road. The default state will be major road green and minor road red. It should stay in this state until it detects a pushbutton (i.e. a car at the minor road) then go amber then red, then the minor road will go from red to green and stay in green for 10 seconds. It will stay in each other state for 1 second.
I've used 9 states (A-I) and one LPM counter and i'm just looking for a 1 in bit 26 and 29 of the "q" output(?) of the counter for the 1 and 10 second delay.
My problem is that i'm not sure where to set and reset the timer. Technically it should be reset after moving into each state then set (i.e. allowed to count) when moving to the next state.
I'll paste my code below, currently the timer_rst bits are commented out. I've tried placing them in all different lines in the code but the closest i've came to having it work is setting and resetting the timer where those commented out set and reset parts are. When i un-comment them out one at a time and run it each time it'll go from state A to B then C but after that it'll just skip to E then it moves through states so quick all the LEDs light and it seems to jump randomly through different states. Obviously this isn't how it should be done!
Can anyone help me out then?
I hope i've given a decent enough explanation here. I'll paste a link to a video of the board running my code and you can check the code out below too.
Thanks for any help provided!
--Finite state machine using DE0 board implementing a set
--of traffic tights at a major road/minor road junction.
--Major road is green until car present at minor road
--then goes to red while minor road goes to green.
--8 states, A-H. A is 'default' state
--1 sec delay: state B,C,D,F,G,H, 10 sec delay: state E,I.
--Maj Rd lights: LEDG(5 downto 3) Red/Amber/Green.
--Min Rd lights: LEDG(2 downto 0) Red/Amber/Green.
--State vector printed on LEDG(9 downto 6) in binary
--library declarations
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY lpm; --allows use of Altera LPM functions
USE lpm.all;
--entity
entity TRAFFICLIGHTS is
port(
KEY : in std_logic_vector(1 downto 0); --minor rd car present KEY(1) & reset KEY(0)-ACTIVE LOW!
CLOCK_50 : in std_logic;
LEDG : out std_logic_vector(9 downto 0); --6 lights 2 * (red/amber/green) & state vector
HEX0 : out std_LOGIC_VECTOR(7 downto 0) --display current state
);
end TRAFFICLIGHTS;
-- architecture
architecture TRAFFICLIGHTS_arch of TRAFFICLIGHTS is
type state_type is (A,B,C,D,E,F,G,H,I);
signal PS, NS : state_type;
signal timer_rst : std_logic; --wiring to delay components , one_sec, ten_sec
signal timer_q : std_logic_vector(29 downto 0); --output from timer
--LPM counter
component timer
PORT
(
aclr : IN STD_LOGIC ;
clock : IN STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (29 DOWNTO 0) --uses bit 29 for 10 secs, bit 26 for 1 sec
);
end component;
begin
--wiring up LPM counter to signals
U1 : timer
PORT MAP (
aclr => timer_rst,
clock => clock_50,
q => timer_q
);
--detects change in clock, next state or reset key press
sync_proc: process (clock_50, NS, KEY(0))
begin
if (KEY(0)='0') then --if reset pressed, return to state A
PS <= A;
elsif (rising_edge(clock_50)) then --else put present state in next state
PS <= NS;
end if;
end process sync_proc;
--detect change in present state or KEY(1) i.e. minor road car present
comb_proc: process (PS, KEY(1))
begin
case PS is
when A => --when in A: MajRd green, MinRd red, no delay
--show state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0001";
HEX0(7 downto 0) <= "10001000"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (KEY(1) = '0') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= B; --if car present #MinRd, next state is B
else NS <= A;
end if;
when B => --when in B: MajRd amber, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0010";
HEX0(7 downto 0) <= "10000011"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '1'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= C;
else NS <= B;
end if;
when C => --when in C: MajRd red, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0011";
HEX0(7 downto 0) <= "11000110"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= D;
else NS <= C;
end if;
when D => --when in D: MajRd red, MinRd red/amber, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0100";
HEX0(7 downto 0) <= "10100001"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '1'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= E;
else NS <= D;
end if;
when E => --when in E: MajRd red, MinRd green, 10 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0101";
HEX0(7 downto 0) <= "10000110"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '0'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '1'; --MinGreen
if (timer_q(29) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= F;
else NS <= E;
end if;
when F => --when in F: MajRd red, MinRd amber, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0110";
HEX0(7 downto 0) <= "10001110"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '0'; --MinRed
LEDG(1) <= '1'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= G;
else NS <= F;
end if;
when G => --when in G: MajRd red, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0111";
HEX0(7 downto 0) <= "10010000"; --display state on 7 seg
LEDG(5) <= '1'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= H;
else NS <= G;
end if;
when H => --when in H: MajRd red/amber, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "1000";
HEX0(7 downto 0) <= "10001001"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= I;
else NS <= H;
end if;
--new state allows MajRd to stay green (10 sec) if car at MinRd or not
when I => --when in I: MajRd green, MinRd red, 10 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "1001";
HEX0(7 downto 0) <= "11111001"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(29) = '1') then
--timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= C;
else NS <= A;
end if;
when others => -- the catch-all condition
PS <= A; -- if anything else, return to state A
end case;
end process comb_proc;
end TRAFFICLIGHTS_arch;
Video:
https://www.dropbox.com/s/70tkr67zdjj8pyk/File%2018-03-2015%2017%2057%2054.mov?dl=0
Tried adding intermediate states, here's the code from the case statement for the first few below. Its just starting and jumping straight to state B now and not going anywhere.
case PS is
when A => --when in A: MajRd green, MinRd red, no delay
--show state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0001";
HEX0(7 downto 0) <= "10001000"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '0'; --MajAmber
LEDG(3) <= '1'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (KEY(1) = '0') then
timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= B; --if car present #MinRd, next state is B
else NS <= A_1;
end if;
when A_1 =>
--LEDs and 7 seg same as A
LEDG(9 downto 0) <= "0001001100";
HEX0(7 downto 0) <= "10001000"; --display state on 7 seg
timer_rst <= '0'; -- allow timer to count
NS <= B;
when B => --when in B: MajRd amber, MinRd red, 1 sec delay
--print state vector using 4 bit binary 1-8
LEDG(9 downto 6) <= "0010";
HEX0(7 downto 0) <= "10000011"; --display state on 7 seg
LEDG(5) <= '0'; --MajRed
LEDG(4) <= '1'; --MajAmber
LEDG(3) <= '0'; --MajGreen
LEDG(2) <= '1'; --MinRed
LEDG(1) <= '0'; --MinAmber
LEDG(0) <= '0'; --MinGreen
if (timer_q(26) = '1') then
timer_rst <= '1'; -- reset timer
--timer_rst <= '0'; -- allow timer to count
NS <= B_1;
else NS <= B;
end if;
when B_1 =>
--LEDs and 7 seg same as B
LEDG(9 downto 0) <= "0010010100";
HEX0(7 downto 0) <= "10000011"; --display state on 7 seg
timer_rst <= '0'; -- allow timer to count
NS <= C;
Chris, check "FINITE STATE MACHINES IN HARDWARE...", V. A. Pedroni, MIT Press, page 166.

reset statement is not synthesizable since it does not hold its value under NOT(clock-edge) condition

I have searched about this problem but it all seemed Greek to me so I came here as last effort.I have the following VHDL code that I want to be implemented on an fpga.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use work.conversions.all;
entity counter is
port ( clk_in: in std_logic; --new clock
target : in std_logic_vector(7 downto 1); --Set the target with the switches (SW7-SW1)
start : in std_logic; --Start/pause (SW0)
rst : in std_logic; --Reset (BT0)
LD : out std_logic_vector(7 downto 1); --Leds show the target at binary (LD7-LD1)
LD0 : out std_logic; --LD0 indicates thw the limit has been reached
seg : out std_logic_vector(7 downto 0); --7 segment display
digit : out std_logic_vector(3 downto 0)
);
end counter;
architecture Behavioral of counter is
begin
process(clk_in,target,rst)
variable timer : natural := 0;
variable counter : natural := 0;
variable display_counter : natural range 0 to 4 := 0;
begin
LD0 <= '0';
LD <= target; --Show the target at the leds
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
<--->if(rst='1') then --Reset counter
counter := 0;
timer := 0;
digit <= "1110"; --Last digit active
seg <= "00000011"; --Show zero
LD0 <= '0';
elsif rising_edge(clk_in) then
if(start = '0') then --Pause
--counter := counter;
elsif(counter = conv_integer(unsigned(target))) then --timer limit has been reached
LD0 <= '1';
else
counter := counter + 1;
display_counter := display_counter + 1;
if(counter rem 10 = 0) then --one second has elapsed (10Hz cycle)
timer := timer + 1; --increase timer
end if;
case display_counter is --Select which digits are gonna be activated and with what
when 1 =>
seg <= int2led(timer/1000);
if(int2led(timer/1000) = "00000000") then
digit(3) <= '1';
else
digit(3) <= '0';
end if;
when 2 =>
seg <= int2led((timer/100) mod 10);
if(int2led((timer/100) mod 10) = "00000000") then
digit(2) <= '1';
else
digit(2) <= '0';
end if;
when 3 =>
seg <= int2led((timer/10) mod 10);
if(int2led((timer/10) mod 10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
when others =>
seg <= int2led(timer/10);
if(int2led(timer/10) = "00000000") then
digit(1) <= '1';
else
digit(1) <= '0';
end if;
end case;
if (display_counter = 4) then --reset the display counter from time to time
display_counter := 0;
else
display_counter := display_counter;
end if;
end if;
end if;
end process;
end Behavioral;
The problem is at if(rst='1') then. Can anyone explain to me in plain English why is this happening and a solution to it so I won't have the same kind problems again? Thanks in advance
You have default signal assignments before the if rst='1' then clause.
That means, when rst returns to 0 (in simulation) these default assignments will execute, and delete the reset values of those signals.
XST is telling you that the hardware can't actually do that.
The solution is to delete those default assignments, which will restore this process to a standard form. Then think carefully about what they were for and how to keep their functionality if you need to.
The traditional place for such assignments is immediately after the elsif rising_edge(clk) then clause, where they will be executed on every clock edge (provided Rst is low) then overridden by any other assignments that are executed yb the process.

VHDL Code for Binary Division bug

I've written code for a binary divider that takes in an 8 bit dividend, 3 bit divisor, and gives a 5 bit quotient (3 bit remainder). I've literally spent hours trying to fix a bug that gives incorrect results but I haven't been able to identify it. Any help would be GREATLY appreciated! I basically get wrong answers for my inputs but I can't figure out why. There is a bus that takes in values and on the first clock cycle where st is 1, the dividend register is loaded. On the second clock cycle after, the divisor register is loaded and the calculation is made for the next three clock cycles.
The V signal is the output to signify that an overflow has occured (the result can't be fit into the five bits of the quotient), my st is the start signal to start the process, sh is the shift signal for the shift register, su is the subtract signal for the subtractor.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity Divider is
Port (bus_in: in std_logic_vector(8 downto 0);
St, Clk, reset: in std_logic;
Quotient: out std_logic_vector(4 downto 0);
Remainder: out std_logic_vector(2 downto 0);
v: out std_logic);
end Divider;
architecture Behavioral of Divider is
signal State, NextState: integer range 0 to 5;
signal C, Ld1, Ld2, Su, Sh: std_logic;
signal Divisor: std_logic_vector(2 downto 0);
signal Subout: std_logic_vector(3 downto 0);
signal Dividend: std_logic_vector(8 downto 0);
begin
Subout <= Dividend(8 downto 5) - ('0' & divisor);
C <= not Subout (3);
Remainder <= Dividend(7 downto 5);
Quotient <= Dividend(4 downto 0);
State_Graph: process (State, St, C)
begin
Ld1 <= '0';
Ld2<='0';
v <= '0';
Sh <= '0';
Su <= '0';
case State is
when 0 =>
if (St = '1') then
Ld1 <= '1';
NextState <= 1;
else
NextState <= 0;
end if;
when 1 =>
if (St = '1') then
Ld2 <= '1';
NextState <= 2;
else
Ld2<='1';
NextState <= 2;
end if;
when 2 =>
if (C = '1') then
v <= '1';
NextState <= 0;
else
Sh <= '1';
NextState <= 3;
end if;
when 3 | 4 =>
if (C = '1') then
Su <= '1';
NextState <= State;
else
Sh <= '1';
NextState <= State + 1;
end if;
when 5 =>
if (C = '1') then
Su <= '1';
end if;
NextState <= 0;
end case;
end process State_Graph;
Update: process (Clk)
begin
if Clk'event and Clk = '1' then
State <= NextState;
--if Load = '1' then
-- Dividend <= '0' & bus_in;
--end if;
if Ld1 = '1' then
Dividend <= '0'&Bus_in(7 downto 0);
end if;
if Ld2 = '1' then
Divisor <= Bus_in(2 downto 0);
end if;
if Su = '1' then
Dividend(8 downto 5) <= Subout;
Dividend(0) <= '1';
end if;
if Sh = '1' then --94
Dividend <= Dividend(7 downto 0) & '0';
end if;
end if;
end process update;
end Behavioral;
Here's my input and outputs:
[Signals]: http://imgur.com/fqfiYJZ 1
The picture shows that my registers for the divisor and dividend is loading correctly. So I think the issue is with the actual division code. The state machine also seems to be working correctly.
Don't write this yourself. You are re-inventing the wheel.
Either write q <= a / b;
or use an IP core from your FPGA vendor.

Resources