# Designing a Combination Lock FSM: Converting State Diagram to Logic Gates

I am trying to design a Synchronous combination lock for my digital logic class. I have the state diagram, as I understand how to draw out the logic which I want to follow. However, I am struggling to convert this whole sequence of steps into digital logic. I understand how to create a state table for each of the states and their next states. But how many state tables do I need? After creating these tables how do I output "U". This stuff is all kind of foreign to me, and it is kind of hard to wrap my mind around.

Some clarification for this diagram. I want input "a" to always be activated each time a colored button is pressed (Red, Green or Blue). I chose to adress each input expression as "arg'b'" where as I could have simplified it to simply "ar" to account for a red button press because I wanted to make sure you couldn't just bash all the buttons and be able to brute force the sequence. The sequence I want to program is pressing the buttons [START][R][G][B][R] in that order.

Any help, tips, video links are greatly appreciated. Thank you!

• Jul 29 '20 at 7:08
• The first step is to assign a numeric value to each state. E.g., "start" is 000, "red 1" is 001, "blue 1" is 010, etc. Then write the logic equation for the next state bit by bit. Jul 29 '20 at 15:08

You can either do it the traditional way with pen, ink, state tables, the TTL Data Book, or simply write it directly in VHDL or Verilog, following the partial example below.

Which approach is best depends on circumstances.

If this is homework, you probably have to do the former.

If you're being paid to get things done, and you don't do the latter, start looking for a new job.

   type State   : State_Type is (Start, Red_1, ..., Wait);
signal State : State_Type;
signal argb  : std_logic_vector(3 downto 0);

argb <= a & r & g & b; -- simplify condition testing...

Process(Clk) is
begin
case State is
when Start =>
if argb = "1100" then
State <= Red_1;
u     <= '0';
elsif a = '1' then
State <= Wait;
u     <= '0';
end if;
when -- and so on for all the other states
end case;
end process;


I'll give a verilog version for your reference.

Step 1: Assign a different binary value to each state that is currently named in human language.

parameter WAIT  = 3'h0;
parameter START = 3'h1;
...


Step 2: The DFF entity holding the current state. (I assume the default state is WAIT here)

reg [2:0] st, st_nxt;
always@(posedge clk or negedge rstn)begin
if(~rstn)begin
st <= WAIT;
end else begin
st <= st_nxt;
end
end


Step 3: As long as all the state transition branches are complete (all possible branches and their priorities are defined), you can now generate the next state.

Consider START state:

current state  |        input      |  next state
START ------ a & (r & ~g & ~b) ---> RED1
+--- a & ~(r & ~g & ~b) --> WAIT
+-------- (others) -------> (stay in START)


We'll code as follows:

always@(*)begin
case(st)
START:begin
if(a & (r & ~g & ~b))begin
st_nxt = RED1;
end else if(a & ~(r & ~g & ~b))begin
st_nxt = WAIT;
end else begin
st_nxt = st;
end
end
(code for other states)
default: st_nxt = WAIT;
endcase
end


Step 3: Generate signals that are controlled by state machine.

Here I simply assert u for the entire RED2 state. You can generate your own if sequential output is needed or there're other requirements.

assign u = (st == RED2);


Finally, in the real world, you may also need to consider time out.