Close

#1: blinky

A project log for FPGA dabbling

I don't need an FPGA for anything but the fun of experimenting with it.

christophChristoph 11/30/2018 at 19:380 Comments

After installing the icestorm tools, arachne-pnr, nextpnr and yosys (which all worked out of the box, apart from some more packages to download), I modified some very old blinky verilog code that was originally written for #DIPSY to work with the board at hand. It was mainly just a bunch of pin assignment changes and using a different clock source.

My blinky code consists of two modules:

clockdivider.v

module clockdivider #(
  parameter bits = 32
  )(
  input clkin,
  input[bits-1:0] div,
  output clkout
);

reg [bits-1:0] count = 0;
always @(posedge clkin)
begin
  if(count == 0)
    count = div;
  count = count - {{bits-1{1'b0}},1'b1};
end

assign clkout = (div == 1'b0) ? 1'b0 : 
                (div == 1'b1) ? clkin :
                (count == {bits{1'b0}});

endmodule

This creates a down-counter with given bit count and reload value. When it reaches zero, it reloads the internal counter with the reload value and starts over. I have no idea if this is good code, or if it's even off by one or whatever. But it seems to do the job.

Next is the top-level module that takes an input clock, feeds it into a clockdivider (see above) and outputs the divided clock to an output:

top.v

module top (
  output pin_led,
  input clk_12m
);

reg led = 0;
SB_IO #(             // IO IP instance
  .PIN_TYPE(6'b011001)  // configure as output
) pin_out_driver (
  .PACKAGE_PIN(pin_led), // connect to this pin
  .D_OUT_0(led)           // output the state of "led"
);

wire clkout;
clockdivider #(.bits(28)) div(
  .clkin(clk_12m),
  .clkout(clkout),
  .div(28'd12000000)
);

always @(posedge clkout)
led = ~led;

endmodule

Again, no quality claims here. But - again - it does the job!

 My board has a 12 MHz oscillator and an LED connected like so:

top.pcf

set_io clk_12m 21
set_io pin_led 96

With icestorm, synthesis, placie&route and "packing" (I don't know what the correct technical term is) are three command lines:

yosys -p 'synth_ice40 -top top -blif top.blif' top.v clockdivider.v
arachne-pnr -d 1k -o top.asc -p top.pcf top.blif
icepack top.asc top.bin

Now there's a bin file to be downloaded to the FPGA's config memory. I couldn't figure out how to program my board's flash chip, so this is for SRAM config:

iceprog -S top.bin

I have this dev rule:

/etc/dev/rules.d/53-lattice-ftdi.rules

ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", MODE="660", GROUP="dialout"

quality level: does the job on my laptop. 

And I had blinky!

Discussions