"Show me the same output done as Moore and as Mealy. When does each fire, and which would you ship?" The interviewer wants the timing difference drawn precisely, plus a decision.
The complete answer gives both machines, states the one-cycle gap, and names the timing path each choice creates.
A Moore output depends on state alone; a Mealy output also depends on live inputs. A combinational Moore decode can still glitch just after an edge while state bits settle. Only an explicitly registered output (or a separately verified hazard-free implementation) provides a glitch-free boundary.
For a falling-edge flag, the Mealy version fires in the cycle the input falls. The Moore version needs a dedicated state, so it fires one cycle later.
Compare where y is written. On the Mealy arc it appears as soon as x falls; in the Moore state it waits for the edge that enters FELL, which is the one-cycle gap.
Moore | Mealy | |
|---|---|---|
Depends on | State only | State and current inputs |
Reacts to an input | After the next clock edge | In the same cycle |
Stability within a cycle | Settles after state/decode transitions; may glitch during settling | Can also follow input glitches |
States for the same job | Often one more | Fewer |
Timing path | State clock-to-Q plus decode and routing | Input/state through combinational logic to output |
Each slot is one clock cycle sampled just before its closing edge. The same input drives both machines, and it falls during slot 3.
Slot 3: x falls while both machines still read ONE, so y_mealy rises in the same slot. The Moore machine only moves to FELL at the closing edge.
Slot 4: o_state reads FELL (the 2 in its lane), so y_moore rises exactly one cycle after y_mealy.
Slot 6: x rises again and neither flag fires. Rising edges are ignored by design.
For glitch-sensitive exported controls, register the output explicitly, whether its decision is Moore or Mealy. A combinational Moore output can be used at a synchronous boundary when its decode delay and settling are included in the timing contract. Keep plain Mealy for intentional same-cycle feedback with a budgeted path.
The Mealy decision must leave the block. What changes? Register it before the port. A registered Mealy output keeps the small state with Moore-like timing.
Which closes timing more easily? Compare the actual paths. Moore removes live input-to-output dependence but may have a deep state decode. A registered output moves that decode before its output flop; clock-to-Q and routing then dominate the external path.
Two Mealy blocks chained together? The combinational paths add up across the chain. Budget the full input-to-output delay, or register between the blocks.
"Mealy saves a cycle, so it is always better." The saved cycle costs a combinational path to the output. At a boundary that path can fail timing or glitch.
"Moore and Mealy detect different things." On the same spec they flag the same events. They differ only in when the flag is visible relative to the clock.
"Sample the Mealy output right at the edge." Inputs driven at the edge race the sampling. Drive inputs away from the edge and compare after the logic settles.
Mealy fires in cycle 3, the same cycle. Moore fires in cycle 4, one cycle later. The testbench below checks exactly this relationship on every sample.
#1 after driving x before comparing the Mealy output?The Mealy output is combinational in x. The delay lets it settle, so the check compares the settled value instead of racing the input change.
A falling-edge flag in both styles, checked sample by sample: Mealy equals the spec, Moore equals the spec delayed by one cycle.
module edge_mealy (input logic clk, rst_n, x, output logic y);
typedef enum logic {ZERO, ONE} state_t; // ONE means the previous sample was 1
state_t state;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) state <= ZERO;
else if (x) state <= ONE;
else state <= ZERO;
assign y = (state == ONE) && !x; // Mealy: state AND live input
endmodule
module edge_moore (input logic clk, rst_n, x, output logic y);
typedef enum logic [1:0] {ZERO, ONE, FELL} state_t;
state_t state, next_state;
always_comb begin
next_state = state;
case (state)
ZERO: if (x) next_state = ONE;
ONE: if (x) next_state = ONE; else next_state = FELL;
FELL: if (x) next_state = ONE; else next_state = ZERO;
default: next_state = ZERO;
endcase
end
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) state <= ZERO;
else state <= next_state;
assign y = (state == FELL); // Moore: state only
endmodule