200 likes | 422 Views
Converting a Finite State Machine to VHDL. Dr. Philip Brisk Department of Computer Science and Engineering University of California, Riverside CS 223. Entity. Name of the system and I/O Interface. LIBRARY ieee ; USE ieee.std_logic_1164.ALL; ENTITY MainSystem IS PORT(
E N D
Converting a Finite State Machine to VHDL Dr. Philip Brisk Department of Computer Science and Engineering University of California, Riverside CS 223
Entity • Name of the system and I/O Interface LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY MainSystem IS PORT( A_i: IN std_logic_vector(7 DOWNTO 0); B_o: OUT std_logic_vector(7 DOWNTO 0); clk_i: IN std_logic; rst_i: IN std_logic ); END MainSystem;
Architecture • Internal circuit of the entity • The internal circuits of an entity
IF (clk_i=’1’ AND clk_i’EVENT) THEN IF (rst_i=’1’) THEN state := LedOff; B0_v := ‘0’; ELSE -- SM case stmts go here CASE state IS -- Transitions WHEN LedOff => state := LedOn; WHEN LedOn => state := LedOff; WHEN OTHERS => state := LedOff; END CASE; CASE state IS -- Actions WHEN LedOff => B0_v := ‘0’; WHEN LedOn => B0_v := ‘1’; END CASE; END IF; B_o(0) <= B0_v; -- update port signal END IF; ARCHITECTURE beh OF MainSystem IS BEGIN BlinkLed: PROCESS(clk_i) TYPE states IS (LedOff, LedOn); VARIABLE state : states := LedOff; VARIABLE B0_v : std_logic := ‘0’; BEGIN … END PROCESS; END beh;
PROCESS statement PROCESS(clk_i) • The “process” executes every time there is an event on clk_i • Typically, this means that clk_i will be a clock, so the event is a rising/fall edge • Details to come…
TYPE and VARIABLE statements • TYPE states IS (LedOff, LedOn); • Two possible system states • VARIABLE state : states := LedOff; • Creates an initializes a variable to maintain the current state • VARIABLE B0_v : std_logic := ‘0’; • Creates and initializes an intermediate value
Clock Events IF (clk_i=’1’ AND clk_i’EVENT) THEN • EVENT means a transition from 0 to 1 or 1 to 0 • clk_i=’1’ means to take the action on the rising edge (0 to 1) • Can create complex circuits with different actions on rising/falling edges • Careful with the timing… • Can create asynchronous circuits by using logic to generate signals that are used for events, rather than connecting to a clock
Conditions rst_i 0 IF (rst_i=’1’) THEN state := LedOff; B0_v := ‘0’; ELSE … state 1 LedOff ELSE rst_i 0 BO_v 1 0
More Muxes state rst_i ELSE -- SM case stmts go here CASE state IS -- Transitions WHEN LedOff => state := LedOn; WHEN LedOn => state := LedOff; WHEN OTHERS => state := LedOff; END CASE; CASE state IS -- Actions WHEN LedOff => B0_v := ‘0’; WHEN LedOn => B0_v := ‘1’; END CASE; END IF; 0 LedOn LedOff state 1 LedOff LedOn LedOff Others LedOff rst_i 0 BO_v 1 0 0 LedOff LedOn 1
Comments -- This is a comment Examples from the code… ELSE -- SM case stmts go here CASE state IS -- Transitions
Signals and Variables • Ports are signals • Output ports cannot be read • Variables hold values • e.g., output of a gate • A wire (bus) or flip-flop (register) <= writes a signal := writes a variable
Wires vs. Registers ELSE -- SM case stmts go here CASE state IS -- Transitions WHEN LedOff => state := LedOn; WHEN LedOn => state:= LedOff; WHEN OTHERS => state:= LedOff; END CASE; CASE state IS -- Actions WHEN LedOff => B0_v := ‘0’; WHEN LedOn => B0_v := ‘1’; END CASE; END IF; • The value of state must be stored so that it can be read by the next process execution • B0_v is not read by the next process execution
How do we get a 500ms Clock Period? • The FPGA will provide its own internal clock that you can use • You can’t speed it up, but you can slow it down. E.g., you don’t necessarily want your LED blinking at 400 MHz
BlinkLedClk: PROCESS(clk_i) -- Suppose 1 MHz VARIABLE cnt: INTEGER := 0; BEGIN -- 1 MHz means 1 microsecond(us) per tick -- 500 ms * 1000us/ms = 500,000us IF (clk_i=’1’ AND clk_i’EVENT) THEN IF (rst_i=’1’) THEN cnt:= 0; ELSE cnt:= cnt + 1; IF (cnt = 500000) THEN BLclk_s<= ‘1’; cnt:= 0; ELSE BLclk_s<= ‘0’; END IF; END IF; END IF; END PROCESS; -- Note: aboveprocessisshorthand -- for 1-state synchSM END beh; Clock Divider ARCHITECTURE beh OF MainSystem IS SIGNAL BLclk_s: std_logic; BEGIN BlinkLed: PROCESS(BLclk_s) ... IF (BLclk_s=’1’ AND BLclk_s’EVENT) THEN ... END PROCESS;
Uneven Blinking LEDs (VHDL) CASE state IS -- Transitions WHEN Init=> state := LedOn; WHEN LedOn => IF (X_v < “00000011”) THEN state := LedOn; ELSIF (NOT(X_v < “00000011”)) THEN state := LedOff; END IF; WHEN LedOff => … WHEN OTHERS => state := Init; END CASE; CASE state IS -- Actions WHEN Init => X_v:= “00000000”; B0_v := ‘0’; WHEN LedOn => X_v:= X_v + “00000001”; B0_v := ‘1’; ... END CASE; ARCHITECTURE beh OF MainSystem IS SIGNAL BL2clk_s: std_logic; BEGIN BlinkingLed2: PROCESS(BL2clk_s) TYPE states IS (Init, LedOn, LedOff); VARIABLE state : states := Init; VARIABLE X_v : std_logic_vector(7 DOWNTO 0); VARIABLE B0_v : std_logic; BEGIN IF (BL2clk_s=’1’ AND BL2clk_s’EVENT) THEN IF (rst_i=’1’) THEN state := Init; ELSE … END IF; B_o(0) <= B0_v; END IF; END PROCESS;
Multiple SynchronousState Machines ARCHITECTURE beh OF MainSystem IS SIGNAL BLclk_s, TLclk_s: std_logic; BEGIN BlinkLed: PROCESS(BLclk_s) ... END PROCESS; BlinkLedClk: PROCESS(clk_i) -- gen 300 msBLclk_s ... END PROCESS; ThreeLeds: PROCESS(TLclk_s) ... END PROCESS; ThreeLedsClk: PROCESS(clk_i) -- gen 200 msTLclk_s ... END PROCESS; END beh; BlinkLED Period = 300ms ThreeLEDs Period = 200ms
Shared Variable Communication (VHDL) ARCHITECTURE beh OF MainSystem IS SIGNAL DMclk_s, ILclk_s: std_logic; SHARED VARIABLE mtn_sv: std_logic; BEGIN DetectMotion: PROCESS(DMclk_s) ... mtn_sv:= ‘1’; ... END PROCESS; DetectMotionClk: PROCESS(clk_i) --gen 200 ms DMclk_s ... END PROCESS; IlluminateLamp: PROCESS(TLclk_s) ... IF (mtn_sv = ‘1’) THEN ... END PROCESS; IlluminateLampClk: PROCESS(clk_i) --gen 200 msILclk_s ... END PROCESS; END beh;