Signal parameter in a subprogram is not supported error - vhdl

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.

Related

Testbench for FSM

I'm trying to implement a testbench for the following fsm in created in vhdl. The problem is that currently, I'm not seeing any state transitions in the test bench. The simulation stays at state 0.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity FPGA_Challenge is
Port ( led : out STD_LOGIC;
clk_in : in STD_LOGIC; -- 100 MHZ internal clock
reset : in STD_LOGIC; -- is reset necessary
button : in STD_LOGIC;
data_line : in STD_LOGIC);
end FPGA_Challenge;
architecture Behavioral of FPGA_Challenge is
type state_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20);
signal state: state_type;
signal x:std_logic;
signal y:std_logic;
signal count : integer:= 0;
--signal tmp: std_logic:= '1';
begin
process(clk_in, reset)
begin
if rising_edge(clk_in)then
if reset = '1'then -- Goes back to known state (state 0)
state <= s0;
count <= 0;
else
count <= count + 1;
case state is
-- Initial state- if button is pressed, then LED is lit and machine goes to state 2, if not it stays in state 1
when s0 =>
if (button <= '1') then
led <= '1';
state <= s1;
else
state <= s0;
led <= '0'; --is this necessary?
end if;
-- Beginning of preamble detection(states 1-17)
-- Count = ((freq in) / (freq out))/ 2 -1 = (100 MHz/ 2 MHz)/ 2 -1 = 50/2 - 1 (due to 50% duty cycle)
when s1=> -- do I need to put led = '1' in each state because it stays on ?
if (count = 25 -1) then
count <= 0;
if (data_line = '1')then
y <= '0';
-- led = '1';
state <= s2;
else
-- led = '1';
y <= '0';
state <= s1;
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s2 =>
if (count = 25-1) then
count <= 0;
if (data_line = '0')then
y <= '0';
-- led = '1';
state <= s3;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s3 =>
if (count = 25-1)then
count <= 0; ----reinitializes count
if (data_line <= '1')then
y <= '0';
-- led = '1';
state <= s4;
else
state <= s1;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s4 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s5;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s5 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s6;
else
state <= s4;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s6 =>
if (count= 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s7;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s7 =>
if (count = 25-1)then
count<= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s7;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s8 =>
if (count = 25-1)then
count <= 0;
if (data_line <='1')then
y <= '0';
-- led = '1';
state <= s9;
else
state <= s1;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s9 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s10;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s10=>
if (count = 25-1)then
count <= 0;
if (data_line <='1')then
y <= '0';
--led = '1';
state <= s11;
else
state <= s1;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s11 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s12;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s12 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
--led = '1';
state <= s13;
else
state <= s2;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s13 =>
if (count = 25-1)then
count <= 0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s14;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s14 =>
if (count = 25-1)then
count <=0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s15;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s15 =>
if (count = 25-1)then
count <=0;
if (data_line <='0') then
y <= '0';
-- led = '1';
state <= s16;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s16 =>
if (count = 25-1) then
count <= 0;
if (data_line <='0')then
y <= '0';
-- led = '1';
state <= s17;
else
state <= s2;
y <= '0';
-- led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s17 =>
if (count = 25-1)then
count <= 0;
if (data_line ='1')then
y <= '1';
-- led = '1';
state <= s18;
else
state <= s1;
y <= '0';
--led = '1';
end if;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when s18 => -- no real condition here except varying period of clock
if (count = 25)then
count <= 0; ----reinitializes count
state <= s19;
else
count <= count + 1;
end if;
-- clock_out <= tmp;
when s19=> -- no real condition here except varying period of clock
if (count = 25)then
count <= 0; ----reinitializes count
state <= s0;
else
count <= count + 1;
end if;
--clock_out <= tmp;
when others=>
null;
end case;
end if;
end if;
end process;
end architecture;
The following is the testbench I have so far. I have internal signals such as y(output for each state), and count(counter for how long I'm in a state) that I probably should be using as drivers in the testbench. Any input is appreciated
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity FPGA_tb is
-- Port ( );
end FPGA_tb;
architecture Behavioral of FPGA_tb is
component FPGA_Challenge is
Port( led : out STD_LOGIC;
clk_in : in STD_LOGIC; -- 100 MHZ internal clock
reset : in STD_LOGIC; -- is reset necessary
button : in STD_LOGIC;
data_line : in STD_LOGIC);
end component;
signal led : STD_LOGIC;
signal clk_in : STD_LOGIC; -- 100 MHZ internal clock
signal reset : STD_LOGIC; -- is reset necessary
signal button : STD_LOGIC;
signal data_line : STD_LOGIC;
type state_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20);
signal state: state_type;
signal x,y: std_logic;
signal count : integer:= 0;
begin
UUT: FPGA_Challenge
PORT MAP(
led => led,
clk_in => clk_in,
reset => reset,
button => button,
data_line => data_line
);
Testing: Process
begin
--wait until rising_edge(clk_in);
--wait until rising_edge(clk_in);
clk_in <='0';
reset <= '1';
button <= '0';
data_line <= '0';
WAIT For 10ns;
clk_in <='1';
reset <= '0';
button <= '1';
data_line <= '0';
WAIT For 10ns;
clk_in <='1';
reset <= '1';
button <= '0';
data_line <= '1';
WAIT For 10ns;
clk_in <='0';
reset <= '1';
button <= '0';
data_line <= '0';
WAIT For 10ns;
clk_in <='1';
reset <= '1';
button <= '0';
data_line <= '0';
WAIT For 10ns;
end process;
end Behavioral;
Try this in the testbench to have a running clock and proper reset
signal clk_in : STD_LOGIC := '1'; -- 100 MHZ internal clock
signal reset : STD_LOGIC := '1'; -- is reset necessary
clk_in <=NOT clk_in after 10ns;
reset <= 0 after 30ns;
play with button after the reset. that is, from 40ns

How to switch between datasamples in VHDL?

I have written a code for my I2S interface. this interface has a PISO function (parallel in and serial out). In my testbench, I've added 2 x 24 bits datasamples (left / right channel). Now I would like to switch between this sample and the new second sample (something like: Left1, Right1 , Left2, Right2 , Left1, Right1).
elsif rising_edge(BCLK) then
PDL_BUF <= PDL1;
PDR_BUF <= PDR1;
READY <= '1';
VALID <= '1';
bitcounter := bitcounter + 1;
if bitcounter = 1 then
WSP <= '1';
else
WSP <= '0';
end if;
if bitcounter >= 0 and bitcounter <= 23 then
WS <= '0';
elsif bitcounter > 24 then -- and bitcounter <= 48
WS <= '1';
WSP <= '0';
end if;
if WS = '0' then
SD <= PDL_BUF(23);
PDL_BUF <= PDL_BUF(22 downto 0) & '0';
else --if WS = '1' then
SD <= PDR_BUF(23);
PDR_BUF <= PDR_BUF(22 downto 0) & '0';
end if;
if bitcounter = 48 then
bitcounter := 0;
end if;
end if;
end process;
this is a block that is repeated twice for two channels, it is clear that you can't access the other channel in that.
you need to add a block let's call it a merging block.
in merging block consider both samples as input then you can have both of them in your code.

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

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.

vhdl manual clock hour set

I am trying to make an alarm clock for a final project in one of my classes. I am using push buttons on a DE1 Altera board to manually increment hours and mins. The mins work but I can not get the hours to increment manually. All pin assignments are correct.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity ClkMain is port (
clk,pb_hr,pb_min,clk_set,almr_enbl: in std_logic;
almr_hr: in integer range 0 to 23;
almr_min: in integer range 0 to 59;
clk_min : out integer range 0 to 59;
clk_hr : out integer range 0 to 23;
almr_indct : out bit
);
end ClkMain;
architecture Behavioral of ClkMain is
signal sec, min: integer range 0 to 60 :=0;
signal hr: integer range 0 to 24 := 0;
begin
clk_min <= min;
clk_hr <= hr;
process(clk) --normal clock operation
begin
if(clk'event and clk='1') then
sec <= sec + 1;
if(sec + 1 = 60 or (pb_min = '1' and clk_set = '1') ) then
sec <= 0;
min <= min + 1;
if (min + 1 = almr_min and hr = almr_hr and almr_enbl = '1') then
almr_indct <= '1';
else
almr_indct <= '0';
end if;
if(min + 1 = 60 ) then
hr <= hr + 1;
min <= 0;
if(hr + 1 = 24) then
hr <= 0;
if (clk'event and clk='1' and pb_hr = '1' and clk_set = '1')then
hr <= hr + 1;
end if;
end if;
end if;
end if;
end if;
end process;
end Behavioral;
You can see where the error is by indenting properly:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_arith.all;
-- use ieee.std_logic_unsigned.all;
entity ClkMain is
port (
clk,pb_hr,pb_min,clk_set,almr_enbl: in std_logic;
almr_hr: in integer range 0 to 23;
almr_min: in integer range 0 to 59;
clk_min: out integer range 0 to 59;
clk_hr: out integer range 0 to 23;
almr_indct : out bit
);
end ClkMain;
architecture Behavioral of ClkMain is
signal sec, min: integer range 0 to 60 :=0;
signal hr: integer range 0 to 24 := 0;
begin
clk_min <= min;
clk_hr <= hr;
process(clk) --normal clock operation
begin
if clk'event and clk = '1' then
sec <= sec + 1;
if sec + 1 = 60 or (pb_min = '1' and clk_set = '1') then
sec <= 0;
min <= min + 1;
if min + 1 = almr_min and hr = almr_hr and almr_enbl = '1' then
almr_indct <= '1';
else
almr_indct <= '0';
end if;
if min + 1 = 60 then
hr <= hr + 1;
min <= 0;
if hr + 1 = 24 then
hr <= 0;
if clk'event and clk = '1' and pb_hr = '1' and clk_set = '1' then
hr <= hr + 1;
end if;
end if;
end if;
end if;
end if;
end process;
end Behavioral;
The clk condition is enclosed in the outermost if statement and isn't necessary:
if clk'event and clk = '1' and pb_hr = '1' and clk_set = '1' then
Should be
if pb_hr = '1' and clk_set = '1' then
And that brings us to what's wrong. pb_hr is only evaluated at 11 PM:
if hr + 1 = 24 then
hr <= 0;
if pb_hr = '1' and clk_set = '1' then
hr <= hr + 1;
end if;
end if;
At a minimum these two if statements need to be at the same nesting level.
Unfortunately it also makes you take a look up the if statement nesting levels where you notice you can only set hours at 23:59:59, or you're also holding down pb_min and clk_set is true.
Also notice you almr_indct is true for a minute no matter what you do. I'd suggest moving the sets and alarm detection outside the enclosing if statement with the clock condition (keep them in the same process). It should also be invalidated when clk_set is true.
Looking even further back:
if sec + 1 = 60 or (pb_min = '1' and clk_set = '1') then
sec <= 0;
min <= min + 1;
We see you could reach 60 for a button push. That all needs to be fixed. It's also possible to move the alarm comparison outside of the counters and disable during clock set.
So you could manipulate the process statement:
architecture foo of clkmain is
signal sec, min: integer range 0 to 59 := 0;
signal hr: integer range 0 to 23 := 0;
signal sec_neq_59: std_logic;
signal min_neq_59: std_logic;
signal hr_neq_23: std_logic;
begin
clk_min <= min;
clk_hr <= hr;
sec_neq_59 <= '0' when sec = 59 else '1';
min_neq_59 <= '0' when min = 59 else '1';
hr_neq_23 <= '0' when hr = 23 else '1';
CLOCK_PROCESS:
process(clk)
begin
if clk'event and clk = '1' then
ALARM_INDICATON:
if min = almr_min and hr = almr_hr and almr_enbl = '1' then
almr_indct <= to_bit(not clk_set);
else
almr_indct <= '0';
end if;
SET_MINUTES:
if pb_min = '1' and clk_set = '1' then
if min_neq_59 = '1' then
min <= min + 1;
else
min <= 0;
end if;
SET_HOURS:
elsif pb_hr = '1' and clk_set = '1' then
if hr_neq_23 = '1' then
hr <= hr + 1;
else
hr <= 0;
end if;
INCREMENT_SECONDS:
elsif sec_neq_59 = '1' then
sec <= sec + 1;
else -- sec = 59
sec <= 0;
INCREMENT_MINUTES:
if min_neq_59 = '1' then
min <= min + 1;
else -- :59:59
min <= 0;
INCREMENT_HOURS:
if hr_neq_23 = '1' then
hr <= hr + 1;
else -- 23:59:59
hr <= 0;
end if;
end if;
end if;
end if;
end process;
end architecture foo;
And with the opportunity I fixed the range for the sec, min and hr counters. The secret is evaluating before incrementing, you intercept a terminal count with a synchronous load.
Also switched to equality comparisons to specific values, separated them to reduce hardware by having one set and prioritized the push buttons over the clock operation by using elsif.
So now push buttons can't cause range errors in minutes and hours, and are independent of actual clock time.
I don't think it's valid to reset seconds when incrementing minutes with the push button. It might be valid to keep seconds at 0 while clock_set is true, which would stop the clock from running when being set. That doesn't work if you're only fixing daylight savings time or changing time zones, though.
I haven't simulated this. It analyzes and elaborates. Range errors in assignment would show up during simulation.
I left almr_indct as type bit, but did use clk_set as a condition for the alarm indication.

Vhdl rising_edge statement not synthesizable

I am writing a little program for use on my Zybo FPGA, its supposedly a variable frequency divider with 10 different steps.
However on the last line when I try to output my clock to an LED for testing purposes it gives me this error: Line 137: statement is not synthesizable since it does not hold its value under NOT(clock-edge) condition
Here is my code
entity StappenMotor is
Port ( Reset, CLK : in STD_LOGIC;
X1, X2 : in STD_LOGIC;
Z1 : out STD_LOGIC);
end StappenMotor;
architecture Behavioral of StappenMotor is
signal speed : integer := 0;
signal puls : STD_LOGIC;
begin
speed_proc: process(X1, X2) is
begin
if (rising_edge(X1) and speed < 10) then
speed <= speed + 1;
elsif (rising_edge(X2) and speed > 0) then
speed <= speed - 1;
end if;
end process speed_proc;
freq_proc: process(CLK) is
variable int : integer := 0;
begin
if rising_edge(CLK) then
int := int + 1;
end if;
case speed is
when 0 =>
if int = 250000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 1 =>
if int = 200000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 2 =>
if int = 175000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 3 =>
if int = 150000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 4 =>
if int = 125000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 5 =>
if int = 100000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 6 =>
if int = 75000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 7 =>
if int = 62500000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 8 =>
if int = 50000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 9 =>
if int = 35000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when 10 =>
if int = 25000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
when others =>
if int = 10000000 then
puls <= '1';
int := 0;
else puls <= '0';
end if;
end case;
end process freq_proc;
test: process(puls) is
begin
if rising_edge(puls) then
Z1 <= '1';
else Z1 <= '0';
end if;
end process test;
end Behavioral;
Error occurs on the line:
if rising_edge(puls) then
Anyone got a clue?
Kind regards.
All of your processes have some issues, though the compiler may not complain about them as loudly as the one in test.
In speed_proc, you are qualifying rising_edge() with an additional comparison. I would recommend nesting if statements instead (put the comparison if inside the rising_edge() if). You're also trying to clock the same register with 2 separate clocks. You probably need to find a different way to do this.
In freq_proc, only your variable increment is inside the rising_edge() check - I don't see a reason not to put the rest in as well. It's more standard, and it should generally lead to fewer unexpected problems.
In test, as #Chiggs mentioned, what you're trying to accomplish is invalid. If you want to toggle Z1 every clock cycle, you can do:
if rising_edge(puls) then
Z1 <= not Z1;
end if;
(For simulation, you'd need to initialize Z1 to see a valid output.)
The problem is the whole test process, not just the single line you've mentioned.
test: process(puls) is
begin
if rising_edge(puls) then
Z1 <= '1';
else Z1 <= '0';
end if;
end process test;
If you think about what you've described here, you're asking to drive Z1 high whenever there's a rising edge on the clock and drive it low whenever puls changes but isn't a rising edge (which includes Z->1, 1->0, Z->0 transitions).
This generally isn't possible in an FPGA and therefore is not synthesisable, hence the tool complaining.

Resources