A ppp Finite State Machine Implementation Using VHDL - vhdl

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity fsm is
Port ( clock : in STD_LOGIC;
P : in STD_LOGIC_VECTOR(4 downto 0);
reset : in STD_LOGIC;
State : out STRING);
end fsm;
architecture Behavioral of fsm is
TYPE State_type IS (Initial, Starting,Closed,Closing,Stopped,Stopping,Req_sent,Opened,Ack_sent,Ack_rcvd); -- Define the states
SIGNAL State : State_Type; -- Create a signal that begin
begin
PROCESS (clock,reset)
BEGIN
If (reset = "1") THEN
State <= Initial;
ELSE IF rising_edge(clock) THEN -- if there is a rising edge
-- clock, then do the stuff below
-- The CASE statement checks the value of the State
-- and based on the value and any other control signals, --change s to a new state.
CASE State IS
WHEN Initial =>
IF P="00000" THEN
State <= Closed;
ELSIF P="00010" THEN
State<=Starting;
ELSIF P="00011" THEN
State<=Initial ;
END IF;
WHEN Starting =>
IF P <="00000" THEN
State <= Req_sent;
ELSIF P <="00010" THEN
State<=Starting;
END IF;
WHEN Closed =>
IF P <="00010" THEN
State <= Req_sent;
ELSIF P <="00001" THEN
State<=Initial;
ELSIF P <="00100" THEN
State<=Closed;
END IF;
WHEN Stopped=>
IF P <="00110" THEN
State <= Stopped;
ELSIF P <="00011" THEN
State <=Closed ;
ELSIF P <="00001" THEN
State<=Starting;
ELSIF P <="01101" THEN
State<=Req_sent;
ELSIF P <="01100" THEN
State<=Ack_sent;
END IF;
WHEN Closing =>
IF P <="00101" THEN
State <= Closing;
ELSIF P <="00001" THEN
State<=Initial;
ELSIF P <="01110" THEN
State<=Closed;
ELSIF P <="00010" THEN
State<=Stopping;
END IF;
WHEN Req_sent=>
IF P <="01001" THEN
State<=Req_sent;
ELSIF P <="01101" THEN
State<=Opened;
ELSIF P <="01100" THEN
State<=Ack_sent;
ELSIF P <="10000" THEN
State<=Ack_rcvd;
ELSIF P <="10011" THEN
State<=Stopped;
ELSIF P <="00001" THEN
State<=Starting;
ELSIF P <="00011" THEN
State<=Closing;
END IF;
WHEN Stopping=>
IF P <="00111" THEN
State<=Stopping;
ELSIF P <="00011" THEN
State<=Closing;
ELSIF P <="01110" THEN
State<=Stopped;
ELSIF P <="00001" THEN
State<=Starting;
END IF;
WHEN Opened=>
IF P <="01000" THEN
State<=Opened;
ELSIF P <="00001" THEN
State<=Starting;
ELSIF P <="00011" THEN
State<=Closing;
ELSIF P <="01111" THEN
State<=Stopping;
ELSIF P <="01100" THEN
State<=Ack_sent;
END IF;
WHEN Ack_sent=>
IF P <="01010" THEN
State<=Ack_sent;
ELSIF P <="00011" THEN
State<=Closing;
ELSIF P <="10000" THEN
State<=Opened;
ELSIF P <="10010" THEN
State<=Red_sent;
ELSIF P <="00001" THEN
State<=Starting;
ELSIF P <="10011" THEN
State<=Stopped;
END IF;
WHEN Ack_rcvd=>
IF P <="01011" THEN
State<=Ack_rcvd;
ELSIF P <="10000" THEN
State<=Opened;
ELSIF P <="00011" THEN
State<=Closing;
ELSIF P <="10001" THEN
State<=Req_sent;
ELSIF P="10011" THEN
State<=Stopped;
ELSIF P <="00001" THEN
State<=Starting;
END IF;
END CASE;
END IF;
END PROCESS;
end Behavioral;
please help me figure out the error in this code.Have been trying for hours
ERROR:HDLCompiler:806 - "C:/.Xilinx/fsm/fsm.vhd" Line 184: Syntax error near "PROCESS".

There are several errors.
Your internal signal State is a duplicate name of the entity signal State
Your check for reset uses "1", when it should be '1'
Your use of Red_sent instead of Req_sent
But the problem which is causing you the error message, is that you use ELSE IF instead of ELSIF.

Related

Creating strings for lcd-data

I want to create dynamic string array, so I can transmit it to the lcd module on my Altera DE2-115 board. So far the most part is working, but the last part is not wrking in the following code:
CREATE_STRING: PROCESS (CLK, RESET, X)
BEGIN
IF RESET = '1' THEN
FOR i IN 0 TO 31 LOOP
lcd_data(i) <= x"30";
END LOOP;
END IF;
IF X /= 0 THEN
FOR i IN 0 TO 15 LOOP
IF X(15-i) = '0' THEN
lcd_data(i) <= x"30";
END IF;
IF X(15-i) ='1' THEN
lcd_data(i) <= x"31";
END IF;
END LOOP;
END IF;
IF char_count > 15 AND lcd_y = '1' THEN
ELSIF CLK = '1' AND CLK'event THEN
lcd_data(to_integer(char_count)) <= x"31";
END IF;
END PROCESS CREATE_STRING;
I'm getting this error message:
Error (10818): Can't infer register for "lcd_data[31][0]" at seqdec.vhd(75) because it does not hold its value outside the clock edge
for every lcd_data[31][x].
I googled the error and if I am not completly on the wrong thought I think i understood it, but I'm still not able the get it right...
Would be great if somebody could help with advice.
Best regards
Adrian
Did this change:
CREATE_STRING: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
FOR i IN 0 TO 31 LOOP
lcd_data(i) <= x"30";
END LOOP;
ELSIF CLK = '1' AND CLK'event THEN
IF X /= 0 THEN
FOR i IN 0 TO 15 LOOP
IF X(15-i) = '0' THEN
lcd_data(i) <= x"30";
END IF;
IF X(15-i) ='1' THEN
lcd_data(i) <= x"31";
END IF;
END LOOP;
END IF;
ELSIF lcd_y = '1' THEN
lcd_data(to_integer(pos_count)) <= x"31";
END IF;
END PROCESS CREATE_STRING;
But still the same problem.
To properly describe a register, you must reverse the order of the if statements as follows:
CREATE_STRING: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
FOR i IN 0 TO 31 LOOP
lcd_data(i) <= x"30";
END LOOP;
ELSIF CLK = '1' AND CLK'event THEN
IF X /= 0 THEN
FOR i IN 0 TO 15 LOOP
IF X(15-i) = '0' THEN
lcd_data(i) <= x"30";
END IF;
IF X(15-i) ='1' THEN
lcd_data(i) <= x"31";
END IF;
END LOOP;
END IF;
IF char_count > 15 AND lcd_y = '1' THEN
lcd_data(to_integer(char_count)) <= x"31";
END IF;
END IF;
END PROCESS CREATE_STRING;

Is it legal to have an independent if-clause for the D flip-flop reset in VHDL?

I have the following code describing some registers:
DCR_WR_REGS_P: process (CLK)
begin
if rising_edge(CLK) then
if DCR_WRITE = '1' then
if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
case to_integer(unsigned(DCR_ABUS(7 to 9))) is
when REG_DMA_RD_ADDR_OFFS =>
dma_rd_addr_reg <= DCR_WR_DBUS (0 to DMA_RD_ADDR_SZ-1);
when REG_DMA_RD_LENG_OFFS =>
dma_rd_leng_reg <= DCR_WR_DBUS (0 to DMA_RD_LENG_SZ-1);
rd_dma_req <= '1';
-- more registers here...
when
when
----------------------
when others =>
end case;
end if;
else
if clear_rd_dma_req='1' then
rd_dma_req <='0';
end if;
end if;
end if;
end process DCR_WR_REGS_P;
This code works except for the fact that the clear_rd_dma_req is ignored when DCR_WRITE is active. So, can I somehow make the "if clear_rd_dma_req='1'" clause an independent one? I realize that I can create a separate process just for the rd_dma_req bit, but I am trying to avoid that as I have a few bits like that.
Here's a version with a separate process:
DCR_WR_REGS_P: process (CLK)
begin
if rising_edge(CLK) then
if DCR_WRITE = '1' then
if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
case to_integer(unsigned(DCR_ABUS(7 to 9))) is
when REG_DMA_RD_ADDR_OFFS =>
dma_rd_addr_reg <= DCR_WR_DBUS (0 to DMA_RD_ADDR_SZ-1);
when REG_DMA_RD_LENG_OFFS =>
dma_rd_leng_reg <= DCR_WR_DBUS (0 to DMA_RD_LENG_SZ-1);
-- more registers here...
when
when
----------------------
when others =>
end case;
end if;
end if;
end if;
end process DCR_WR_REGS_P;
RD_DMA_REQ_P: process (CLK)
begin
if rising_edge(CLK) then
if clear_rd_dma_req='1' then
rd_dma_req <='0';
elsif DCR_WRITE = '1' then
if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
if to_integer(unsigned(DCR_ABUS(7 to 9))) = REG_DMA_RD_LENG_OFFS then
rd_dma_req <= '1';
end if;
end if;
end if;
end if;
end process RD_DMA_REQ_P;
And here's a version with an independent if-clause, which is probably illegal:
DCR_WR_REGS_P: process (CLK)
begin
if rising_edge(CLK) then
if DCR_WRITE = '1' then
if C_BASEADDR(0 to 6) = DCR_ABUS(0 to 6) then
case to_integer(unsigned(DCR_ABUS(7 to 9))) is
when REG_DMA_RD_ADDR_OFFS =>
dma_rd_addr_reg <= DCR_WR_DBUS (0 to DMA_RD_ADDR_SZ-1);
when REG_DMA_RD_LENG_OFFS =>
dma_rd_leng_reg <= DCR_WR_DBUS (0 to DMA_RD_LENG_SZ-1);
rd_dma_req <= '1';
-- more registers here...
when
when
----------------------
when others =>
end case;
end if;
end if;
if clear_rd_dma_req='1' then
rd_dma_req <='0';
end if;
end if;
end process DCR_WR_REGS_P;
Thanks
Yes you can make it an independent one (still inside the if rising_edge(clk) statement). What makes you think this version (last in the modified question) should be illegal?
Anything it does will override assignments made to the same signals by the if DCR_Write statement, thanks to the "last assignment wins" rule.
HOWEVER why not simply reverse the prioritisation and tidy it up, like this?
if clear_rd_dma_req='1' then
...
elsif DCR_Write = '1' then
...
end if;

Simplifying A State Machine To Reduce Logic Levels and Meet Timing

My design at the moment isn't meeting timing. I've tried putting it on a slower clock and pipelining the inputs/outputs. The problem is always the same - too many levels of logic. Have any of you got any tips on making this logic more clock friendly?
signal ctr : std_logic_vector(9 downto 0);
signal sig_bit_shift : std_logic_vector (15 downto 0);
begin
process(clk_p)
begin
if rising_edge(clk_p) then
if rst_i = '1' or nuke = '1' then
ctr <= (others => '0');
state <= ST_IDLE;
elsif unsigned(event_settings) < 1 then -- disables
state <= ST_IDLE;
elsif unsigned(event_settings) = 1 then -- always on
state <= ST_ENABLE;
else
case state is
when ST_IDLE =>
if ctr = (unsigned(event)-2) then
state <= ST_ENABLE;
elsif unsigned(ctr) = 1 and sig = '0' then --catches first word
state <= ST_ENABLE;
elsif sig = '1' then
ctr <= ctr + 1;
end if;
when ST_ENABLE =>
if s_sig = '1' then
state <= ST_IDLE;
if unsigned(s_evt) > 1 then
ctr <= (others => '0');
end if;
end if;
end case;
end if;
end if;
end process;
UPDATE:
process(clk_p)
begin
if rising_edge(clk_p) then
if rst_i = '1' or nuke = '1' then
ctr <= x"00" & "10";
state <= ST_IDLE;
elsif settings = '1' then
case state is
when ST_IDLE =>
if ctr = (unsigned(event)) then
state <= ST_ENABLE;
elsif unsigned(ctr) = 1 and sig = '0' then --catches first word -- this is the part which when added, fails timing
state <= ST_ENABLE;
elsif sig = '1' then
ctr <= ctr + 1;
end if;
when ST_ENABLE =>
if s_sig = '1' then
state <= ST_IDLE;
if unsigned(s_evt) > 1 then
ctr <= X"00" & "10";
end if;
end if;
end case;
end if;
end if;
end process;
I think too it's slowed down by where the signal comes from:
sig <= sig_token when unsigned(SIG_DELAY) < 1 else (sig_bit_shift(to_integer(unsigned(SIG_DELAY)-1)));
process(clk_p) -- delays sig
begin
if rising_edge(clk_p) then
if rst = '1' then
sig_bit_shift <= (others => '0');
else
sig_bit_shift <= l1a_bit_shift(sig_bit_shift'high-1 downto 0) & sig_token;
end if;
end if;
end process;
UPDATE 2 :
Seems like half the routing went into the above delay so i'm going to try and fix with this:
signal sig_del_en : std_logic;
signal sig_del_sel : integer;
begin
process(clk_p)
begin
if rising_edge(clk_p) then
if unsigned(SIG_DELAY) = 0 then
sig_del_en <= '0';
else
sig_del_en <= '1';
end if;
sig_del_sel <= to_integer(unsigned(SIG_DELAY)-1);
end if;
end process;
sig <= sig_token when sig_del_en = '0' else (sig_bit_shift(sig_del_sel));
Some of the "slow" operations are array = which requires compare over all bits in the argument, and < and > which requires subtraction over all bits in the argument. So you may improve timing in a cycle, if there is sufficient time in the previous cycle to generate the compare result up front as a std_logic. It may be relevant for these:
unsigned(event_settings) < 1
unsigned(event_settings) = 1
ctr = (unsigned(event)-2)
unsigned(ctr) = 1
unsigned(s_evt) > 1
The code to generate the different std_logic values depends on the way the related signal is generated, but an example can be:
process (clk) is
variable event_settings_v : event_settings'range;
begin
if rising_edge(clk) then
...
event_settings_v := ... code for generating event_settings; -- Variable with value
event_settings <= event_settings_v; -- Signal drive from variable
if unsigned(event_settings_v) < 1 then
unsigned_event_settings_tl_1 <= '1';
else
unsigned_event_settings_tl_1 <= '0';
end if;
end if;
end process;
The code unsigned(event_settings) < 1 in the state machine can then be changed to unsigned_event_settings_tl_1 = '1', which may improve timing if this compare is in the critical path.
Using the asynchronous reset typically available on the the flip-flop for rst_i = '1' may also improve timing, since it removes logic from the synchronous part. It is unlikely to give a significant improvement, but it's typically a good design practice in order to maximize the time for synchronous logic. The asynchronous reset is used through coding style like:
process (rst_i, clk_p) is
begin
if rst_i = '1' then
... Apply asynchronous reset value to signals
elsif rising_edge(clk_p) then
... Synchronous update of signals

Addition of 2 numbers from keyboard using spartan 3 (vhdl)

My task is to take 2 inputs from keyboard which is numbers from 0 to 9 and to add them. Problem is in
STORING these numbers.i want to save first press(input no.) into "a" and second press(input no.) into
"b" but by using following code first press stores in both a and b. 2nd press is of no use. here
scan_code = scancode of the pressed button (output of keyboard interfacing code)
a = number in binary (for example if first time i press "1" then the code check the scancode and assign the binary value of "1" to a).
Any one who can help?
process (clk, scan_code, cin)
variable scancode1 : std_logic_vector (7 downto 0) := "00000000";
variable cin2 : std_logic_vector(2 downto 0);
begin
if(clk'event and clk = '1') then
scancode1 := scan_code;
a <= "0000";
b <="0000";
if (scancode1 = "00010110") then
a <= "0001";
elsif (scancode1 = "00011110") then
a <="0010";
elsif (scancode1 = "00100110") then
a <="0011";
elsif (scancode1 = "00100101") then
a <="0100";
elsif (scancode1 = "00101110") then
a <="0101";
elsif(scancode1 = "00110110") then
a <="0110";
elsif (scancode1 = "00111101") then
a <="0111";
elsif (scancode1 = "00111110") then
a <="1000";
elsif (scancode1 = "01000110") then
a <="1001";
elsif (scancode1 = "01000101") then
a <="0000";
end if;
if (scancode1 = "01010101") then --scancode for + sign
a <=a;
end if;
if (scancode1 = "00010110") then
b <="0001";
elsif (scancode1 = "00011110") then
b <="0010";
elsif (scancode1 = "00100110") then
b <="0011";
elsif (scancode1 = "00100101") then
b <="0100";
elsif (scancode1 = "00101110") then
b <="0101";
elsif(scancode1 = "00110110") then
b <="0110";
elsif (scancode1 = "00111101") then
b <="0111";
elsif (scancode1 = "00111110") then
b <="1000";
elsif (scancode1 = "01000110") then
b <="1001";
elsif (scancode1 = "01000101") then
b <="0000";
end if;
sum(0) <= a(0) xor b(0) xor cin;
cin2(0) := (a(0) and b(0)) or (cin and (a(0) xor b(0)));
sum(1) <= a(1) xor b(1) xor cin2(0);
cin2(1) := (a(1) and b(1)) or (cin2(0) and (a(1) xor b(1)));
sum(2) <= a(2) xor b(2) xor cin2(1);
cin2(2) := (a(2) and b(2)) or (cin2(1) and (a(2) xor b(2)));
sum(3) <= a(3) xor b(3) xor cin2(2);
cout <= (a(3) and b(3)) or (cin2(2) and (a(3) xor b(3)));
end if;
end process;
"a" and "b" are updating at the same time as you wrote it like that (same "scancodes" are checked for "a" and "b" on the same clockedge). think about using an event trigger like in the following example:
...
if reset='1' then
a<=(others => '0');
b<=(others => '0');
event_last<='0';
event_nr<=0;
elsif rising_edge(clk) then
event_last<=event;
-- trigger on "rising edge" of event
if event='1' and event_last='0' then
case event_nr is
-- first event is "a"
when 0 =>
event_nr<=1;
if (scancode1 = "00010110") then
a <= "0001";
...
-- second event is "b"
when others =>
event_nr<=0;
if (scancode1 = "00010110") then
b <= "0001";
...
end case;
...
...

HDL sythesis complains about missing signals in sensitivity list

Hello I've got this simple VHDL process (Generated from MyHDL code):
DIGIPOT_CONTROLLER_CONNECTCLOCK: process (delayedClock) is
begin
if to_boolean(clkEn) then
if to_boolean(delayedClock) then
scl_d <= '0';
else
scl_d <= 'Z';
end if;
else
if to_boolean(sclIdleValue) then
scl_d <= 'Z';
else
scl_d <= '0';
end if;
end if;
end process DIGIPOT_CONTROLLER_CONNECTCLOCK;
Original MyHDL code:
#always(delayedClock)
def connectClock():
if(clkEn):
if(delayedClock):
scl_d.next = False
else:
scl_d.next = None
else:
if(sclIdleValue):
scl_d.next = None
else:
scl_d.next = False
In simulation it works perfectly(both ISIM and MyHDL simulator), but when I try to synthesise it into Spartan 6 it gives these warnings:
clken should be on the sensitivity list of the process
sclidlevalue should be on the sensitivity list of the process
Which I understand that it somehow inferred that this process should be sensitive on clkEn and sclIdleValue signals. But of course this is not what I have intended.
I want it to change output only when delayedClock changes it's state, not when clkEn or sclIdleValue changes their respective states.
Is it something that could not be done in Spartan 6 architecture? Or should I decribe process otherwise to have my intended behavior?
I have finally figured it out this is resulting MyHDL code:
#always(delayedClock.posedge, reset.posedge)
def connectClock():
if(reset == 1):
delayedClock_int.next = True
else:
delayedClock_int.next = not delayedClock_int
if(clkEn):
if(delayedClock_int):
scl_d.next = False
else:
scl_d.next = None
else:
if(sclIdleValue):
scl_d.next = None
else:
scl_d.next = False
and (generated) VHDL:
DIGIPOT_CONTROLLER_CONNECTCLOCK: process (delayedClock, reset) is
begin
if (reset = '1') then
delayedClock_int <= '1';
elsif rising_edge(delayedClock) then
delayedClock_int <= to_std_logic((not to_boolean(delayedClock_int)));
if to_boolean(clkEn) then
if to_boolean(delayedClock_int) then
scl_d <= '0';
else
scl_d <= 'Z';
end if;
else
if to_boolean(sclIdleValue) then
scl_d <= 'Z';
else
scl_d <= '0';
end if;
end if;
end if;
end process DIGIPOT_CONTROLLER_CONNECTCLOCK;
I had to make delayed clock twice the frequency (and then divide it by two in my connectClock process), this way it produces the same result as original process and it is sythesisable without warning.. the reason for phased out clock is SCL of I2C waveform as shown here:

Resources