Introduction: State Machine Visualization for the Claw Game

The Claw Game's state machine is quite large so it would be nice to know exactly what it is thinking at any one time. To accomplish this we will add in a UART transmitter to communicate with an attached computer running LabVIEW. This can be adapted for use in any Verilog project.

For more information on the Claw Game see this collection.

Materials required:

Step 1: Planning the Transmitter

The Transmitter requires three blocks.

  1. Clock Divider - gets the correct baud rate
  2. Shift Register - pushes the data asynchronously to the computer
  3. State Machine - controls the shift register at the rate of the clock divider

For this we use the "packet" design as shown in the above image

The baud rate clock can be generated with:

divider = FPGA clock speed / desired baud rate

For this we will use 9600 baud.

A shift register will be needed to use as a FIFO (First In First Out) buffer for the data along with a state machine with 2 states, Idle and transmitting.

Step 2: Creating the Transmitter Part 1

The transmitter has the following inputs and outputs:

  • input clk (A 50 MHz clock)
  • input reset (Active high reset signal)
  • input transmit (Active low signal to let the module know to load new data)
  • input data (8 bit value to send on transmit signal)
  • output Tx (The wire to transmit on)

The

First we implement the clock divider as a counter. At 50 MHz, a 9600 baud clock can be generated with a counter that resets every 5207 clock cycles. The state update block with built in shifter looks like this:

always @ (posedge(clk))begin
    if (reset)
    begin
        state <= 0;
        counter <= 0;
        bitcounter <= 0;
    end
    else
    begin
        counter <= counter + 1;
        if (counter >= 5207) //baud of 9600 at 50MHz clk
        begin
            state <= nextstate;
            counter <= 0;
            if (load) rightshiftreg <= {1'b1, ^data, data, 1'b0};
            if (clear) bitcounter <= 0;
            if (shift)
            begin
                rightshiftreg <= rightshiftreg >> 1;
                bitcounter <= bitcounter + 1;
            end
        end
    end
end

Step 3: Creating the Transmitter Part 2

The state machine starts with an always block and a case statement. The always block triggers on a change in the state, transmit signal, or the bit count. The state machine will allow the module to enter an idle state when data is not being transmitted.

The final module is attached below.

always @ (state or bitcounter or transmit)
begin
    load <= 0;
    shift <= 0;
    clear <= 0;
    Tx <= 1;
    
    case (state)
        0:
        begin
            if (transmit == 1)
            begin
                nextstate <= 1;
                load <= 1;
                shift <= 0;
                clear <= 0;
            end
            else
            begin
                nextstate <= 0;
                Tx <= 1;
            end
        end
        1:
        begin
            if (bitcounter >= 10)
            begin
                nextstate <= 0;
                clear <= 1;
            end
            else
            begin
                nextstate <= 1;
                shift <= 1;
                Tx <= rightshiftreg[0];
            end
        end
    endcase
end

Attachments

Step 4: Getting the State From the Machine

To get the state from the state machine two lines are required in the state machine. One is an addition to the I/O of the module and the other is an assign statement to set the new output to the current state of the state machine. For example the output line could look like:

output [4:0] state_out

Then the assign statement will look like

assign state_out = present_state;

Now the state_outwire will always have the present state of the state machine available.

Step 5: Updating the Constraints and Top Module Outputs

In order for the signal to get to the USB port of the Basys 3 the xdc file needs to be updated with the following lines added:

set_property PACKAGE_PIN A18 [get_ports tx]
set_property IOSTANDARD LVCMOS33 [get_ports tx]

This directs the net called tx to pin A18 on the FPGA. To bring this wire into the top module the line output tx also needs to be added to the I/O list.

If you are using the master .xdc file for the Basys 3 just uncomment lines 283 and 284.

Step 6: Sending the States to the Transmitter

Now that the states are available to the transmitter the transmitter needs to know when it is OK to send data. Using a ternary statement the logic for this can be done without the need of an always block.

assign uart_transmit = (next_state != prev_state && clk_50 == 1'b1 ? 1 : 0);

This is equivalent to the following always block:

always @ (posedge(clk_50)) begin
	if (next_state != prev_state)
		uart_transmit <= 1;
	else
		uart_transmit <= 0;
end

The last state needs to be known in order to detect a state change. This can be done with another tertiary statement:

assign prev_state = (uart_busy == 1'b0 && tx_clk == 1'b1 ? state : prev_state);

The code should now be ready to generate the bitstream and program the Basys 3. I'm assuming that you have followed to the How to Code Your Own Claw Machine tutorial and have done this step before.

The full Vivado project is available on Github.

Step 7: LabVIEW Interface

To create a graphical interface for the claw game, a computer with LabVIEW and NI VISA was used. NI VISA allows LabVIEW to read/write serial data.

Using the VISA serial configure block, we can setup the serial communication from the Basys3 to LabVIEW. We then check to see if there are bytes available to read. If there are, the VISA read VI is used to read the incoming data. A string to U8 array as well as an index array is used to read the state information that was sent from the Basys3.

Depending on the state, we can output the name of the state using a string indicator and a case structure and we can also use a boolean indicator to give users a visual representation of where they are in the state machine.

To read more about the Claw Game project see this blog post or the full collection of Claw Game Instructables.

Makerspace Contest

Participated in the
Makerspace Contest