Mittwoch, 14. August 2019

Getting my feet wet with TinyFPGA

In this write-up, I am going to document my first steps using an FPGA.

The device that was used is a TinyFPGA BX, featuring a Lattice iCE40LP8K. This FPGA features 7680 logic elements, so called LUT-4. This means that every programmable logic element is a 4-input look up table that can take on any possible 4-input logic function. This LUTs are the basic logic elements (BLEs) of the FPGA. Several BLEs are combined to form a configurable logic block (CLB), which is at the basis of the configurability of FPGAs. The internal frequency of the FPGA is 16MHz.

A great resource for FPGA architecture can be found under this link: FPGA Architecture.

The first thing was to install everything according to this link: TinyFPGA Setup
After the installation completed successfully, and the first program was synthesized on the FPGA, I could see the LED flashing according to an SOS pattern, just as the tutorial promised.

After reading a bit about Verilog, the language used in the TinyFPGA, I wanted to create my own first program. The idea of the program was a simple counter, that would get incremented whenever a button was pressed. The counter was rather simple:

module counter(
  trigger,
  out
  );

  input trigger;
  output out;

  wire trigger;
  reg out;

  reg [2:0] counter;

  initial begin
    out <= 0;
    counter <= 0;
  end

  always @(posedge trigger) begin
    if (counter == 7) begin
      counter <= 0;
      out <= 1;
    end
    else begin
      counter <= counter + 1;
      out <= 0;
    end
  end
endmodule

It's a small module that contains a 3-bit wide register. This register is incremented on every positive edge of the trigger input. Whenever it hits the maximum value of 7 (3'b111 in Verilog-speak), the counter outputs a 1 and resets the counter to 0. Otherwise, the counter is just incremented and it outputs a 0.

Now I hooked up a button to one of the IO-Pins of the FPGA with a pull-up resistor and hooked the IO-Pin to the trigger of the counter. However, the mindful reader may have noticed that this will obviously not work. The reason for this is, that the button is not debounced.

Looking up a way to debounce a circuit in an FPGA, I came across this site: Debounce

Using the blockdiagram, I implemented the debounce logic in Verilog and tested it with a testbench.
The final result was the following code:

module button(
  in,
  clk,
  out
  );

  input clk;
  input in;
  output out;

  reg step_1;
  reg step_2;
  reg counter_clr;
  reg [19:0] counter;
  reg out;

  initial begin
    step_1 = 1'b0;
    step_2 = 1'b0;
    counter_clr = 1'b0;
    counter = 4'b0;
    out = 1'b0;
  end

  always @(posedge clk)
  begin
    step_1 <= in;
    step_2 <= step_1;
    counter_clr <= step_1 ^ step_2;

    if (counter_clr)
      counter <= 0;
    else if (counter < (1 << 19))
      counter <= counter + 1;
    else begin
      counter <= counter;
      out <= (counter == (1 << 19)) ? step_2 : out;
    end
  end
endmodule

The basic idea behind this logical circuit is, that there is a counter, which is cleared every time the input signal transitions from high to low or vice-versa. The output of the circuit is only set to the input value (or rather the input value one timestep ago), once the timer reaches a certain value.

The value that was needed for this was computed as follows:
First, the button was "clicked" several times, and the signal was measured with a logic analyzer. The minimum value for the time the button signal showed 0V was measured. This value was divided by two for good measure, then multiplied by the clock frequency of 16 MHz, giving the number of cycles. Finally, the closest power of 2 was used as a counter value, which turned out to be 219.

These two modules were bundled together in the top module:


module top(
  LED,
  PIN_2,
  CLK
  );

  output LED;
  input PIN_2;
  input CLK;
  reg OUT;

  button btn2(
    PIN_2,
    CLK,
    OUT
    );

  counter cnt(
    OUT,
    LED
    );
endmodule



The output of the debounced button is directly fed to the trigger input of the counter.
The output of the counter is then used to light an LED.

Now, clicking the button 8 times triggers the onboard LED!

I hope you found this first dabbling in FPGA synthesis interesting.
Please leave a comment and let me know about your thoughts!

Keine Kommentare:

Kommentar veröffentlichen