| /* | |
| Key Idea: next state, current state | |
| use the observer pattern to do actions on state change | |
| */ | |
| module FSM_Q4b ( | |
| input CLK, | |
| input RESET, // Asynchronous active high reset | |
| input T, | |
| output reg Y | |
| ); | |
| // Define state encodings for readability | |
| parameter STATE_A = 2'b00, | |
| STATE_B = 2'b01, | |
| STATE_C = 2'b11, | |
| STATE_D = 2'b10; | |
| // State registers | |
| reg [1:0] current_state; | |
| reg [1:0] next_state; | |
| // --- State Transition Logic (Sequential Block) --- | |
| // Updates current_state on CLK edge, handles asynchronous RESET | |
| always @(posedge CLK or posedge RESET) begin | |
| if (RESET) begin | |
| // Asynchronous Reset to initial state A | |
| current_state <= STATE_A; | |
| end else begin | |
| // Synchronous update on CLK | |
| current_state <= next_state; | |
| end | |
| end | |
| // --- Next State Logic (Combinational Block) --- | |
| // Determines the next state based on current_state and input T | |
| always @(*) begin | |
| // Default next_state to current_state to avoid latch inference | |
| next_state = current_state; | |
| case (current_state) | |
| STATE_A: begin | |
| if (T == 1'b0) | |
| next_state = STATE_A; | |
| else // T == 1'b1 | |
| next_state = STATE_B; | |
| end | |
| STATE_B: begin | |
| if (T == 1'b0) | |
| next_state = STATE_A; | |
| else // T == 1'b1 | |
| next_state = STATE_C; | |
| end | |
| STATE_C: begin | |
| if (T == 1'b0) | |
| next_state = STATE_B; | |
| else // T == 1'b1 | |
| next_state = STATE_D; | |
| end | |
| STATE_D: begin | |
| if (T == 1'b0) | |
| next_state = STATE_C; | |
| else // T == 1'b1 | |
| next_state = STATE_D; | |
| end | |
| default: begin | |
| // Should not happen, but reset to a safe state | |
| next_state = STATE_A; | |
| end | |
| endcase | |
| end | |
| // --- Output Logic (Combinational Block for Moore Machine) --- | |
| // Output Y is solely determined by the current_state | |
| always @(current_state) begin | |
| case (current_state) | |
| STATE_A, STATE_B: begin | |
| // A (Y=0), B (Y=0) | |
| Y = 1'b0; | |
| end | |
| STATE_C, STATE_D: begin | |
| // C (Y=1), D (Y=1) | |
| Y = 1'b1; | |
| end | |
| default: begin | |
| Y = 1'b0; // Safe default | |
| end | |
| endcase | |
| end | |
| endmodule |
-8'd5 or -8'b101
always @(state) begin
case (state)
IDLE: begin green = 0; red = 0; end
DETECT_PED: begin green = 0; red = 1; end
DETECT_VEH: begin green = 0; red = 1; end
TIMER: begin green = 1; red = 0; end
default: begin green = 0; red = 0; end
endcase
endalways @(*) begin
warning_light = 0;
case (state)
DETECT_VEH: begin
if (vehicle == 1)
warning_light = 1;
end
endcase
endmodule circuit(
input wire clk, start, stop, pedestrian, vehicle, timeout,
output reg green, red
);
// --- DEFINITIONS ---
parameter IDLE = 2'b00, DETECT_PED = 2'b01, DETECT_VEH = 2'b10, TIMER = 2'b11;
reg [1:0] state, next_state;
// --- 1. STATE MEMORY (Synchronous - The "Anchor") ---
// This is the only part that remembers history.
always @(posedge clk) begin
if (stop) state <= IDLE;
else state <= next_state;
end
// --- 2. NEXT STATE LOGIC (Combinational - The "Brain") ---
// Pure function: (current_state, inputs) -> next_state
always @(*) begin
next_state = state; // Default to stay (prevents latch creation)
case (state)
IDLE: if (start) next_state = DETECT_PED;
DETECT_PED: if (!pedestrian) next_state = DETECT_VEH;
DETECT_VEH: if (vehicle) next_state = TIMER;
else next_state = DETECT_PED; // The missing link from before
TIMER: if (timeout) next_state = DETECT_PED;
default: next_state = IDLE;
endcase
end
// --- 3. OUTPUT LOGIC (Combinational - The "Display") ---
// PURE MOORE: Depends ONLY on state. No side effects from inputs.
always @(*) begin
case (state)
IDLE: begin green = 0; red = 0; end
DETECT_PED: begin green = 0; red = 1; end
DETECT_VEH: begin green = 0; red = 1; end
TIMER: begin green = 1; red = 0; end
default: begin green = 0; red = 0; end
endcase
end
endmodule
JK Flip Flop
if both J&K 1 --> toggle,
else function like a normal flip flop