=====State Machine Design===== This tutorial will provide a basic overview of state machine design using Behavioral Verilog. It will simply consist of an example block of code for a generic state machine with explanations following. A silly little state machine is designed that, for the purpose of being generic, very briefly and simply represents a growing tree. Here is a list of the inputs and outputs, along with the state graph that the code will be representing. Following these is the module's Verilog code. The code is explained afterwards. ^ Inputs ^^ | Plant | Planting the seed | | Water | Watering the plant | | Sun | Giving the plant sunlight | | Reset | Start over | ^ Outputs ^^ | getFruit | Getting fruit from the tree | | getSeeds | Getting more seeds from the tree | | Done | Cycle is over | {{ :tutorials:state_machine_intro:growing_tree_state_graph.png?nolink |}} It is assumed that if no listed transition conditions are met, the state stays where its at and does not transition. module state_machine (clock, reset, plant, water, sun, harvest, getFruit, getSeeds, done); input clock, reset, plant, water, sun, harvest; output getFruit, getSeeds, done; // stores the state reg[1:0] state; reg[1:0] next_state; // state parameters parameter seed = 2'd0; parameter sprout = 2'd1; parameter tree = 2'd2; parameter dead = 2'd3; always @(posedge clock) if (reset) state <= seed; else state <= next_state; // setting the state always @(*) case (state) seed: if (plant) next_state <= sprout; else // Keep the state the same // This is required because the Nexys 4 apparently // will reset the register if it is not given a value next_state <= state; sprout: if (water && sun) next_state <= tree; else next_state <= dead; tree: if (harvest) next_state <= seed; else // Keep the state the same // This is required because the Nexys 4 apparently // will reset the register if it is not given a value next_state <= state; default: next_state <= seed; endcase // note that the always block ends here // setting the outputs // moore outputs assign getFruit = state == tree; assign done = state == dead; //mealy output assign getSeeds = (state == tree) && harvest; endmodule As you can see, inputs and outputs as declared in a state machine module just like they would be in any Verilog module. **reg[1:0] state** creates the register that will store the state. This must have enough bits to store all the states. In this example there are 4 different states thus **state** only needs 2 bits. **reg[1:0] next_state** creates a register that stores the next state. **parameter** is similar to const in C. This simply creates a constant variable with the value given. This allows you to encode your states with names. It is not necessary to do this, but it makes it incredibly easy to manage your states. If you don't do this, you'll have to remember which state encoding corresponds to each state, and when you transition states you'll have to store a number directly like ''state <= 2'b10''. It is highly recommended that you use parameters. **always @(posedge clock)** is the block in which all the transitions occur. Note that ''begin'' and ''end'' are not necessary because this always block only contains one statement. **always @(*)** is an always block that will always be operating. It is essentially combination logic but an easier way to code it. Setting the next state inside an always block like this allows states that don't need a clock cycle to be passed through. This will be particularly helpful in the last lab of this class, where the **decode** state should not take up a clock cycle. **case (state)** is a switch statement. It acts just like a ''switch case'' statement in C. ''case'' looks at the value that is passed to it, in this example ''state'', and then executes the option that ''state'' is equal to. So if ''state'' is equal to ''seed'', it will execute ''if (plant) state <= sprout;''. If ''state'' doesn't match any of the given options, ''default'' is executed. In this case ''default'' is used to give the state machine an initial state even if ''reset'' is not asserted. Case does not need a **begin** but it needs an **endcase**. **else state %%<=%% dead;** under state ''sprout'' doesn't need to be an ''else if'' statement because there are only 2 transitions leaving that state, and the second is actually an inversion of the first using DeMorgan's Law! **default:** is the case that is selected if no others are met. \\ **The outputs** are described in lines of combinational logic at the end. You can set the outputs inside the always block, but the outputs must then be made registers and its harder to find problems in your code as statements for a single output will be spread out all over. There are multiple ways to set an output to 1 given a condition. The first output line, **assign getFruit = state == tree? 1 : 0;** tests ''state == tree'' using a ternary operator. However, the statement ''state == tree'' will return a 1 or a 0 anyway, so it can be used on its own without a ternary operator as is done in the third output, **assign done = state == dead;**. This can only be done on single bit outputs. The outputs **getFruit** and **done** are both only moore outputs, they only depend on the current state. This can be seen from the fact that their logic only depends on what ''state'' is. **getSeeds**, however, is a mealy output as it depends on the transition. This is done by checking the current state and the transition condition and then and'ing them together.