On 2008-04-23, ee_ether <xjjzdv402@sneakemail.com> wrote:> Hi, > > A colleague and I are having a friendly debate on coding state > machines in Verilog, targeting synthesis for FPGAs. Comments are very > appreciated. I am NOT trying to start a holy war here regarding > syntax style (one process vs. two process, etc). > > Crux of the matter: Do you need to define values for outputs of your > state machine in EVERY state, or do you only need to define values for > outputs in states where you want the output to update/change?In a process activated by a clock edge it is not necessary to specify the output value in every branch. It is possible to create synchronous logic anyway. The following example will show a flip-flop with a load enable for example. always @(posedge clk) begin if (ce) q <= d; // Flip flop with enable signal //else q <= q; // This is automatically implied end However, if you have a combinational circuit I guess you could see the construction like this: always @* begin if (ce) q = d; // else q = q; // This is also automatically implied end The problem is that q = q would build a combinational loop and the synthesizer will probably implement this as a latch. (In reality I guess there might be some simulation issues. I guess that a simulator is not even going to update q with the value of q if the else case is not present. Actually, I'm not sure that it will update q anyway, even if the else case is present as it is just going to be updated with the same value. A quick experiment indicates that at least ModelSim doesn't update the variable in this case at least.) /Andreas
Re: Verilog state machines, latches, syntax and a bet!
This discussion explores whether Verilog state machine outputs must be explicitly defined in every state or only when their values change. The thread clarifies how different coding styles, specifically one-process versus two-process designs, affect the synthesis of registers and the potential for unintentional latches.
The consensus is that while specifying values only during changes is technically acceptable in clocked processes, designers must be careful with combinational logic to avoid creating transparent latches. Several experts recommend using default assignments or a single-process approach to simplify the code and ensure hardware reliability.
- In a clocked (one-process) design, omitted assignments naturally result in registers that retain their previous state.
- In a combinational (two-process) design, every output must be assigned in every path to prevent the synthesis of unintended latches.
- Default assignments at the top of a process can serve as a shorthand to ensure all signals are defined for every state branch.
- The choice between coding styles often depends on the complexity of the state machine and the desired readability for debugging.
- Modern synthesizers like Quartus and ISE handle abbreviated output logic by inferring flip-flops with multiplexers.
Hi, A colleague and I are having a friendly debate on coding state machines in Verilog, targeting synthesis for FPGAs. Comments are very appreciated. I am NOT trying to start a holy war here regarding syntax style (one process vs. two process, etc). Crux of the matter: Do you need to define values for outputs of your state machine in EVERY state, or do you only need to define values for outputs in states where you want the output to update/change? Skip to the chase: At end of message is a Verilog state machine that does NOT define outputs in all states. Is this acceptable Verilog or unacceptable (targeting FPGA)? If not, how would you re-write it? If yes, what are the implications? When you write a SM in Verilog can you "abbreviate" your output logic and let the synthesizer infer storage registers for flags assuming you don't define output condition for all states? For the code below, the synthesizer (Altera Quartus II v7.1) produces DFF with MUXes in front ; no latches synthesized. The register is fed back its value when NOT in the states where value is updated. This is gleaned from using RTL Viewer in Quartus II. I am curious what ISE 10x would do with this Verilog too... Colleague: Verilog/RTL is supposed to provide a reasonable abstraction, so if you have a state machine where you are updating a flag (i.e. set the bit/flag in one state, clear it in some other), you only need to define the output in those states where the bit will be set or cleared. The synthesizer will then produce a register and only update the value(register) in the correct state. Coding values of ALL outputs in ALL states would be too tedious and negates advantage of RTL. My perspective is : You must define output in every state otherwise the synthesizer will produce a latch, or some other kind of unwanted feedback vs. decoding the output based off state registers (and possibly any other asynchronous inputs). When I wrote VHDL I would always define output of SM (mealy or moore) and it would result in unpleasant to read RTL but synthesized to what I want. FWIW, I prefer to combine output statements and next-state logic in one process since I can follow the logic more easily; if I want a set/clear type flag then I define SET_FLAG and CLEAR_FLAG signals and they are driven in every state; a clocked process is used to check SET and CLEAR to synchronously toggle output (flag). cpu_lw_*, ackb are all outputs and outputs are not always defined in all states (hence the debate). ----------------------------------------------------------------------------------------------------------------------------------------------- //State Machine always @ (posedge CLK or negedge negreset) begin if(!negreset) begin ackb <= 1'b1; cpu_lw_read <= 1'b0; cpu_hw_read <= 1'b0; cpu_lw_write <= 1'b0; cpu_hw_write <= 1'b0; state <= 0; end else begin case (state) 0: begin if (!csb) begin case (rd_wr_sel) 2'b00: state <= 2; 2'b01: state <= 3; 2'b10: begin cpu_lw_read <= 1'b1; dataout_sel <= 1'b1; state <= 4; end 2'b11: begin cpu_hw_read <= 1'b1; dataout_sel <= 1'b1; state <= 4; end endcase end else state <= 0; end 2: begin if(!dsb) begin cpu_lw_write <= 1'b1; state <= 4; end else begin state <= 2; end end 3: begin if(!dsb) begin cpu_hw_write <= 1'b1; state <= 4; end else begin state <= 3; end end 4: begin if(ready) begin ackb <= 1'b0; state <= 5; end else if (csb) begin cpu_lw_read <= 1'b0; cpu_hw_read <= 1'b0; cpu_lw_write <= 1'b0; cpu_hw_write <= 1'b0; state <= 0; end else begin state <= 4; end end 5: begin if(csb) begin ackb <= 1'b1; cpu_lw_read <= 1'b0; cpu_hw_read <= 1'b0; cpu_lw_write <= 1'b0; cpu_hw_write <= 1'b0; state <= 0; end else begin state <= 5; end end endcase end
On Apr 23, 5:33=A0am, ee_ether <xjjzdv...@sneakemail.com> wrote:> Hi, > > Crux of the matter: =A0Do you need to define values for outputs of your > state machine in EVERY state, or do you only need to define values for > outputs in states where you want the output to update/change? >It doesn't matter. The same synthesized output can result from more than one source code representation.> Skip to the chase: =A0At end of message is a Verilog state machine that > does NOT define outputs in all states. =A0Is this acceptable Verilog or > unacceptable (targeting FPGA)?If it implements the required function than it is acceptable.> If not, how would you re-write it? =A0If it's not broken, don't fix it.> If > yes, what are the implications? =A0When you write a SM in Verilog can > you "abbreviate" your output logic and let the synthesizer infer > storage registers for flags assuming you don't define output condition > for all states? >If you get paid by the line of code then you might want to set those outputs in every state.> For the code below, the synthesizer (Altera Quartus II v7.1) produces > DFF with MUXes in front ; no latches synthesized. =A0The register is fed > back its value when NOT in the states where value is updated. =A0This is > gleaned from using RTL Viewer in Quartus II. =A0I am curious what ISE > 10x would do with this Verilog too... >Why the curiousity? Run it through and satisfy your curiousity, that's the best teacher.> Colleague: =A0Verilog/RTL is supposed to provide a reasonable > abstraction, so if you have a state machine where you are updating a > flag (i.e. set the bit/flag in one state, clear it in some other), you > only need to define the output in those states where the bit will be > set or cleared. =A0The synthesizer will then produce a register and only > update the value(register) in the correct state. =A0Coding values of ALL > outputs in ALL states would be too tedious and negates advantage of > RTL. >Whether one *should* code outputs in every state or not can depend on how many different paths there can be through the state machine. One that is fairly simple (like a simple loop) it is likely just as clear to the reader to only explicitly set the outputs when they need to change. Another more complicated one where there is all sorts of branching dependent on various conditions might benefit from coding the output values in more (or all) of the states. The other thing that influences the decision (possibly even more) is whether or not you, from a design perspective, inherently 'know' what the output should be while you're in a particular state. Many state machines might not care what the value of output 'xyz' should be while they're in state 'state_abc'. Those types of state machines will be more clearly written in the style of specifying output changes rather than explicitly setting them. The example that the colleague mentioned sounds to me like a case where coding only the changes (as he suggests) would be best because it more clearly captures the intent.> My perspective is : You must define output in every state otherwise > the synthesizer will produce a latch, or some other kind of unwanted > feedback vs. decoding the output based off state registers (and > possibly any other asynchronous inputs). =A0Not true at all...state machines are synchronous things clocked by a clock, there will be no latches ever produced. You're getting confused with the 'two process' style where this can happen (which is why the 'two process' style is considered inferior by most skilled designers).> When I wrote VHDL I would > always define output of SM (mealy or moore) and it would result in > unpleasant to read RTL but synthesized to what I want. =A0FWIW, I prefer > to combine output statements and next-state logic in one process since > I can follow the logic more easily; if I want a set/clear type flag > then I define SET_FLAG and CLEAR_FLAG signals and they are driven in > every state; a clocked process is used to check SET and CLEAR to > synchronously toggle output (flag). >And there is the main criteria you should use....how easy is it to read and understand the resulting code because that is what one will need to maintain down the road. Clarity of intent in the source code is second only to correct function in my book. Kevin Jennings
On Wed, 23 Apr 2008 02:33:32 -0700 (PDT), ee_ether <xjjzdv402@sneakemail.com> wrote:>Hi, > >A colleague and I are having a friendly debate on coding state >machines in Verilog, targeting synthesis for FPGAs. Comments are very >appreciated. I am NOT trying to start a holy war here regarding >syntax style (one process vs. two process, etc). > >Crux of the matter: Do you need to define values for outputs of your >state machine in EVERY state, or do you only need to define values for >outputs in states where you want the output to update/change?In either one process or two process designs, you only need to write to the next state when you need to change it. In one process, the registers by definition remember their state so there is no chance of getting a latch. In two states, you assign the next state to the current state at the top of the process so if they don't get written again later, they keep their current state so no latches either.
On Wed, 23 Apr 2008 15:25:33 GMT, Muzaffer Kal <kal@dspia.com> wrote:>On Wed, 23 Apr 2008 02:33:32 -0700 (PDT), ee_ether ><xjjzdv402@sneakemail.com> wrote: > >>Hi, >> >>A colleague and I are having a friendly debate on coding state >>machines in Verilog, targeting synthesis for FPGAs. Comments are very >>appreciated. I am NOT trying to start a holy war here regarding >>syntax style (one process vs. two process, etc). >> >>Crux of the matter: Do you need to define values for outputs of your >>state machine in EVERY state, or do you only need to define values for >>outputs in states where you want the output to update/change? > >In either one process or two process designs, you only need to write >to the next state when you need to change it. In one process, the >registers by definition remember their state so there is no chance of >getting a latch. In two states, you assign the next state to thethis should say "in two process implementation..." of course>current state at the top of the process so if they don't get written >again later, they keep their current state so no latches either.here are some example for my points: always@(posedge clk) if (enable) count <= count+1; in this case there is no need for else count <= count; because if not enable counter registers remember their state so in a state machine, there is no reason to write to states/outputs which don't need changing. In two process design, you say always @(*) begin next_state = state; case (state) foo: next_state = bar; bar: output_x = 6; // no state change ... end in this case the first line always assigns next_state so if later not reassigned it remembers that value so there is no latch for next_state, strictly combinational of off state.
On Apr 23, 11:34 am, Muzaffer Kal <k...@dspia.com> wrote:> On Wed, 23 Apr 2008 15:25:33 GMT, Muzaffer Kal <k...@dspia.com> wrote: > >On Wed, 23 Apr 2008 02:33:32 -0700 (PDT), ee_ether > ><xjjzdv...@sneakemail.com> wrote: > > >>Hi, > > >>A colleague and I are having a friendly debate on coding state > >>machines in Verilog, targeting synthesis for FPGAs. Comments are very > >>appreciated. I am NOT trying to start a holy war here regarding > >>syntax style (one process vs. two process, etc). > > >>Crux of the matter: Do you need to define values for outputs of your > >>state machine in EVERY state, or do you only need to define values for > >>outputs in states where you want the output to update/change? > > >In either one process or two process designs, you only need to write > >to the next state when you need to change it. In one process, the > >registers by definition remember their state so there is no chance of > >getting a latch. In two states, you assign the next state to the > > this should say "in two process implementation..." of course > > >current state at the top of the process so if they don't get written > >again later, they keep their current state so no latches either. > > here are some example for my points: > > always@(posedge clk) > if (enable) > count <= count+1; > > in this case there is no need for > else > count <= count; > > because if not enable counter registers remember their state so in a > state machine, there is no reason to write to states/outputs which > don't need changing. > > In two process design, you say > always @(*) > begin > next_state = state; > case (state) > foo: next_state = bar; > bar: output_x = 6; // no state change > ... > end > > in this case the first line always assigns next_state so if later not > reassigned it remembers that value so there is no latch for > next_state, strictly combinational of off state.I think what Kevin was getting at was that in the two-process style, every output signal in the asynchronous process needs to be assigned for every case. The fact that there is a default assignment doesn't change this - every output is defined for every possible case. Even if there is a default assignment, you still need to specify the output when the output differs from the default, which is different from saying that the output needs to be specified only when it changes. You could omit the output assignment for a case, and it might still change from a non-default value to the default value. The default assignment does not imply memory, it's just a shorthand notation to keep the code more readable. Dave
Hi,> Crux of the matter: Do you need to define values for outputs of your > state machine in EVERY state, or do you only need to define values > for outputs in states where you want the output to update/change?It depends on the type of output. If the output is a combinational function of the current state, or a combinational function of the current state and the inputs, then you must describe the output values for all possible conditions. This is how you model combinational logic; it doesn't matter if it is part of an FSM or not. On the other hand, if you have outputs which are a registered function of the current state, or a registered function of the current state and the inputs, then you do not need to describe the output values for all possible conditions. Since you will be modeling these assignments to something that maintains state in a clocked process, using a reg datatype, the absence of an assignment for a given condition implies "retain the previous value". Here's a short presentation on a "textbook" FSM: http://www.engr.sjsu.edu/crabill/vlogfsm.pdf To paraphrase what someone else wrote, if it solves the problem -- it's correct. However, I think it's a good practice to fully understand what you are creating when you write the code solve a given problem. If you look at the code you provided in the context of a "textbook" FSM, I would suggest that your FSM state variable is actually more than just "state". It's {ackb,cpu_lw_read,cpu_hw_read,cpu_lw_write,cpu_hw_write,state} and by way of what is a custom state assignment implemented in the next state logic, you are able to use certain bits of the state directly as outputs (Moore type outputs) with no combinational decoding logic required to generate those outputs. Eric
On Wed, 23 Apr 2008 08:54:24 -0700 (PDT), Dave <dhschetz@gmail.com> wrote:> The default assignment >does not imply memory, it's just a shorthand notation to keep the code >more readable.Isn't the whole idea of a combinatorial process to avoid memory? In the two process model, the non-clocked process is supposed to be fully combinational. You can imagine the default assignment as the branch of a mux coming from the output of the memory directly and the other branch which is actually calculated next state. If there is no calculated next state the current state gets loaded again.
On Apr 24, 11:55=A0am, Muzaffer Kal <k...@dspia.com> wrote:> On Wed, 23 Apr 2008 08:54:24 -0700 (PDT), Dave <dhsch...@gmail.com> > wrote: > > > The default assignment > >does not imply memory, it's just a shorthand notation to keep the code > >more readable. > > Isn't the whole idea of a combinatorial process to avoid memory?Yes...the memory is 'supposed to' be implemented in a separate clocked process (for the two process design approach).> In > the two process model, the non-clocked process is supposed to be fully > combinational.But there is nothing preventing the designer from inadvertantly creating a latch in this process. The two process approach presents no advantages and has several disadvantages as compared to the one process approach.> You can imagine the default assignment as the branch of > a mux coming from the output of the memory directly and the other > branch which is actually calculated next state. If there is no > calculated next state the current state gets loaded again.If there is no 'calculated next state' in the combinatorial process then you have a design error because you've just created a transparent latch that will come up and bite you at the most inopportune time. This latch is the 'unwanted memory' that is being created which should not exist when using the two process form. All this unpleasantness is completely avoided by simply using a one process design approach. KJ
ee_ether wrote:> Hi, > > A colleague and I are having a friendly debate on coding state > machines in Verilog, targeting synthesis for FPGAs. Comments are very > appreciated. I am NOT trying to start a holy war here regarding > syntax style (one process vs. two process, etc). > > Crux of the matter: Do you need to define values for outputs of your > state machine in EVERY state, or do you only need to define values for > outputs in states where you want the output to update/change? >You shouldn't need to specify output values for states in which the output doesn't change. However, this sometimes makes it hard to debug something like a flag because you have to make sure that you deassert the signal in all states that can follow the state in which you asserted it. For things like flags that are only to be asserted on a few states, I like to do this: always@(posedge clk) begin flag <= 0; // set the default value case (state) state0: state <= state1; state1: state <= state2; state2: flag <= 1; state3: state <= state0; endcase end You can see that for state2, the value of flag is set twice: once to 0 and then later to 1. In a clocked process which uses nonblocking signals, the assignment made last is the one that is used. (Sometimes order *is* important with nonblocking assignments.) This ensures that flag is assigned to 0 in every other state. If the synthesizer has state machine extraction, it might just implement the logic to assert flag's clock enable in the two states (state2 and state3) where it actually changes. An explicit synthesis would update flag on every cycle but only assign it to 1 on state2. If the machine is one-hot, it wouldn't matter too much either way. -Kevin




