[
  {
    "path": ".gitignore",
    "content": "# yosys - Verilog synthesis\n# nextpnr - Place and route\n# Icarus Verilog - Simulation\n# GTKWate - Simulation viewer\n*.dblite\n*.history\n*.asc\n*.bin\n*.json\n*.out\n*.vcd\n*.out"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/info",
    "content": "Hello world example for the Icestick board. Turning all the leds on\n"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds.pcf",
    "content": "# -----------------------------------------------------------------------------\n#- Leds example for the iCEstick board\n#- Constraint file (.pcf)\n# -----------------------------------------------------------------------------\n# --  Pinout: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/images/icestick_pinout.png\n# --  Guide: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/icestickusermanual.pdf\n\n# ------------ User Leds ------------------------------------------------------\nset_io  D1  99\nset_io  D2  98\nset_io  D3  97\nset_io  D4  96\nset_io  D5  95\n"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds.v",
    "content": "//------------------------------------------------------------------\n//-- Hello world example for the iCEstick board\n//-- Turn on all the leds\n//------------------------------------------------------------------\n\nmodule leds(output wire D1,\n            output wire D2,\n            output wire D3,\n            output wire D4,\n            output wire D5);\n\nassign D1 = 1'b1;\nassign D2 = 1'b1;\nassign D3 = 1'b1;\nassign D4 = 1'b1;\nassign D5 = 1'b0;\n\nendmodule\n"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI\n[*] Mon Aug 29 09:12:21 2016\n[*]\n[dumpfile] \"/home/jesus/code/apio-examples/icestick-leds/leds_tb.vcd\"\n[dumpfile_mtime] \"Mon Aug 29 09:10:49 2016\"\n[dumpfile_size] 606\n[savefile] \"/home/jesus/code/apio-examples/icestick-leds/leds_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] 507 137\n*0.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[treeopen] leds_tb.\n[sst_width] 223\n[signals_width] 78\n[sst_expanded] 1\n[sst_vpaned_height] 160\n@28\nleds_tb.UUT.D1\nleds_tb.UUT.D2\nleds_tb.UUT.D3\nleds_tb.UUT.D4\n@29\nleds_tb.UUT.D5\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds_tb.v",
    "content": "//-------------------------------------------------------------------\n//-- leds_tb.v\n//-- Testbench\n//-------------------------------------------------------------------\n//-- Juan Gonzalez (Obijuan)\n//-- Jesus Arroyo Torrens\n//-- GPL license\n//-------------------------------------------------------------------\n`default_nettype none\n`define DUMPSTR(x) `\"x.vcd`\"\n`timescale 100 ns / 10 ns\n\nmodule leds_tb();\n\n//-- Simulation time: 1us (10 * 100ns)\nparameter DURATION = 10;\n\n//-- Clock signal. It is not used in this simulation\nreg clk = 0;\nalways #0.5 clk = ~clk;\n\n//-- Leds port\nwire d1, d2, d3, d4, d5;\n\n//-- Instantiate the unit to test\nleds UUT (\n           .D1(d1),\n           .D2(d2),\n           .D3(d3),\n           .D4(d4),\n           .D5(d5)\n         );\n\n\ninitial begin\n\n  //-- File were to store the simulation results\n  $dumpfile(`DUMPSTR(`VCD_OUTPUT));\n  $dumpvars(0, leds_tb);\n\n   #(DURATION) $display(\"End of simulation\");\n  $finish;\nend\n\nendmodule\n"
  },
  {
    "path": "03-verilog-gate-logic/example-01-and-gate/and_gate.pcf",
    "content": "# LEDs\nset_io              led_0   99\n\n# PMOD I/O\nset_io  -pullup yes pmod_0  78\nset_io  -pullup yes pmod_1  79"
  },
  {
    "path": "03-verilog-gate-logic/example-01-and-gate/and_gate.v",
    "content": "// AND gate example\n//\n// Inputs:\n//      pmod_0  - pushbutton\n//      pmod_1  - pushbutton\n// Outputs:\n//      led_0   - LED\n//\n// LED will turn on if both pushbuttons are pressed (~pmod_0 & ~pmod_1).\n//\n// Date: October 13, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Module: when buttons 1 and 2 are pressed, turn on LED\nmodule and_gate (\n\n    // Inputs\n    input   pmod_0,\n    input   pmod_1,\n    \n    // Outputs\n    output  led_0\n);\n\n    // Continuous assignment: NOT and AND operators\n    assign led_0 = ~pmod_0 & ~pmod_1;\n    \nendmodule"
  },
  {
    "path": "03-verilog-gate-logic/example-01-and-gate/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "03-verilog-gate-logic/example-02-vectors/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "03-verilog-gate-logic/example-02-vectors/vectors.pcf",
    "content": "# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\nset_io              led[2]  97\nset_io              led[3]  96\nset_io              led[4]  95\n\n# PMOD I/O\nset_io  -pullup yes pmod[0] 78\nset_io  -pullup yes pmod[1] 79"
  },
  {
    "path": "03-verilog-gate-logic/example-02-vectors/vectors.v",
    "content": "// Vector and intermediate (wire) value example\n//\n// Inputs:\n//      pmod[1:0]   - pushbuttons (x2)\n//\n// Outputs:\n//      led[2:0]    - LEDs (x3)\n//\n// LEDs 0 and 1 turn on if pmod[0] button is pressed. LED 2 turns on if pmod[0]\n// and pmod[1] are pressed together.\n//\n// Date: October 13, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Module: button 0 lights up 2 LEDs, button 0 and 1 light up another LED\nmodule and_gate (\n\n    // Inputs\n    input   [1:0]   pmod,\n    \n    // Output\n    output  [2:0]   led\n);\n\n    // Wire (net) declarations (internal to module)\n    wire not_pmod_0;\n\n    // Continuous assignment: replicate 1 wire to 2 outputs\n    assign not_pmod_0 = ~pmod[0];\n    assign led[1:0] = {2{not_pmod_0}};\n    \n    // Continuous assignment: NOT and AND operators\n    assign led[2] = not_pmod_0 & ~pmod[1];\n    \nendmodule"
  },
  {
    "path": "03-verilog-gate-logic/solution-full-adder/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "03-verilog-gate-logic/solution-full-adder/full-adder.pcf",
    "content": "# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\n\n# PMOD I/O\nset_io  -pullup yes pmod[0] 78\nset_io  -pullup yes pmod[1] 79\nset_io  -pullup yes pmod[2] 80"
  },
  {
    "path": "03-verilog-gate-logic/solution-full-adder/full-adder.v",
    "content": "// Solution to full adder challenge\n//\n// Inputs:\n//      pmod[2:0]   - pushbuttons (x3)\n//\n// Outputs:\n//      led[1:0]    - LEDs (x2)\n//\n// LED 0 turns on if 1 or 3 buttons are pressed. LED 1 turns on if 2 or 3\n// buttons are pressed.\n//\n// Date: October 25, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Full adder with button inputs\nmodule full_adder (\n\n    // Inputs\n    input   [2:0]   pmod,\n    \n    // Output\n    output  [1:0]   led\n);\n\n    // Wire (net) declarations (internal to module)\n    wire a;\n    wire b;\n    wire c_in;\n    wire a_xor_b;\n    \n    // A, B, and C_IN are inverted button logic\n    assign a = ~pmod[0];\n    assign b = ~pmod[1];\n    assign c_in = ~pmod[2];\n    \n    // Create intermediate wire (net)\n    assign a_xor_b = a ^ b;\n\n    // Create output logic\n    assign led[0] = a_xor_b ^ c_in;\n    assign led[1] = (a_xor_b & c_in) | (a & b);\n    \nendmodule"
  },
  {
    "path": "04-clocks-and-procedural-assignments/example-01-button-counter/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "04-clocks-and-procedural-assignments/example-01-button-counter/button-counter.pcf",
    "content": "# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\nset_io              led[2]  97\nset_io              led[3]  96\n\n# PMOD I/O\nset_io  -pullup yes pmod[0] 78\nset_io  -pullup yes pmod[1] 79"
  },
  {
    "path": "04-clocks-and-procedural-assignments/example-01-button-counter/button-counter.v",
    "content": "// Button counter\n//\n// Inputs:\n//      pmod[0]     - pushbutton (RESET)\n//      pmod[1]     - pushbutton (CLOCK)\n// Outputs:\n//      led[3:0]    - LEDs (count from 0x0 to 0xf)\n//\n// LEDs will count up in binary on each CLOCK button press. Note: there will\n// be a lot of button bounce, so don't worry if the numbers seem to skip around!\n//\n// Date: October 26, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Count up on each button press and display on LEDs\nmodule button_counter (\n\n    // Inputs\n    input       [1:0]   pmod,\n    \n    // Outputs\n    output  reg [3:0]   led\n);\n\n    wire rst;\n    wire clk;\n\n    // Reset is the inverse of the first button\n    assign rst = ~pmod[0];\n\n    // Clock signal is the inverse of second button\n    assign clk = ~pmod[1];\n\n    // Count up on clock rising edge or reset on button push\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            led <= 4'b0;\n        end else begin\n            led <= led + 1'b1;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "04-clocks-and-procedural-assignments/solution-clock-counter/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "04-clocks-and-procedural-assignments/solution-clock-counter/clock-counter.pcf",
    "content": "# Oscillator\nset_io              clk     21\n\n# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\nset_io              led[2]  97\nset_io              led[3]  96\n\n# PMOD I/O\nset_io  -pullup yes rst_btn 78"
  },
  {
    "path": "04-clocks-and-procedural-assignments/solution-clock-counter/clock-counter.v",
    "content": "// Clock-divided counter\n//\n// Inputs:  \n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n//      \n// Outputs:\n//      led[3:0]    - LEDs (count from 0x0 to 0xf)\n//\n// LEDs will display a binary number that increments by one each second.\n//\n// Date: October 26, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Count up each second\nmodule clock_counter (\n\n    // Inputs\n    input               clk,\n    input               rst_btn,\n    \n    // Outputs\n    output  reg [3:0]   led\n);\n\n    wire rst;\n    reg div_clk;\n    reg [31:0] count;\n    localparam [31:0] max_count = 6000000 - 1;\n\n    // Reset is the inverse of the reset button\n    assign rst = ~rst_btn;\n\n    // Count up on (divided) clock rising edge or reset on button push\n    always @ (posedge div_clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            led <= 4'b0;\n        end else begin\n            led <= led + 1'b1;\n        end\n    end\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count <= 32'b0;\n        end else if (count == max_count) begin\n            count <= 32'b0;\n            div_clk <= ~div_clk;\n        end else begin\n            count <= count + 1;\n        end\n    end\n    \nendmodule\n"
  },
  {
    "path": "05-finite-state-machines/example-01-moore-fsm/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "05-finite-state-machines/example-01-moore-fsm/moore-fsm.pcf",
    "content": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]      98\nset_io              led[2]      97\nset_io              led[3]      96\nset_io              done_sig    95\n\n# PMOD I/O\nset_io  -pullup yes rst_btn     78\nset_io  -pullup yes go_btn      79"
  },
  {
    "path": "05-finite-state-machines/example-01-moore-fsm/moore-fsm.v",
    "content": "// Count up on button press and stop (Moore state machine)\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n//      go_btn      - pushbutton (GO)\n// \n// Outputs:\n//      led[3:0]    - LEDs (count from 0x0 to 0xf)\n//      done_sig    - LED that flashes once when counting is done_sig\n// \n// Press GO button to start counting. When max value (0xf) is reached, green\n// LED will flash once, and the state machine will return to the Idle state.\n//\n// Date: November 4, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// State machine that counts up when button is pressed\nmodule moore_fsm (\n\n    // Inputs\n    input               clk,\n    input               rst_btn,\n    input               go_btn,\n    \n    // Outputs\n    output  reg [3:0]   led,\n    output  reg         done_sig\n);\n\n    // States\n    localparam  STATE_IDLE      = 2'd0;\n    localparam  STATE_COUNTING  = 2'd1;\n    localparam  STATE_DONE      = 2'd2;\n    \n    // Max counts for clock divider and counter\n    localparam  MAX_CLK_COUNT   = 24'd1500000;\n    localparam  MAX_LED_COUNT   = 4'hF;\n    \n    // Internal signals\n    wire rst;\n    wire go;\n    \n    // Internal storage elements\n    reg         div_clk;\n    reg [1:0]   state;\n    reg [23:0]  clk_count;\n    \n    // Invert active-low buttons\n    assign rst = ~rst_btn;\n    assign go = ~go_btn;\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            clk_count <= 24'b0;\n        end else if (clk_count == MAX_CLK_COUNT) begin\n            clk_count <= 24'b0;\n            div_clk <= ~div_clk;\n        end else begin\n            clk_count <= clk_count + 1;\n        end\n    end\n    \n    // State transition logic\n    always @ (posedge div_clk or posedge rst) begin\n    \n        // On reset, return to idle state\n        if (rst == 1'b1) begin\n            state <= STATE_IDLE;\n            \n        // Define the state transitions\n        end else begin\n            case (state)\n            \n                // Wait for go button to be pressed\n                STATE_IDLE: begin\n                    if (go == 1'b1) begin\n                        state <= STATE_COUNTING;\n                    end\n                end\n                \n                // Go from counting to done if counting reaches max\n                STATE_COUNTING: begin\n                    if (led == MAX_LED_COUNT) begin\n                        state <= STATE_DONE;\n                    end\n                end\n                \n                // Spend one clock cycle in done state\n                STATE_DONE: state <= STATE_IDLE;\n                \n                // Go to idle if in unknown state\n                default: state <= STATE_IDLE;\n            endcase\n        end\n    end\n    \n    // Handle the LED counter\n    always @ (posedge div_clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            led <= 4'd0;\n        end else begin\n            if (state == STATE_COUNTING) begin\n                led <= led + 1;\n            end else begin\n                led <= 4'd0;\n            end\n        end\n    end\n    \n    // Handle done LED output\n    always @ ( * ) begin\n        if (state == STATE_DONE) begin\n            done_sig = 1'b1;\n        end else begin\n            done_sig = 1'b0;\n        end\n    end\n    \nendmodule\n"
  },
  {
    "path": "05-finite-state-machines/example-02-mealy-fsm/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "05-finite-state-machines/example-02-mealy-fsm/mealy-fsm.pcf",
    "content": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]      98\nset_io              led[2]      97\nset_io              led[3]      96\nset_io              done_sig    95\n\n# PMOD I/O\nset_io  -pullup yes rst_btn     78\nset_io  -pullup yes go_btn      79"
  },
  {
    "path": "05-finite-state-machines/example-02-mealy-fsm/mealy-fsm.v",
    "content": "// Count up on button press and stop (Mealy state machine)\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n//      go_btn      - pushbutton (GO)\n// \n// Outputs:\n//      led[3:0]    - LEDs (count from 0x0 to 0xf)\n//      done_sig    - LED that flashes once when counting is done_sig\n// \n// Press GO button to start counting. When max value (0xf) is reached, green\n// LED will flash once, and the state machine will return to the Idle state.\n//\n// Date: November 4, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// State machine that counts up when button is pressed\nmodule mealy_fsm (\n\n    // Inputs\n    input               clk,\n    input               rst_btn,\n    input               go_btn,\n    \n    // Outputs\n    output  reg [3:0]   led,\n    output  reg         done_sig\n);\n\n    // States\n    localparam  STATE_IDLE      = 1'd0;\n    localparam  STATE_COUNTING  = 1'd1;\n    \n    // Max counts for clock divider and counter\n    localparam  MAX_CLK_COUNT   = 24'd1500000;\n    localparam  MAX_LED_COUNT   = 4'hF;\n    \n    // Internal signals\n    wire rst;\n    wire go;\n    \n    // Internal storage elements\n    reg         div_clk;\n    reg         state;\n    reg [23:0]  clk_count;\n    \n    // Invert active-low buttons\n    assign rst = ~rst_btn;\n    assign go = ~go_btn;\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            clk_count <= 24'b0;\n        end else if (clk_count == MAX_CLK_COUNT) begin\n            clk_count <= 24'b0;\n            div_clk <= ~div_clk;\n        end else begin\n            clk_count <= clk_count + 1;\n        end\n    end\n    \n    // State transition logic\n    always @ (posedge div_clk or posedge rst) begin\n    \n        // On reset, return to idle state\n        if (rst == 1'b1) begin\n            state <= STATE_IDLE;\n            \n        // Define the state transitions\n        end else begin\n            case (state)\n            \n                // Wait for go button to be pressed\n                STATE_IDLE: begin\n                    done_sig <= 1'b0;\n                    if (go == 1'b1) begin\n                        state <= STATE_COUNTING;\n                    end\n                end\n                \n                // Go from counting to done if counting reaches max\n                STATE_COUNTING: begin\n                    if (led == MAX_LED_COUNT) begin\n                        done_sig <= 1'b1;\n                        state <= STATE_IDLE;\n                    end\n                end\n                \n                // Go to idle if in unknown state\n                default: state <= STATE_IDLE;\n            endcase\n        end\n    end\n    \n    // Handle the LED counter\n    always @ (posedge div_clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            led <= 4'd0;\n        end else begin\n            if (state == STATE_COUNTING) begin\n                led <= led + 1;\n            end else begin\n                led <= 4'd0;\n            end\n        end\n    end\n    \nendmodule\n            \n    \n      \n       \n    "
  },
  {
    "path": "05-finite-state-machines/solution-button-debouncing/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "05-finite-state-machines/solution-button-debouncing/solution-button-debouncing.pcf",
    "content": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]      98\nset_io              led[2]      97\nset_io              led[3]      96\n\n# PMOD I/O\nset_io  -pullup yes rst_btn     78\nset_io  -pullup yes inc_btn     79"
  },
  {
    "path": "05-finite-state-machines/solution-button-debouncing/solution-button-debouncing.v",
    "content": "// One possible way to debounce a button press (using a Moore state machine)\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n//      inc_btn     - pushbutton (INCREMENT)\n// \n// Outputs:\n//      led[3:0]    - LEDs (count from 0x0 to 0xf)\n// \n// One press of the increment button should correspond to one and only one\n// increment of the counter. Use a state machine to identify the edge on the\n// button line, wait 40 ms, and sample again to see if the button is still\n// pressed.\n//\n// Date: November 5, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Use a state machine to debounce the button, which increments a counter\nmodule debounced_counter (\n\n    // Inputs\n    input               clk,\n    input               rst_btn,\n    input               inc_btn,\n    \n    // Outputs\n    output  reg [3:0]   led\n);\n\n    // States\n    localparam STATE_HIGH       = 2'd0;\n    localparam STATE_LOW        = 2'd1;    \n    localparam STATE_WAIT       = 2'd2;\n    localparam STATE_PRESSED    = 2'd3;\n    \n    // Max counts for wait state (40 ms with 12 MHz clock)\n    localparam MAX_CLK_COUNT    = 20'd480000 - 1;\n    \n    // Internal signals\n    wire rst;\n    wire inc;\n    \n    // Internal storage elements\n    reg [1:0]   state;\n    reg [19:0]  clk_count;\n    \n    // Invert active-low buttons\n    assign rst = ~rst_btn;\n    assign inc = ~inc_btn;\n    \n    // State transition logic\n    always @ (posedge clk or posedge rst) begin\n    \n        // On reset, return to idle state and restart counters\n        if (rst == 1'b1) begin\n            state <= STATE_HIGH;\n            led <= 4'd0;\n            \n        // Define the state transitions\n        end else begin\n            case (state)\n            \n                // Wait for increment signal to go from high to low\n                STATE_HIGH: begin\n                    if (inc == 1'b0) begin\n                        state <= STATE_LOW;\n                    end\n                end\n            \n                // Wait for increment signal to go from low to high\n                STATE_LOW: begin\n                    if (inc == 1'b1) begin\n                        state <= STATE_WAIT;\n                    end\n                end\n                \n                // Wait for count to be done and sample button again\n                STATE_WAIT: begin\n                    if (clk_count == MAX_CLK_COUNT) begin\n                        if (inc == 1'b1) begin\n                            state <= STATE_PRESSED;\n                        end else begin\n                            state <= STATE_HIGH;\n                        end\n                    end\n                end\n                \n                // If button is still pressed, increment LED counter\n                STATE_PRESSED: begin\n                    led <= led + 1;\n                    state <= STATE_HIGH;\n                end\n                \n                    \n                // Default case: return to idle state\n                default: state <= STATE_HIGH;\n            endcase\n        end\n    end\n    \n    // Run counter if in wait state\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            clk_count <= 20'd0;\n        end else begin\n            if (state == STATE_WAIT) begin\n                clk_count <= clk_count + 1;\n            end else begin\n                clk_count <= 20'd0;\n            end\n        end\n    end\n    \nendmodule\n"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/clock-divider.v",
    "content": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum value of counter\n// \n// Inputs:\n//      clk         - Input clock\n//      rst         - Reset signal\n// \n// Outputs:\n//      out         - Divided clock output\n// \n// Toggles out line at a divided rate given clk input.\n//\n// Date: November 8, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Clock divider\nmodule clock_divider (\n\n    // Inputs\n    input       clk,\n    input       rst,\n    \n    // Outputs\n    output  reg out    \n);\n\n    // Parameters\n    parameter                   COUNT_WIDTH = 24;\n    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1;\n\n    // Internal signals\n    wire rst;\n    reg div_clk;\n    reg [COUNT_WIDTH:0] count;\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count <= 0;\n            out <= 0;\n        end else if (count == MAX_COUNT) begin\n            count <= 0;\n            out <= ~out;\n        end else begin\n            count <= count + 1;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/top-design.pcf",
    "content": "# Oscillator\nset_io              clk     21\n\n# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\n\n# PMOD I/O\nset_io  -pullup yes rst_btn 78"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/top-design.v",
    "content": "// Example of a top-level design with 2 different clocks.\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n// \n// Outputs:\n//      led[1:0]    - LEDs\n// \n// LED[0] should flash at 4 Hz and LED[1] should flash at 1 Hz.\n//\n// Date: November 8, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Top-level design that produces 2 different divided clocks\nmodule top_design (\n\n    // Inputs\n    input           clk,\n    input           rst_btn,\n    \n    // Outputs\n    output  [1:0]   led         // Not reg element!\n);\n\n    // Internal signals\n    wire rst;\n    \n    // Invert active-low button\n    assign rst = ~rst_btn;\n\n    // Instantiate the first clock divider module\n    clock_divider div_1 (\n        .clk(clk), \n        .rst(rst), \n        .out(led[0])\n    );\n    defparam div_1.COUNT_WIDTH  = 32;\n    defparam div_1.MAX_COUNT    = 1500000 - 1;\n    \n    // Instantiate the second clock divider module\n    clock_divider div_2 (\n        .clk(clk),\n        .rst(rst),\n        .out(led[1])\n    );\n                    \nendmodule"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/clock-divider.v",
    "content": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum value of counter\n// \n// Inputs:\n//      clk         - Input clock\n//      rst         - Reset signal\n// \n// Outputs:\n//      out         - Divided clock output\n// \n// Toggles out line at a divided rate given clk input.\n//\n// Date: November 8, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Clock divider\nmodule clock_divider #(\n\n    // Parameters\n    parameter                   COUNT_WIDTH = 24,\n    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1\n) (\n\n    // Inputs\n    input       clk,\n    input       rst,\n    \n    // Outputs\n    output  reg out    \n);\n\n    // Internal signals\n    wire rst;\n    reg div_clk;\n    reg [COUNT_WIDTH:0] count;\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count <= 0;\n            out <= 0;\n        end else if (count == MAX_COUNT) begin\n            count <= 0;\n            out <= ~out;\n        end else begin\n            count <= count + 1;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/top-design.pcf",
    "content": "# Oscillator\nset_io              clk     21\n\n# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\n\n# PMOD I/O\nset_io  -pullup yes rst_btn 78"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/top-design.v",
    "content": "// Example of a top-level design with 2 different clocks.\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n// \n// Outputs:\n//      led[1:0]    - LEDs\n// \n// LED[0] should flash at 4 Hz and LED[1] should flash at 1 Hz.\n//\n// Date: November 8, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Top-level design that produces 2 different divided clocks\nmodule top_design (\n\n    // Inputs\n    input           clk,\n    input           rst_btn,\n    \n    // Outputs\n    output  [1:0]   led         // Not reg element!\n);\n\n    // Internal signals\n    wire rst;\n    \n    // Invert active-low button\n    assign rst = ~rst_btn;\n\n    // Instantiate the first clock divider module\n    clock_divider #(.COUNT_WIDTH(32), .MAX_COUNT(1500000 - 1)) div_1 (\n        .clk(clk), \n        .rst(rst), \n        .out(led[0])\n    );\n    \n    // Instantiate the second clock divider module\n    clock_divider div_2 (\n        .clk(clk),\n        .rst(rst),\n        .out(led[1])\n    );\n                    \nendmodule"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/clock-divider.v",
    "content": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum value of counter\n// \n// Inputs:\n//      clk         - Input clock\n//      rst         - Reset signal\n// \n// Outputs:\n//      out         - Divided clock output\n// \n// Toggles out line at a divided rate given clk input.\n//\n// Date: November 8, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Clock divider\nmodule clock_divider #(\n\n    // Parameters\n    parameter                   COUNT_WIDTH = 24,\n    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1\n) (\n\n    // Inputs\n    input       clk,\n    input       rst,\n    \n    // Outputs\n    output  reg out    \n);\n\n    // Internal signals\n    wire rst;\n    reg div_clk;\n    reg [COUNT_WIDTH:0] count;\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count <= 0;\n            out <= 0;\n        end else if (count == MAX_COUNT) begin\n            count <= 0;\n            out <= ~out;\n        end else begin\n            count <= count + 1;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/count-up-down-top.v",
    "content": "// One possible solution to the count up and down challenge\n//\n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n//\n// Outputs:\n//      led[3:0]    - LEDs (connected to counter outputs)\n//\n// LEDs continuously count up and down.\n//\n// Date: November 9, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Top-level design that controls the clock divider and counter FSMs\nmodule count_up_down_top (\n\n    // Inputs\n    input               clk,\n    input               rst_btn,\n    \n    // Outputs\n    output  reg [3:0]   led\n);\n\n    // Internal signals\n    wire            rst;\n    wire            div_clk;\n    wire            up_done;\n    wire            down_done;\n    wire    [3:0]   up_out;\n    wire    [3:0]   down_out;\n    \n    // Storage elements\n    reg             init_go;\n    reg             counting_up;\n    \n    // Invert active-low buttons\n    assign rst = ~rst_btn;\n    \n    // Use the reset button to start the endless loop of counters\n    always @ (posedge div_clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            init_go <= 1'b1;\n        end else begin\n            init_go <= 1'b0;\n        end\n    end\n    \n    // Remember if we're counting up or down\n    always @ (posedge div_clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            counting_up <= 1'b1;\n        end else begin\n            if (up_done == 1'b1) begin\n                counting_up <= 1'b0;\n            end else if (down_done == 1'b1) begin\n                counting_up <= 1'b1;\n            end\n        end\n    end\n    \n    // Multiplexer to switch which counter is controlling the LEDs\n    always @ ( * ) begin\n        if (counting_up == 1'b1) begin\n            led = up_out;\n        end else begin\n            led = down_out;\n        end\n    end\n    \n    // Clock divider\n    clock_divider #(.COUNT_WIDTH(24), .MAX_COUNT(1500000 - 1)) div (\n        .clk(clk),\n        .rst(rst),\n        .out(div_clk)\n    );\n    \n    // Counter (up)\n    counter_fsm #(.COUNT_UP(1), .MAX_COUNT(4'hF)) up_counter (\n        .clk(div_clk),\n        .rst(rst),\n        .go(down_done | init_go),\n        .out(up_out),\n        .done(up_done)\n    );\n    \n    // Counter (down)\n    counter_fsm #(.COUNT_UP(0), .MAX_COUNT(4'hF)) down_counter (\n        .clk(div_clk),\n        .rst(rst),\n        .go(up_done),\n        .out(down_out),\n        .done(down_done)\n    );\n    \nendmodule"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/count-up-down.pcf",
    "content": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]      98\nset_io              led[2]      97\nset_io              led[3]      96\n\n# PMOD I/O\nset_io  -pullup yes rst_btn     78"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/counter-fsm.v",
    "content": "// Count up on button signal and stop.\n//\n// Parameters:\n//      COUNT_UP    - 1 to count up, 0 to count down\n//      MAX_COUNT   - Maximum number to count to\n// \n// Inputs:\n//      clk         - Clock input to module\n//      rst         - Reset signal to clear state machine and counter\n//      go          - Go signal to start state machine\n// \n// Outputs:\n//      out[3:0]    - Bus that counts from 0x0 to 0xf or 0xf to 0x0\n//      done        - Signal that pulses on 1 clock cycle when FSM is complete\n// \n// Send rising edge on go input to start counter. If up is 1, counter will\n// count up. Otherwise, it will count down. \n//\n// Date: November 9, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Mealy state machine that counts when go signal is sent\nmodule counter_fsm #(\n\n    // Parameters\n    parameter   COUNT_UP = 1'b1,    // 1'b1 to count up\n    parameter   MAX_COUNT = 4'hF    // Maximum number to count to\n) (\n\n    // Inputs\n    input               clk,\n    input               rst,\n    input               go,\n    \n    // Outputs\n    output  reg [3:0]   out,\n    output  reg         done\n);\n\n    // States\n    localparam  STATE_IDLE      = 1'd0;\n    localparam  STATE_COUNTING  = 1'd1;\n    \n    // Internal storage elements\n    reg         state;\n    \n    // State transition logic\n    always @ (posedge clk or posedge rst) begin\n    \n        // On reset, return to idle state\n        if (rst == 1'b1) begin\n            state <= STATE_IDLE;\n            \n        // Define the state transitions\n        end else begin\n            case (state)\n            \n                // Wait for go signal\n                STATE_IDLE: begin\n                    done <= 1'b0;\n                    if (go == 1'b1) begin\n                        state <= STATE_COUNTING;\n                    end\n                end\n                \n                // Go from counting to done if counting reaches max\n                STATE_COUNTING: begin\n                    if (COUNT_UP == 1'b1 && out == MAX_COUNT) begin\n                        done <= 1'b1;\n                        state <= STATE_IDLE;\n                    end else if (COUNT_UP == 1'b0 && out == 0) begin\n                        done <= 1'b1;\n                        state <= STATE_IDLE;\n                    end\n                end\n                \n                // Go to idle if in unknown state\n                default: state <= STATE_IDLE;\n            endcase\n        end\n    end\n    \n    // Handle the counter output\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            out <= 4'd0;\n        end else begin\n            case (state)\n            \n                // Start counter at the right value\n                STATE_IDLE: begin\n                    if (COUNT_UP == 1'b1) begin\n                        out <= 4'd0;\n                    end else begin\n                        out <= MAX_COUNT;\n                    end\n                end\n                \n                // Count up or down\n                STATE_COUNTING: begin\n                    if (COUNT_UP == 1'b1) begin\n                        if (out != MAX_COUNT) out <= out + 1;\n                    end else begin\n                        if (out != 4'h0) out <= out - 1;\n                    end\n                end\n                \n                default: out <= out;\n            endcase\n        end\n    end\n    \nendmodule\n"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/clk-div_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Nov 11 19:42:09 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\07-simulation-and-testbenches\\example-01-testbench\\clk-div_tb.vcd\"\n[dumpfile_mtime] \"Thu Nov 11 19:40:47 2021\"\n[dumpfile_size] 4709\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\07-simulation-and-testbenches\\example-01-testbench\\clk-div_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] -1 -1\n*-22.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[treeopen] clock_divider_tb.\n[sst_width] 211\n[signals_width] 110\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\nclock_divider_tb.div_1.clk\n@22\nclock_divider_tb.div_1.count[4:0]\n@28\nclock_divider_tb.div_1.out\nclock_divider_tb.div_1.rst\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/clk-div_tb.v",
    "content": "// Testbench for clock divider\n//\n// Date: November 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Defines timescale for simulation: <time_unit> / <time_precision>\n`timescale 1 ns / 10 ps\n\n// Define our testbench\nmodule clock_divider_tb();\n\n    // Internal signals\n    wire    out;\n\n    // Storage elements (set initial values to 0)\n    reg     clk = 0;\n    reg     rst = 0;            \n\n    // Simulation time: 10000 * 1 ns = 10 us\n    localparam DURATION = 10000;\n    \n    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz\n    always begin\n        \n        // Delay for 41.67 time units\n        // 10 ps precision means that 41.667 is rounded to 41.67\n        #41.667\n        \n        // Toggle clock line\n        clk = ~clk;\n    end\n    \n    // Instantiate the unit under test (UUT)\n    clock_divider #(.COUNT_WIDTH(4), .MAX_COUNT(6 - 1)) uut (\n        .clk(clk),\n        .rst(rst),\n        .out(out)\n    );\n    \n    // Pulse reset line high at the beginning\n    initial begin\n        #10\n        rst = 1'b1;\n        #1\n        rst = 1'b0;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"clk-div_tb.vcd\");\n        $dumpvars(0, clock_divider_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/clock-divider.v",
    "content": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum value of counter\n// \n// Inputs:\n//      clk         - Input clock\n//      rst         - Reset signal\n// \n// Outputs:\n//      out         - Divided clock output\n// \n// Toggles out line at a divided rate given clk input.\n//\n// Date: November 8, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Clock divider\nmodule clock_divider (\n\n    // Inputs\n    input       clk,\n    input       rst,\n    \n    // Outputs\n    output  reg out    \n);\n\n    // Parameters\n    parameter                   COUNT_WIDTH = 24;\n    parameter [COUNT_WIDTH-1:0]   MAX_COUNT   = 6000000 - 1;\n\n    // Internal signals\n    wire rst;\n    reg div_clk;\n    reg [COUNT_WIDTH:0] count;\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count <= 0;\n            out <= 0;\n        end else if (count == MAX_COUNT) begin\n            count <= 0;\n            out <= ~out;\n        end else begin\n            count <= count + 1;\n        end\n    end\n    \nendmodule\n"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing.v",
    "content": "// One possible way to debounce a button press (using a Moore state machine)\n//\n// Parameters:\n//      MAX_CLK_COUNT   - How long to wait (cycles) before sampling button again\n// \n// Inputs:\n//      clk             - Input clock\n//      rst_btn         - Pushbutton (RESET)\n//      inc_btn         - Pushbutton (INCREMENT)\n// \n// Outputs:\n//      led[3:0]        - LEDs (count from 0x0 to 0xf)\n// \n// One press of the increment button should correspond to one and only one\n// increment of the counter. Use a state machine to identify the edge on the\n// button line, wait 40 ms, and sample again to see if the button is still\n// pressed.\n//\n// Date: November 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Use a state machine to debounce the button, which increments a counter\nmodule debounced_counter #(\n\n    // Parameters\n    parameter MAX_CLK_COUNT     = 20'd480000 - 1\n) (\n\n    // Inputs\n    input               clk,\n    input               rst_btn,\n    input               inc_btn,\n    \n    // Outputs\n    output  reg [3:0]   led\n);\n\n    // States\n    localparam STATE_HIGH       = 2'd0;\n    localparam STATE_LOW        = 2'd1;    \n    localparam STATE_WAIT       = 2'd2;\n    localparam STATE_PRESSED    = 2'd3;\n    \n    // Internal signals\n    wire rst;\n    wire inc;\n    \n    // Internal storage elements\n    reg [1:0]   state;\n    reg [19:0]  clk_count;\n    \n    // Invert active-low buttons\n    assign rst = ~rst_btn;\n    assign inc = ~inc_btn;\n    \n    // State transition logic\n    always @ (posedge clk or posedge rst) begin\n    \n        // On reset, return to idle state and restart counters\n        if (rst == 1'b1) begin\n            state <= STATE_HIGH;\n            led <= 4'd0;\n            \n        // Define the state transitions\n        end else begin\n            case (state)\n            \n                // Wait for increment signal to go from high to low\n                STATE_HIGH: begin\n                    if (inc == 1'b0) begin\n                        state <= STATE_LOW;\n                    end\n                end\n            \n                // Wait for increment signal to go from low to high\n                STATE_LOW: begin\n                    if (inc == 1'b1) begin\n                        state <= STATE_WAIT;\n                    end\n                end\n                \n                // Wait for count to be done and sample button again\n                STATE_WAIT: begin\n                    if (clk_count == MAX_CLK_COUNT) begin\n                        if (inc == 1'b1) begin\n                            state <= STATE_PRESSED;\n                        end else begin\n                            state <= STATE_HIGH;\n                        end\n                    end\n                end\n                \n                // If button is still pressed, increment LED counter\n                STATE_PRESSED: begin\n                    led <= led + 1;\n                    state <= STATE_HIGH;\n                end\n                \n                    \n                // Default case: return to idle state\n                default: state <= STATE_HIGH;\n            endcase\n        end\n    end\n    \n    // Run counter if in wait state\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            clk_count <= 0;\n        end else begin\n            if (state == STATE_WAIT) begin\n                clk_count <= clk_count + 1;\n            end else begin\n                clk_count <= 0;\n            end\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Nov 11 22:58:44 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\07-simulation-and-testbenches\\solution-debounce-testbench\\button-debouncing_tb.vcd\"\n[dumpfile_mtime] \"Thu Nov 11 22:56:49 2021\"\n[dumpfile_size] 4760913\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\07-simulation-and-testbenches\\solution-debounce-testbench\\button-debouncing_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] -1 -1\n*-31.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[treeopen] button_debouncing_tb.\n[sst_width] 211\n[signals_width] 110\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\nbutton_debouncing_tb.uut.clk\nbutton_debouncing_tb.uut.inc_btn\n@29\nbutton_debouncing_tb.uut.state[1:0]\n@22\nbutton_debouncing_tb.uut.led[3:0]\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing_tb.v",
    "content": "// Testbench for button debounce design\n//\n// Date: November 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define timescale\n`timescale 1 us / 10 ps\n\n// Define our testbench\nmodule button_debouncing_tb();\n\n    // Internal signals\n    wire    [3:0]   out;\n    \n    // Storage elements (buttons are active low!)\n    reg             clk = 0;\n    reg             rst_btn = 1;\n    reg             inc_btn = 1;\n    integer         i;              // Used in for loop\n    integer         j;              // Used in for loop\n    integer         prev_inc;       // Previous increment button state\n    integer         nbounces;       // Holds random number\n    integer         rdelay;         // Holds random number\n    \n    // Simulation time: 10000 * 1 us = 10 ms\n    localparam DURATION = 10000;\n    \n    // Generate clock signal (about 12 MHz)\n    always begin\n        #0.04167\n        clk = ~clk;\n    end\n    \n    // Instantiate debounce/counter module (use about 400 us wait time)\n    debounced_counter #(.MAX_CLK_COUNT(4800 - 1)) uut (\n        .clk(clk),\n        .rst_btn(rst_btn),\n        .inc_btn(inc_btn),\n        .led(out)\n    );\n    \n    // Test control: pulse reset and create some (bouncing) button presses\n    initial begin\n    \n        // Pulse reset low to reset state machine\n        #10\n        rst_btn = 0;\n        #1\n        rst_btn = 1;\n        \n        // We can use for loops in simulation!\n        for (i = 0; i < 32; i = i + 1) begin\n        \n            // Wait some time before pressing button\n            #1000\n            \n            // Simulate a bouncy/noisy button press\n            // $urandom generates a 32-bit unsigned (pseudo) random number\n            // \"% 10\" is \"modulo 10\"\n            prev_inc = inc_btn;\n            nbounces = $urandom % 20;\n            for (j = 0; j < nbounces; j = j + 1) begin\n                #($urandom % 10)\n                inc_btn = ~inc_btn;\n            end\n            \n            // Make sure button ends up in the opposite state\n            inc_btn = ~prev_inc;\n        end\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"button-debouncing_tb.vcd\");\n        $dumpvars(0, button_debouncing_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/example-01-memory/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "08-memory/example-01-memory/memory.v",
    "content": "// Simple block RAM example\n// \n// Inputs:\n//      clk             - Input clock\n//      w_en            - Write enable\n//      r_en            - Read enable\n//      w_addr[3:0]     - Write address\n//      r_addr[3:0]     - Read address\n//      w_data[7:0]     - Data to be written\n// \n// Outputs:\n//      r_data[7:0]     - Data to be read\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Inferred block RAM\nmodule memory (\n\n    // Inputs\n    input               clk,\n    input               w_en,\n    input               r_en,\n    input       [3:0]   w_addr,\n    input       [3:0]   r_addr,\n    input       [7:0]   w_data,\n    \n    // Outputs\n    output  reg [7:0]   r_data\n);\n\n    // Declare memory\n    reg [7:0]  mem [0:15];\n    \n    // Interact with the memory block\n    always @ (posedge clk) begin\n    \n        // Write to memory\n        if (w_en == 1'b1) begin\n            mem[w_addr] <= w_data;\n        end\n        \n        // Read from memory\n        if (r_en == 1'b1) begin\n            r_data <= mem[r_addr];\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/example-01-memory/memory_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Nov 15 20:31:41 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\08-memory\\example-01-memory\\memory_tb.vcd\"\n[dumpfile_mtime] \"Mon Nov 15 20:31:26 2021\"\n[dumpfile_size] 4133\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\08-memory\\example-01-memory\\memory_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] -1 -1\n*-19.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[sst_width] 211\n[signals_width] 118\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\nmemory_tb.clk\n@22\nmemory_tb.r_addr[3:0]\nmemory_tb.r_data[7:0]\n@28\nmemory_tb.r_en\n@22\nmemory_tb.w_addr[3:0]\nmemory_tb.w_data[7:0]\n@28\nmemory_tb.w_en\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "08-memory/example-01-memory/memory_tb.v",
    "content": "// Testbench for memory\n//\n// First, read from address in memory (should be garbage or unknown). Next,\n// write to that location and read from it again. Output should match input.\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Defines timescale for simulation: <time_unit> / <time_precision>\n`timescale 1 ns / 10 ps\n\n// Define our testbench\nmodule memory_tb();\n\n    // Internal signals\n    wire    [7:0]  r_data;\n    \n\n    // Storage elements (set initial values to 0)\n    reg             clk = 0;\n    reg             w_en = 0;\n    reg             r_en = 0;\n    reg     [3:0]   w_addr;\n    reg     [3:0]   r_addr;\n    reg     [7:0]   w_data;\n\n    // Simulation time: 10000 * 1 ns = 10 us\n    localparam DURATION = 10000;\n    \n    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz\n    always begin\n        #41.67\n        clk = ~clk;\n    end\n    \n    // Instantiate the unit under test (UUT)\n    memory uut (\n        .clk(clk),\n        .w_en(w_en),\n        .r_en(r_en),\n        .w_addr(w_addr),\n        .r_addr(r_addr),\n        .w_data(w_data),\n        .r_data(r_data)\n    );\n    \n    // Run test: write to location and read value back\n    initial begin\n    \n        // Test 1: read from address 0x10 (should be garbage)\n        #(2 * 41.67)\n        r_addr = 'h0f;\n        r_en = 1;\n        #(2 * 41.67)\n        r_addr = 0;\n        r_en = 0;\n        \n        // Test 2: Write to address 0x0f and read it back\n        #(2 * 41.67)\n        w_addr = 'h0f;\n        w_data = 'hA5;\n        w_en = 1;\n        #(2 * 41.67)\n        w_addr = 0;\n        w_data = 0;\n        w_en = 0;\n        r_addr = 'h0f;\n        r_en = 1;\n        #(2 * 41.67)\n        r_addr = 0;\n        r_en = 0;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"memory_tb.vcd\");\n        $dumpvars(0, memory_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/example-01-memory/test.pcf",
    "content": "# Oscillator\nset_io  clk         21\n\n# Dummy ports\nset_io  w_en        44\nset_io  r_en        45\n\nset_io  w_addr[0]   78\nset_io  w_addr[1]   79\nset_io  w_addr[2]   80\nset_io  w_addr[3]   81\n\nset_io  r_addr[0]   87\nset_io  r_addr[1]   88\nset_io  r_addr[2]   90\nset_io  r_addr[3]   91\n\nset_io  w_data[0]   112\nset_io  w_data[1]   113\nset_io  w_data[2]   114\nset_io  w_data[3]   115\nset_io  w_data[4]   116\nset_io  w_data[5]   117\nset_io  w_data[6]   118\nset_io  w_data[7]   119\n\nset_io  r_data[0]   95\nset_io  r_data[1]   96\nset_io  r_data[2]   97\nset_io  r_data[3]   98\nset_io  r_data[4]   99\nset_io  r_data[5]   60\nset_io  r_data[6]   61\nset_io  r_data[7]   62\n"
  },
  {
    "path": "08-memory/example-02-memory-initialization/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "08-memory/example-02-memory-initialization/mem_init.txt",
    "content": "00\n01\n02\n03\n04\n05\n06\n07\nb8\nb9\nba\nbb\nbc\nbd\nbe\nbf"
  },
  {
    "path": "08-memory/example-02-memory-initialization/memory.v",
    "content": "// Simple block RAM example\n// \n// Inputs:\n//      clk             - Input clock\n//      w_en            - Write enable\n//      r_en            - Read enable\n//      w_addr[3:0]     - Write address\n//      r_addr[3:0]     - Read address\n//      w_data[7:0]     - Data to be written\n// \n// Outputs:\n//      r_data[7:0]     - Data to be read\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Inferred block RAM\nmodule memory #(\n\n    // Parameters\n    parameter   INIT_FILE = \"\"\n) (\n\n    // Inputs\n    input               clk,\n    input               w_en,\n    input               r_en,\n    input       [3:0]   w_addr,\n    input       [3:0]   r_addr,\n    input       [7:0]   w_data,\n    \n    // Outputs\n    output  reg [7:0]   r_data\n);\n\n    // Declare memory\n    reg [7:0]  mem [0:15];\n    \n    // Interact with the memory block\n    always @ (posedge clk) begin\n    \n        // Write to memory\n        if (w_en == 1'b1) begin\n            mem[w_addr] <= w_data;\n        end\n        \n        // Read from memory\n        if (r_en == 1'b1) begin\n            r_data <= mem[r_addr];\n        end\n    end\n    \n    // Initialization (if available)\n    initial if (INIT_FILE) begin\n        $readmemh(INIT_FILE, mem);\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/example-02-memory-initialization/memory_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Nov 15 20:27:07 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\08-memory\\example-02-memory-initialization\\memory_tb.vcd\"\n[dumpfile_mtime] \"Mon Nov 15 20:25:26 2021\"\n[dumpfile_size] 5178\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\08-memory\\example-02-memory-initialization\\memory_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] 1230 252\n*-20.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[sst_width] 211\n[signals_width] 118\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\nmemory_tb.clk\n@420\nmemory_tb.i\n@22\nmemory_tb.r_addr[3:0]\nmemory_tb.r_data[7:0]\n@28\nmemory_tb.r_en\n@22\nmemory_tb.w_addr[3:0]\nmemory_tb.w_data[7:0]\n@28\nmemory_tb.w_en\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "08-memory/example-02-memory-initialization/memory_tb.v",
    "content": "// Testbench for memory\n//\n// First, read from address in memory (should be garbage or unknown). Next,\n// write to that location and read from it again. Output should match input.\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Defines timescale for simulation: <time_unit> / <time_precision>\n`timescale 1 ns / 10 ps\n\n// Define our testbench\nmodule memory_tb();\n\n    // Internal signals\n    wire    [7:0]  r_data;\n    \n\n    // Storage elements (set initial values to 0)\n    reg             clk = 0;\n    reg             w_en = 0;\n    reg             r_en = 0;\n    reg     [3:0]   w_addr;\n    reg     [3:0]   r_addr;\n    reg     [7:0]   w_data;\n    integer         i;\n\n    // Simulation time: 10000 * 1 ns = 10 us\n    localparam DURATION = 10000;\n    \n    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz\n    always begin\n        #41.67\n        clk = ~clk;\n    end\n    \n    // Instantiate the unit under test (UUT)\n    memory #(.INIT_FILE(\"mem_init.txt\")) uut (\n        .clk(clk),\n        .w_en(w_en),\n        .r_en(r_en),\n        .w_addr(w_addr),\n        .r_addr(r_addr),\n        .w_data(w_data),\n        .r_data(r_data)\n    );\n    \n    // Run test: write to location and read value back\n    initial begin\n    \n        // Test 1: read initial values\n        for (i = 0; i < 16; i = i + 1) begin\n            #(2 * 41.67)\n            r_addr = i;\n            r_en = 1;\n            #(2 * 41.67)\n            r_addr = 0;\n            r_en = 0;\n        end\n        \n        // Test 2: Write to address 0x0f and read it back\n        #(2 * 41.67)\n        w_addr = 'h0f;\n        w_data = 'hA5;\n        w_en = 1;\n        #(2 * 41.67)\n        w_addr = 0;\n        w_data = 0;\n        w_en = 0;\n        r_addr = 'h0f;\n        r_en = 1;\n        #(2 * 41.67)\n        r_addr = 0;\n        r_en = 0;\n        \n        // Test 3: Read and write at same time\n        #(2 * 41.67)\n        w_addr = 'h0a;\n        w_data = 'hef;\n        w_en = 1;\n        r_addr = 'h0a;\n        r_en = 1;\n        #(2 * 41.67)\n        w_addr = 0;\n        w_data = 0;\n        w_en = 0;\n        r_addr = 0;\n        r_en = 0;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"memory_tb.vcd\");\n        $dumpvars(0, memory_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/example-02-memory-initialization/test.pcf",
    "content": "# Oscillator\nset_io  clk         21\n\n# Dummy ports\nset_io  w_en        44\nset_io  r_en        45\n\nset_io  w_addr[0]   78\nset_io  w_addr[1]   79\nset_io  w_addr[2]   80\nset_io  w_addr[3]   81\n\nset_io  r_addr[0]   87\nset_io  r_addr[1]   88\nset_io  r_addr[2]   90\nset_io  r_addr[3]   91\n\nset_io  w_data[0]   112\nset_io  w_data[1]   113\nset_io  w_data[2]   114\nset_io  w_data[3]   115\nset_io  w_data[4]   116\nset_io  w_data[5]   117\nset_io  w_data[6]   118\nset_io  w_data[7]   119\n\nset_io  r_data[0]   95\nset_io  r_data[1]   96\nset_io  r_data[2]   97\nset_io  r_data[3]   98\nset_io  r_data[4]   99\nset_io  r_data[5]   60\nset_io  r_data[6]   61\nset_io  r_data[7]   62\n"
  },
  {
    "path": "08-memory/solution-sequencer/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "08-memory/solution-sequencer/clock-divider.v",
    "content": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum value of counter\n// \n// Inputs:\n//      clk         - Input clock\n//      rst         - Reset signal\n// \n// Outputs:\n//      out         - Divided clock output\n// \n// Toggles out line at a divided rate given clk input.\n//\n// Date: November 8, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Clock divider\nmodule clock_divider #(\n\n    // Parameters\n    parameter                   COUNT_WIDTH = 24,\n    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1\n) (\n\n    // Inputs\n    input       clk,\n    input       rst,\n    \n    // Outputs\n    output  reg out    \n);\n\n    // Internal signals\n    wire rst;\n    reg div_clk;\n    reg [COUNT_WIDTH:0] count;\n    \n    // Clock divider\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count <= 0;\n            out <= 0;\n        end else if (count == MAX_COUNT) begin\n            count <= 0;\n            out <= ~out;\n        end else begin\n            count <= count + 1;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/solution-sequencer/debouncer.v",
    "content": "// One possible way to debounce a button press (using a Moore state machine)\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst         - reset signal\n//      in          - input signal\n// \n// Outputs:\n//      out         - output signal (debounced)\n// \n// Single pulse sent on out when in signal goes high for some time.\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Use a state machine to debounce a button\nmodule debouncer #(\n\n    // Max counts for wait state (40 ms with 12 MHz clock)\n    parameter                   COUNT_WIDTH     = 20,\n    parameter [COUNT_WIDTH:0]   MAX_CLK_COUNT   = 480000 - 1\n) (\n\n    // Inputs\n    input               clk,\n    input               rst,\n    input               in,\n    \n    // Outputs\n    output  reg         out\n);\n\n    // States\n    localparam  STATE_HIGH      = 2'd0;\n    localparam  STATE_LOW       = 2'd1;    \n    localparam  STATE_WAIT      = 2'd2;\n    localparam  STATE_PRESSED   = 2'd3;\n    \n    // Internal storage elements\n    reg [1:0]           state;\n    reg [COUNT_WIDTH:0] clk_count;\n    \n    // State transition logic\n    always @ (posedge clk or posedge rst) begin\n    \n        // On reset, return to idle state\n        if (rst == 1'b1) begin\n            state <= STATE_HIGH;\n            out <= 1'b0;\n            \n        // Define the state transitions\n        end else begin\n            case (state)\n            \n                // Wait for increment signal to go from high to low\n                STATE_HIGH: begin\n                    out <= 1'b0;\n                    if (in == 1'b0) begin\n                        state <= STATE_LOW;\n                    end\n                end\n                \n                // Wait for increment signal to go from low to high\n                STATE_LOW: begin\n                    if (in == 1'b1) begin\n                        state <= STATE_WAIT;\n                    end\n                end\n                \n                // Wait for count to be done and sample button again\n                STATE_WAIT: begin\n                    if (clk_count == MAX_CLK_COUNT) begin\n                        if (in == 1'b1) begin\n                            state <= STATE_PRESSED;\n                        end else begin\n                            state <= STATE_HIGH;\n                        end\n                    end\n                end\n                \n                // If button is still pressed\n                STATE_PRESSED: begin\n                    out <= 1'b1;\n                    state <= STATE_HIGH;\n                end\n                \n                    \n                // Default case: return to idle state\n                default: state <= STATE_HIGH;\n            endcase\n        end\n    end\n    \n    // Run counter if in wait state\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            clk_count <= 0;\n        end else begin\n            if (state == STATE_WAIT) begin\n                clk_count <= clk_count + 1;\n            end else begin\n                clk_count <= 0;\n            end\n        end\n    end\n    \nendmodule\n"
  },
  {
    "path": "08-memory/solution-sequencer/mem_init.txt",
    "content": "0\n0\n0\n0\n1\n1\n1\n1"
  },
  {
    "path": "08-memory/solution-sequencer/memory.v",
    "content": "// Simple block RAM example\n// \n// Inputs:\n//      clk             - Input clock\n//      w_en            - Write enable\n//      r_en            - Read enable\n//      w_addr[x:0]     - Write address\n//      r_addr[x:0]     - Read address\n//      w_data[x:0]     - Data to be written\n// \n// Outputs:\n//      r_data[x:0]     - Data to be read\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Inferred block RAM\nmodule memory #(\n\n    // Parameters\n    parameter   MEM_WIDTH = 16,\n    parameter   MEM_DEPTH = 256,\n    parameter   INIT_FILE = \"\"\n) (\n\n    // Inputs\n    input               clk,\n    input               w_en,\n    input               r_en,\n    input       [ADDR_WIDTH - 1:0]   w_addr,\n    input       [ADDR_WIDTH - 1:0]   r_addr,\n    input       [MEM_WIDTH - 1:0]  w_data,\n    \n    // Outputs\n    output  reg [MEM_WIDTH - 1:0]  r_data\n);\n\n    // Calculate the number of bits required for the address\n    localparam  ADDR_WIDTH = $clog2(MEM_DEPTH);\n\n    // Declare memory\n    reg [MEM_WIDTH - 1:0]  mem [0:MEM_DEPTH - 1];\n    \n    // Interact with the memory block\n    always @ (posedge clk) begin\n        \n        // Write to memory\n        if (w_en) begin\n            mem[w_addr] <= w_data;\n        end\n        \n        // Read from memory\n        if (r_en) begin\n            r_data <= mem[r_addr];\n        end\n    end\n    \n    // Initialization (if available)\n    initial if (INIT_FILE) begin\n        $readmemh(INIT_FILE, mem);\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top.pcf",
    "content": "# Oscillator\nset_io              clk             21\n\n# LEDs\nset_io              led[0]          99\nset_io              led[1]          98\nset_io              unused_led[0]   97\nset_io              unused_led[1]   96\nset_io              unused_led[2]   95\n\n# PMOD I/O\nset_io  -pullup yes rst_btn         78\nset_io  -pullup yes set_btn         79\nset_io  -pullup yes ptn_0_btn       80\nset_io  -pullup yes ptn_1_btn       81"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top.v",
    "content": "// Top-level design for sequencer\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n//      set_btn     - pushbutton (SET value at next memory address)\n//      ptn_0_btn   - pushbutton (PATTERN[0] for sequence)\n//      ptn_1_btn   - pushbutton (PATTERN[1] for sequence)\n// \n// Outputs:\n//      led[1:0]    - LEDs\n// \n// Push RESET to set everything to 0. Hold PATTERN[0] and/or PATTERN[1] and \n// press SET to record value in memory. Continue doing this for up to 8 memory\n// locations. Sequence will play on LEDs and loop forever.\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Top-level design for the sequencer\nmodule sequencer_top #(\n\n    // Parameters\n    parameter   DEBOUNCE_COUNTS = 480000 - 1,   // Counts for debounce wait\n    parameter   STEP_COUNTS = 6000000 - 1,      // Clock cycles between steps\n    parameter   NUM_STEPS = 8                   // Number of steps\n\n) (\n\n    // Inputs\n    input               clk,\n    input               rst_btn,\n    input               set_btn,\n    input               ptn_0_btn,\n    input               ptn_1_btn,\n    \n    // Outputs\n    output  reg [1:0]   led,\n    output      [2:0]   unused_led\n);\n    \n    // Internal signals\n    wire            rst;\n    wire            set;\n    wire            set_d;\n    wire    [1:0]   ptn;\n    wire            div_clk;\n    wire    [1:0]   r_data;\n    \n    // Storage elements (initialize some values)\n    reg             w_en = 0;\n    reg             r_en = 1'b1;    // Always high!\n    reg     [2:0]   w_addr = 0;\n    reg     [2:0]   r_addr;\n    reg     [1:0]   w_data;\n    reg     [2:0]   step_counter;\n    reg     [2:0]   mem_ptr = 0;\n    \n    // Turn off unused LEDs\n    assign unused_led = 3'b000;\n    \n    // Invert active-low buttons\n    assign rst = ~rst_btn;\n    assign set = ~set_btn;\n    assign ptn[0] = ~ptn_0_btn;\n    assign ptn[1] = ~ptn_1_btn;\n    \n    // Clock divider\n    clock_divider #(\n        .COUNT_WIDTH(24), \n        .MAX_COUNT(STEP_COUNTS)\n    ) div (\n        .clk(clk),\n        .rst(rst),\n        .out(div_clk)\n    );\n    \n    // Button debouncer for set buttons\n    debouncer #(\n        .COUNT_WIDTH(24),\n        .MAX_CLK_COUNT(DEBOUNCE_COUNTS)\n    ) set_debouncer (\n        .clk(clk),\n        .rst(rst),\n        .in(set),\n        .out(set_d)\n    );\n    \n    // Memory unit\n    memory #(   \n        .MEM_WIDTH(2), \n        .MEM_DEPTH(NUM_STEPS), \n        .INIT_FILE(\"mem_init.txt\")\n    ) mem (\n        .clk(clk),\n        .w_en(w_en),\n        .r_en(r_en),\n        .w_addr(w_addr),\n        .r_addr(r_addr),\n        .w_data(w_data),\n        .r_data(r_data)\n    );\n    \n    // Read from memory each divided clock cycle\n    always @ (posedge div_clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            led <= 0;\n            r_addr <= 0;\n            step_counter <= 0;\n        end else begin\n            r_addr <= step_counter;\n            step_counter <= step_counter + 1;\n            led <= r_data;\n        end\n    end\n    \n    // Register write data as soon as debounced set signal goes high\n    always @ (posedge set_d) begin\n        w_data <= ptn;\n    end\n    \n    // Handle writing pattern to memory\n    always @ (posedge clk or posedge rst) begin\n    \n        // Reset memory address pointer and write enable signal\n        if (rst == 1'b1) begin\n            mem_ptr <= 0;\n            w_en <= 1'b0;\n            \n        // Set write enable high and increment memory pointer\n        end else if (set_d == 1'b1) begin\n            w_addr <= mem_ptr;\n            w_en <= 1'b1;\n            mem_ptr <= mem_ptr + 1;\n        \n        // Reset write enable signal\n        end else begin\n            w_en <= 1'b0;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Tue Nov 16 17:21:28 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\08-memory\\solution-sequencer\\sequencer-top_tb.vcd\"\n[dumpfile_mtime] \"Tue Nov 16 17:20:28 2021\"\n[dumpfile_size] 25572\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\08-memory\\solution-sequencer\\sequencer-top_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] 143 193\n*-21.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[treeopen] memory_tb.\n[treeopen] memory_tb.uut.\n[sst_width] 211\n[signals_width] 118\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\nmemory_tb.clk\n@29\nmemory_tb.uut.div_clk\n@28\nmemory_tb.led[1:0]\nmemory_tb.ptn_0_btn\nmemory_tb.ptn_1_btn\nmemory_tb.rst_btn\nmemory_tb.set_btn\nmemory_tb.uut.mem.r_addr[2:0]\nmemory_tb.uut.mem.r_data[1:0]\nmemory_tb.uut.mem.r_en\nmemory_tb.uut.mem.w_addr[2:0]\nmemory_tb.uut.mem.w_data[1:0]\nmemory_tb.uut.mem.w_en\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top_tb.v",
    "content": "// Testbench for sequencer\n//\n// Make sure the sequencer can store and replay step values.\n//\n// Date: November 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Defines timescale for simulation: <time_unit> / <time_precision>\n`timescale 1 ns / 10 ps\n\n// Define our testbench\nmodule memory_tb();\n\n    // Internal signals\n    wire    [1:0]  led;\n    \n    // Storage elements\n    reg             clk = 0;\n    reg             rst_btn = 1;\n    reg             set_btn = 1;\n    reg             ptn_0_btn = 1;\n    reg             ptn_1_btn = 1;\n\n    // Simulation time: 50000 * 1 ns = 50 us\n    localparam DURATION = 50000;\n    \n    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz\n    always begin\n        #41.67\n        clk = ~clk;\n    end\n    \n    // Instantiate the unit under test (UUT)\n    sequencer_top #(\n        .DEBOUNCE_COUNTS(2),\n        .STEP_COUNTS(10),\n        .NUM_STEPS(8)\n    ) uut (\n        .clk(clk),\n        .rst_btn(rst_btn),\n        .set_btn(set_btn),\n        .ptn_0_btn(ptn_0_btn),\n        .ptn_1_btn(ptn_1_btn),\n        .led(led),\n        .unused_led()\n    );\n    \n    // Run test: write to sequencer and make sure it plays the sequence back\n    initial begin\n    \n        // Toggle reset\n        #10\n        rst_btn = 0;\n        #1\n        rst_btn = 1;\n        \n        // View a few default steps\n        #(50 * 41.67)\n        \n        // Write 'b11 to the sequencer\n        #(10 * 41.67)\n        ptn_0_btn = 0;\n        ptn_1_btn = 0;\n        set_btn = 0;\n        #(10 * 41.67)\n        ptn_0_btn = 1;\n        ptn_1_btn = 1;\n        set_btn = 1;\n        \n        // Write 'b11 to the sequencer\n        #(10 * 41.67)\n        ptn_0_btn = 0;\n        ptn_1_btn = 0;\n        set_btn = 0;\n        #(10 * 41.67)\n        ptn_0_btn = 1;\n        ptn_1_btn = 1;\n        set_btn = 1;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"sequencer-top_tb.vcd\");\n        $dumpvars(0, memory_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "09-pll-and-glitches/example-01-pll/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "09-pll-and-glitches/example-01-pll/pll_test.pcf",
    "content": "# Oscillator\nset_io              ref_clk     21\n\n# PMOD I/O\nset_io              clk         87"
  },
  {
    "path": "09-pll-and-glitches/example-01-pll/pll_test.v",
    "content": "// Simple block RAM example\n// \n// Inputs:\n//      ref_clk     - Input reference clock (12 MHz)\n// \n// Outputs:\n//      clk         - Output of PLL (120 MHz clock)\n//\n// Date: December 6, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Instantiate PLL and output clock signal to pin\nmodule pll_test (\n\n    // Inputs\n    input               ref_clk,\n    \n    // Outputs\n    output              clk\n);\n\n    // Instantiate PLL (120 MHz)\n    SB_PLL40_CORE #(\n        .FEEDBACK_PATH(\"SIMPLE\"),   // Don't use fine delay adjust\n        .PLLOUT_SELECT(\"GENCLK\"),   // No phase shift on output\n        .DIVR(4'b0000),             // Reference clock divider\n        .DIVF(7'b1001111),          // Feedback clock divider\n        .DIVQ(3'b011),              // VCO clock divider\n        .FILTER_RANGE(3'b001)       // Filter range\n    ) pll (\n        .REFERENCECLK(ref_clk),     // Input clock\n        .PLLOUTCORE(clk),           // Output clock\n        .LOCK(),                    // Locked signal\n        .RESETB(1'b1),              // Active low reset\n        .BYPASS(1'b0)               // No bypass, use PLL signal as output\n    );\n    \nendmodule"
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/empty.v",
    "content": ""
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/glitch-test_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Dec 06 17:26:08 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\09-pll-and-glitches\\example-02-glitches\\glitch-test_tb.vcd\"\n[dumpfile_mtime] \"Mon Dec 06 17:25:24 2021\"\n[dumpfile_size] 153010\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\09-pll-and-glitches\\example-02-glitches\\glitch-test_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] -1 -1\n*-15.000000 12501 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[sst_width] 211\n[signals_width] 110\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\nglitch_test_tb.rst\nglitch_test_tb.clk\n@c00023\nglitch_test_tb.out[3:0]\n@28\n(0)glitch_test_tb.out[3:0]\n(1)glitch_test_tb.out[3:0]\n(2)glitch_test_tb.out[3:0]\n(3)glitch_test_tb.out[3:0]\n@1401201\n-group_end\n@22\nglitch_test_tb.count[3:0]\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/glitch-test_tb.v",
    "content": "// Simulation of glitches with a ripple-carry adder.\n//\n// Date: December 6, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Defines timescale for simulation: <time_unit> / <time_precision>\n`timescale 1 ns / 1 ps\n\n// Half adder (with gate delays)\nmodule half_adder (\n\n    // Inputs\n    input a,\n    input b,\n    \n    // Output\n    output sum,\n    output c_out\n);\n\n    // Create output logic\n    assign #1 sum = a ^ b;\n    assign #1 c_out = a & b;\n    \nendmodule\n\n// Define our testbench\nmodule glitch_test_tb();\n\n    // Simulation time: 10000 * 1 ns = 10000 ns\n    localparam DURATION = 10000;\n\n    // Internal signals\n    wire            c_0;\n    wire            c_1;\n    wire            c_2;\n    wire    [3:0]   out;\n    \n    // Internal storage elements\n    reg             clk = 0;\n    reg             rst = 0;\n    reg     [3:0]   count;\n    \n    // Generate clock signal: 1 / ((2 * 4.167) * 1 ns) = 119,990,400.77 Hz\n    always begin\n        #4.167\n        clk = ~clk;\n    end\n    \n    // Instantiate half adders\n    half_adder ha_0 (.a(1'b1), .b(count[0]), .sum(out[0]), .c_out(c_0));\n    half_adder ha_1 (.a(c_0), .b(count[1]), .sum(out[1]), .c_out(c_1));\n    half_adder ha_2 (.a(c_1), .b(count[2]), .sum(out[2]), .c_out(c_2));\n    half_adder ha_3 (.a(c_2), .b(count[3]), .sum(out[3]), .c_out());\n    \n    // Let the counter count\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count = 0;\n        end else begin\n            count <= out;\n        end\n    end\n    \n    // Pulse reset line high at the beginning\n    initial begin\n        #10\n        rst = 1;\n        #1\n        rst = 0;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"glitch-test_tb.vcd\");\n        $dumpvars(0, glitch_test_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/empty.v",
    "content": "// This file is needed to make apio happy"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/gray-code-counter_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Dec 06 17:23:51 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\09-pll-and-glitches\\solution-gray-code-counter\\gray-code-counter_tb.vcd\"\n[dumpfile_mtime] \"Mon Dec 06 17:23:21 2021\"\n[dumpfile_size] 65129\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\GitHub\\introduction-to-fpga\\09-pll-and-glitches\\solution-gray-code-counter\\gray-code-counter_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] -1 -1\n*-15.000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[sst_width] 211\n[signals_width] 94\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@29\nglitch_test_tb.rst\n@28\nglitch_test_tb.clk\n@22\nglitch_test_tb.out[3:0]\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/gray-code-counter_tb.v",
    "content": "// Simulation of a 4-bit gray code counter using a finite state machine.\n//\n// Date: December 6, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Defines timescale for simulation: <time_unit> / <time_precision>\n`timescale 1 ns / 1 ps\n\n// 4-bit gray code counter FSM\nmodule gray_counter (\n\n    // Inputs\n    input               clk,\n    input               rst,\n    \n    // Outputs\n    output  reg [3:0]   count\n);\n\n    // State machine transitions (with simulated delays)\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            count <= 0;\n        end else begin\n            case (count)                            // Gray code state\n                4'b0000:    #1 count <= 4'b0001;    // 0\n                4'b0001:    #1 count <= 4'b0011;    // 1\n                4'b0011:    #1 count <= 4'b0010;    // 2\n                4'b0010:    #1 count <= 4'b0110;    // 3\n                4'b0110:    #1 count <= 4'b0111;    // 4\n                4'b0111:    #1 count <= 4'b0101;    // 5\n                4'b0101:    #1 count <= 4'b0100;    // 6\n                4'b0100:    #1 count <= 4'b1100;    // 7\n                4'b1100:    #1 count <= 4'b1101;    // 8\n                4'b1101:    #1 count <= 4'b1111;    // 9\n                4'b1111:    #1 count <= 4'b1110;    // 10\n                4'b1110:    #1 count <= 4'b1010;    // 11\n                4'b1010:    #1 count <= 4'b1011;    // 12\n                4'b1011:    #1 count <= 4'b1001;    // 13\n                4'b1001:    #1 count <= 4'b1000;    // 14\n                4'b1000:    #1 count <= 4'b0000;    // 15\n                default:    #1 count <= 4'b0000;\n            endcase\n        end\n    end\n    \nendmodule\n\n// Define our testbench\nmodule gray_counter_tb();\n\n    // Simulation time: 10000 * 1 ns = 10000 ns\n    localparam DURATION = 10000;\n\n    // Internal signals\n    wire    [3:0]   out;\n    \n    // Internal storage elements\n    reg             clk = 0;\n    reg             rst = 0;\n    \n    // Generate clock signal: 1 / ((2 * 4.167) * 1 ns) = 119,990,400.77 Hz\n    always begin\n        #4.167\n        clk = ~clk;\n    end\n    \n    // Instantiate gray code counter\n    gray_counter gray (.clk(clk), .rst(rst), .count(out));\n    \n    // Pulse reset line high at the beginning\n    initial begin\n        #10\n        rst = 1;\n        #1\n        rst = 0;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"gray-code-counter_tb.vcd\");\n        $dumpvars(0, gray_counter_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule\n"
  },
  {
    "path": "10-metastability/example-01-metastability-test/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/example-01-metastability-test/metastability-test.pcf",
    "content": "# PMOD I/O\nset_io              clk_in      87\nset_io              sig_in      88\nset_io              clk_out     90\nset_io              sig_out     91"
  },
  {
    "path": "10-metastability/example-01-metastability-test/metastability-test.v",
    "content": "// Input 2 MHz clock and 1 MHz sqaure wave signal. Phase shift the\n// 1 MHz signal to force metastability.\n//\n// Connections\n//  Signal  | IceStick      | AnalogDiscovery 2 | Oscilloscope  \n// ---------|---------------|-------------------|---------------\n//  VCC     | 3.3V          | vary 0.7 to 3.3V  |\n//  GND     | GND           | GND               | ground clips\n//  clk_in  | 87            | W1                |\n//  sig_in  | 88            | W2                | ch. 1\n//  clk_out | 90            |                   | ch. 2\n//  sig_out | 91            |                   | ch. 3    \n//\n// Date: December 18, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Sample input waveform and register it\nmodule metastability_test (\n\n    // Inputs\n    input               clk_in,\n    input               sig_in,    \n    \n    // Outputs\n    output              clk_out,\n    output  reg         sig_out = 0\n);\n    \n    // Internal storage elements\n    reg     div_sig;\n    reg     pipe_0;\n    \n    // Pass input clock to output pin\n    assign clk_out = clk_in;\n\n    // Register input signal\n    always @ (posedge clk_in) begin\n        sig_out <= sig_in;\n        //pipe_0 <= sig_in;\n        //sig_out <= pipe_0;\n    end\n    \nendmodule"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/clock-divider.v",
    "content": "// A better way to create a clock divider that does not use flip-flip outputs\n// as clock inputs to other flip-flops. Us the tick pulse in combination with\n// other logic to determine when to perform some action.\n//\n// Based on work by: https://github.com/Paebbels\n//\n// Date: December 16, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Divide the clock by outputting a pulse at the desired time\nmodule clock_divider #(\n\n    // Parameters\n    parameter   MODULO  = 6000000\n) (\n    \n    // Inputs\n    input   clk,\n    input   rst,\n    \n    // Outputs\n    output  tick\n);\n\n    // Calculate number of bits needed for the counter\n    localparam WIDTH = (MODULO == 1) ? 1 : $clog2(MODULO);\n\n    // Internal storage elements\n    reg [WIDTH-1:0] count = 0;\n\n    // Tick is high for one clock cycle at max count\n    assign tick = (count == MODULO - 1) ? 1'b1 : 1'b0;\n    \n    // Count up, reset on tick pulse\n    always @ (posedge clk or posedge rst) begin\n        if (rst | tick == 1'b1) begin\n            count <= 0;\n        end else begin\n            count <= count + 1;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/clock-divider_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Dec 16 22:08:09 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\apio\\better-clock-divider\\clock-divider_tb.vcd\"\n[dumpfile_mtime] \"Thu Dec 16 22:08:03 2021\"\n[dumpfile_size] 5375201\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\apio\\better-clock-divider\\clock-divider_tb.gtkw\"\n[timestart] 0\n[size] 1000 600\n[pos] -1 -1\n*-25.000000 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[treeopen] clock_divider_tb.\n[sst_width] 211\n[signals_width] 110\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\nclock_divider_tb.clk\nclock_divider_tb.rst\nclock_divider_tb.tick\n@25\nclock_divider_tb.uut.count[6:0]\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/clock-divider_tb.v",
    "content": "// Test clock divider operation. The divider output (tick) should\n// pulse once at each divided cycle.\n//\n// Date: December 16, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define timescale\n`timescale 1 us / 10 ps\n\n// Define our testbench\nmodule clock_divider_tb();\n\n    // Settings\n    localparam  MODULO = 120;   // 12 MHz / 120 = 100 kHz ticks\n    \n    // Internal signals\n    wire    tick;\n    \n    // Internal storage elements\n    reg     clk = 0;\n    reg     rst = 0;\n    \n    // Simulation time: 10000 * 1 us = 10 ms\n    localparam DURATION = 10000;\n    \n    // Generate clock signal\n    always begin\n        #0.04167\n        clk = ~clk;\n    end\n    \n    // Instantiate clock divider\n    clock_divider #(\n        .MODULO(MODULO)\n    ) uut (\n        .clk(clk),\n        .rst(rst),\n        .tick(tick)\n    );\n    \n    // Test control: run for some time, toggle reset, let run some more\n    initial begin\n        #10\n        rst = 1;\n        #1\n        rst = 0;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"clock-divider_tb.vcd\");\n        $dumpvars(0, clock_divider_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/slow-blink.pcf",
    "content": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led         99\n\n# PMOD I/O\nset_io  -pullup yes rst_btn     78"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/slow-blink.v",
    "content": "// Slow blink example using the better clock divider.\n//\n// Based on work by: https://github.com/Paebbels\n//\n// Date: December 16, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Slow blink top level design\nmodule slow_blink (\n\n    // Inputs\n    input           clk,\n    input           rst_btn,    \n    \n    // Outputs\n    output  reg     led\n);\n\n    // Settings\n    localparam MODULO = 6000000;    // Toggle LED every 0.5 s with 12 MHz clk\n    \n    // Internal signals\n    wire    rst;\n    wire    tick;\n    \n    // Invert reset button\n    assign rst = ~rst_btn;\n\n    // Instantiate clock divider\n    clock_divider #(\n        .MODULO(MODULO)\n    ) uut (\n        .clk(clk),\n        .rst(rst),\n        .tick(tick)\n    );\n    \n    // Example using clock divider to blink LED\n    always @ (posedge clk or posedge rst) begin\n        if (rst == 1'b1) begin\n            led <= 1'b0;\n        end else if (tick == 1'b1) begin\n            led <= ~led;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/debouncer.v",
    "content": "// Debounce signal logic without the use of a clock divider.\n//\n// Based on: https://forum.digikey.com/t/debounce-logic-circuit-vhdl/12573\n//\n// Date: December 16, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Debouncing logic\nmodule debouncer #(\n    \n    // Parameters\n    parameter MAX_CLK_COUNT = 120000    // 10 ms with 12 MHz clock\n) (\n\n    // Inputs\n    input           clk,\n    input           rst,\n    input           sig,\n    \n    // Outputs\n    output  reg     out\n);\n\n    // Calculate number of bits needed for the counter\n    localparam WIDTH = $clog2(MAX_CLK_COUNT + 1);\n    \n    // Internal signals\n    wire            sig_edge;\n\n    // Internal storage elements\n    reg             ff_1;\n    reg             ff_2;\n    reg [WIDTH-1:0] count = 0;\n    \n    // Counter starts when outputs of the two flip-flops are different\n    assign sig_edge = ff_1 ^ ff_2;\n    \n    // Logic to sample signal after a period of time\n    always @ (posedge clk or posedge rst) begin\n    \n        // Reset flip-flops\n        if (rst == 1'b1) begin\n            ff_1 <= 0;\n            ff_2 <= 0;\n            out <= 0;\n        \n        // If rising or falling edge on signal, run counter and sample again\n        end else begin\n            ff_1 <= sig;\n            ff_2 <= ff_1;\n            if (sig_edge == 1'b1) begin\n                count <= 0;\n            end else if (count < MAX_CLK_COUNT) begin\n                count <= count + 1;\n            end else begin\n                out <= ff_2;\n            end\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/debouncer_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Dec 16 22:04:13 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\apio\\better-debounce\\debouncer_tb.vcd\"\n[dumpfile_mtime] \"Thu Dec 16 17:47:23 2021\"\n[dumpfile_size] 4164257\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\apio\\better-debounce\\debouncer_tb.gtkw\"\n[timestart] 0\n[size] 1108 600\n[pos] -135 173\n*-31.000000 0 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[treeopen] debouncer_tb.\n[sst_width] 211\n[signals_width] 110\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\ndebouncer_tb.clk\ndebouncer_tb.rst\ndebouncer_tb.inc_btn\n@22\ndebouncer_tb.uut.count[8:0]\n@28\ndebouncer_tb.out\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/debouncer_tb.v",
    "content": "// Testbench for button debounce design\n//\n// Date: November 16, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define timescale\n`timescale 1 us / 10 ps\n\n// Define our testbench\nmodule debouncer_tb();\n\n    // Internal signals\n    wire            out;\n    \n    // Storage elements (buttons are active low!)\n    reg             clk = 0;\n    reg             rst = 0;\n    reg             inc_btn = 1;\n    integer         i;              // Used in for loop\n    integer         j;              // Used in for loop\n    integer         prev_inc;       // Previous increment button state\n    integer         nbounces;       // Holds random number\n    integer         rdelay;         // Holds random number\n    \n    // Simulation time: 10000 * 1 us = 10 ms\n    localparam DURATION = 10000;\n    \n    // Generate clock signal (about 12 MHz)\n    always begin\n        #0.04167\n        clk = ~clk;\n    end\n    \n    // Instantiate debounce/counter module (use about 40 us wait time)\n    debouncer #(\n        .MAX_CLK_COUNT(480)\n    ) uut (\n        .clk(clk),\n        .rst(rst),\n        .sig(inc_btn),\n        .out(out)\n    );\n    \n    // Test control: pulse reset and create some (bouncing) button presses\n    initial begin\n    \n        // Pulse reset\n        #10\n        rst = 1;\n        #1\n        rst = 0;\n        \n        // We can use for loops in simulation!\n        for (i = 0; i < 32; i = i + 1) begin\n        \n            // Wait some time before pressing button\n            #1000\n            \n            // Simulate a bouncy/noisy button press\n            // $urandom generates a 32-bit unsigned (pseudo) random number\n            // \"% 10\" is \"modulo 10\"\n            prev_inc = inc_btn;\n            nbounces = $urandom % 20;\n            for (j = 0; j < nbounces; j = j + 1) begin\n                #($urandom % 10)\n                inc_btn = ~inc_btn;\n            end\n            \n            // Make sure button ends up in the opposite state\n            inc_btn = ~prev_inc;\n        end\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"debouncer_tb.vcd\");\n        $dumpvars(0, debouncer_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n    \nendmodule"
  },
  {
    "path": "10-metastability/solution-async-fifo/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/solution-async-fifo/async-fifo.v",
    "content": "// Implementation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf\n//\n// Top-level asynchronous FIFO module to be used in designs.\n//\n// Notes:\n//  - w_* means something is in the \"write clock domain\"\n//  - r_* means something is in the \"read clock domain\"\n//  - Single memory element is DATA_SIZE bits wide\n//  - Memory is 2^ADDR_SIZE elements deep\n//\n// Date: December 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Asynchronous FIFO module\nmodule async_fifo #(\n\n    // Parameters\n    parameter   DATA_SIZE = 8,              // Number of data bits\n    parameter   ADDR_SIZE = 4               // Number of bits for address\n) (\n\n    // Inputs\n    input       [DATA_SIZE-1:0] w_data,     // Data to be written to FIFO\n    input                       w_en,       // Write data and increment addr.\n    input                       w_clk,      // Write domain clock\n    input                       w_rst,      // Write domain reset\n    input                       r_en,       // Read data and increment addr.\n    input                       r_clk,      // Read domain clock\n    input                       r_rst,      // Read domain reset\n    \n    // Outputs\n    output                      w_full,     // Flag: 1 if FIFO is full\n    output  reg [DATA_SIZE-1:0] r_data,     // Data to be read from FIFO\n    output                      r_empty     // Flag: 1 if FIFO is empty\n);\n\n    // Constants\n    localparam  FIFO_DEPTH  = (1 << ADDR_SIZE);\n    \n    // Internal signals\n    wire    [ADDR_SIZE-1:0] w_addr;\n    wire    [ADDR_SIZE:0]   w_gray;\n    wire    [ADDR_SIZE-1:0] r_addr;\n    wire    [ADDR_SIZE:0]   r_gray;\n    \n    // Internal storage elements\n    reg     [ADDR_SIZE:0]   w_syn_r_gray;\n    reg     [ADDR_SIZE:0]   w_syn_r_gray_pipe;\n    reg     [ADDR_SIZE:0]   r_syn_w_gray;\n    reg     [ADDR_SIZE:0]   r_syn_w_gray_pipe;\n    \n    // Declare memory\n    reg     [DATA_SIZE-1:0] mem [0:FIFO_DEPTH-1];\n    \n    //--------------------------------------------------------------------------\n    // Dual-port memory (should be inferred as block RAM)\n    \n    // Write data logic for dual-port memory (separate write clock)\n    // Do not write if FIFO is full!\n    always @ (posedge w_clk) begin\n        if (w_en & ~w_full) begin\n            mem[w_addr] <= w_data;\n        end\n    end\n    \n    // Read data logic for dual-port memory (separate read clock)\n    // Do not read if FIFO is empty!\n    always @ (posedge r_clk) begin\n        if (r_en & ~r_empty) begin\n            r_data <= mem[r_addr];\n        end\n    end\n    \n    //--------------------------------------------------------------------------\n    // Synchronizer logic\n    \n    // Pass read-domain Gray code pointer to write domain\n    always @ (posedge w_clk or posedge w_rst) begin\n        if (w_rst == 1'b1) begin\n            w_syn_r_gray_pipe <= 0;\n            w_syn_r_gray <= 0;\n        end else begin\n            w_syn_r_gray_pipe <= r_gray;\n            w_syn_r_gray <= w_syn_r_gray_pipe;\n        end\n    end\n    \n    // Pass write-domain Gray code pointer to read domain\n    always @ (posedge r_clk or posedge r_rst) begin\n        if (r_rst == 1'b1) begin\n            r_syn_w_gray_pipe <= 0;\n            r_syn_w_gray <= 0;\n        end else begin\n            r_syn_w_gray_pipe <= w_gray;\n            r_syn_w_gray <= r_syn_w_gray_pipe;\n        end\n    end\n    \n    //--------------------------------------------------------------------------\n    // Instantiate incrementer and full/empty checker modules\n    \n    // Write address increment and full check module\n    w_ptr_full #(.ADDR_SIZE(ADDR_SIZE)) w_ptr_full (\n        .w_syn_r_gray(w_syn_r_gray),\n        .w_inc(w_en),\n        .w_clk(w_clk),\n        .w_rst(w_rst),\n        .w_addr(w_addr),\n        .w_gray(w_gray),\n        .w_full(w_full)\n    );\n    \n    // Read address increment and empty check module\n    r_ptr_empty #(.ADDR_SIZE(ADDR_SIZE)) r_ptr_empty (\n        .r_syn_w_gray(r_syn_w_gray),\n        .r_inc(r_en),\n        .r_clk(r_clk),\n        .r_rst(r_rst),\n        .r_addr(r_addr),\n        .r_gray(r_gray),\n        .r_empty(r_empty)\n    );\n    \nendmodule"
  },
  {
    "path": "10-metastability/solution-async-fifo/async-fifo_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Sat Dec 11 20:21:30 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\apio\\fifo_test_03\\async-fifo_tb.vcd\"\n[dumpfile_mtime] \"Sat Dec 11 20:20:07 2021\"\n[dumpfile_size] 5748705\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\apio\\fifo_test_03\\async-fifo_tb.gtkw\"\n[timestart] 0\n[size] 1707 897\n[pos] -1 -1\n*-21.000000 6927000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[sst_width] 211\n[signals_width] 118\n[sst_expanded] 1\n[sst_vpaned_height] 259\n@28\nasync_fifo_tb.w_clk\nasync_fifo_tb.w_rst\n@22\nasync_fifo_tb.w_data[7:0]\n@28\nasync_fifo_tb.w_en\n@29\nasync_fifo_tb.w_full\n@28\nasync_fifo_tb.r_clk\nasync_fifo_tb.r_rst\n@22\nasync_fifo_tb.r_data[7:0]\n@28\nasync_fifo_tb.r_en\nasync_fifo_tb.r_empty\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "10-metastability/solution-async-fifo/async-fifo_tb.v",
    "content": "// Simulation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf\n//\n// Testbench to verify RTL design of the asynchronous FIFO design. Note that\n// this does not check for things like metastability and glitches! You would\n// likely need to use a gate-level simulation tool for that.\n//\n// Notes:\n//  - w_* means something is in the \"write clock domain\"\n//  - r_* means something is in the \"read clock domain\"\n//  - Single memory element is DATA_SIZE bits wide\n//  - Memory is 2^ADDR_SIZE elements deep\n//\n// Date: December 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define timescale\n`timescale 1 us / 10 ps\n\n// Define our testbench\nmodule async_fifo_tb();\n\n    // Settings\n    localparam  DATA_SIZE = 8;\n    localparam  ADDR_SIZE = 4;\n    \n    // Internal signals\n    wire    [DATA_SIZE-1:0]     r_data;\n    wire                        r_empty;\n    wire                        r_full;\n    \n    // Internal storage elements\n    reg                         r_en = 0;\n    reg                         r_clk = 0;\n    reg                         r_rst = 0;\n    reg     [DATA_SIZE-1:0]     w_data;\n    reg                         w_en = 0;\n    reg                         w_clk = 0;\n    reg                         w_rst = 0;\n    \n    // Variables\n    integer                     i;\n    \n    // Simulation time: 10000 * 1 us = 10 ms\n    localparam DURATION = 10000;\n    \n    // Generate read clock signal (about 12 MHz)\n    always begin\n        #0.04167\n        r_clk = ~r_clk;\n    end\n    \n    // Generate write clock signal (5 MHz)\n    always begin\n        #0.1\n        w_clk = ~w_clk;\n    end\n    \n    // Instantiate FIFO\n    async_fifo #(\n        .DATA_SIZE(DATA_SIZE),\n        .ADDR_SIZE(ADDR_SIZE)\n    ) uut (\n        .w_data(w_data),\n        .w_en(w_en),\n        .w_clk(w_clk),\n        .w_rst(w_rst),\n        .r_en(r_en),\n        .r_clk(r_clk),\n        .r_rst(r_rst),\n        .w_full(w_full),\n        .r_data(r_data),\n        .r_empty(r_empty)\n    );\n    \n    // Test control: write and read data to/from FIFO\n    initial begin\n    \n        // Pulse resets high to initialize memory and counters\n        #0.1\n        w_rst = 1;\n        r_rst = 1;\n        #0.01\n        w_rst = 0;\n        r_rst = 0;\n        \n        // Write some data to the FIFO\n        for (i = 0; i < 4; i = i + 1) begin\n            #0.2\n            w_data = i;\n            w_en = 1'b1;\n        end\n        #0.2\n        w_en = 1'b0;\n        \n        // Try to read more than what's in the FIFO\n        for (i = 0; i < 6; i = i + 1) begin\n            #0.08334\n            r_en = 1'b1;\n        end\n        #0.08334\n        r_en = 1'b0;\n        \n        // Fill up FIFO (and then some)\n        for (i = 0; i < 18; i = i + 1) begin\n            #0.2\n            w_en = 1'b1;\n            w_data = i;\n        end\n        #0.2\n        w_en = 1'b0;\n        \n        // Read everything in the FIFO (and then some)\n        for (i = 0; i < 18; i = i + 1) begin\n            #0.08334\n            r_en = 1'b1;\n        end\n        #0.08334\n        r_en = 1'b0;\n            \n    end\n    \n        // Run simulation\n    initial begin\n    \n        // Create simulation output file \n        $dumpfile(\"async-fifo_tb.vcd\");\n        $dumpvars(0, async_fifo_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n\nendmodule"
  },
  {
    "path": "10-metastability/solution-async-fifo/dummy.pcf",
    "content": "# Dummy PCF signals to test synthesis\nset_io  r_en        112\nset_io  r_clk       113\nset_io  w_data[0]   114\nset_io  w_data[1]   115\nset_io  w_data[2]   116\nset_io  w_data[3]   117\nset_io  w_data[4]   118\nset_io  w_data[5]   119\nset_io  w_data[6]   44\nset_io  w_data[7]   45\nset_io  w_en        47\nset_io  w_clk       48\nset_io  w_rst       56\nset_io  r_rst       60\nset_io  r_data[0]   61\nset_io  r_data[1]   62\nset_io  r_data[2]   78\nset_io  r_data[3]   79\nset_io  r_data[4]   80\nset_io  r_data[5]   81\nset_io  r_data[6]   87\nset_io  r_data[7]   88\nset_io  r_empty     99\nset_io  w_full      98"
  },
  {
    "path": "10-metastability/solution-async-fifo/r-ptr-empty.v",
    "content": "// Implementation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf\n//\n// Module to incrememnt the read address and determine if the FIFO is empty.\n//\n// Notes:\n//  - w_* means something is in the \"write clock domain\"\n//  - r_* means something is in the \"read clock domain\"\n//\n// Date: December 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Increment read address and check if FIFO is empty\nmodule r_ptr_empty #(\n\n    // Parameters\n    parameter   ADDR_SIZE = 4                   // Number of bits for address\n) (\n    \n    // Inputs\n    input       [ADDR_SIZE:0]   r_syn_w_gray,   // Synced write Gray pointer\n    input                       r_inc,          // 1 to increment address\n    input                       r_clk,          // Read domain clock\n    input                       r_rst,          // Read domain reset\n\n    // Outputs\n    output      [ADDR_SIZE-1:0] r_addr,         // Mem address to read from\n    output  reg [ADDR_SIZE:0]   r_gray,         // Gray address with +1 MSb\n    output  reg                 r_empty         // 1 if FIFO is empty\n);\n    \n    // Internal signals\n    wire    [ADDR_SIZE:0]   r_gray_next;    // Gray code version of address\n    wire    [ADDR_SIZE:0]   r_bin_next;     // Binary version of address\n    wire                    r_empty_val;    // FIFO is empty\n    \n    // Internal storage elements\n    reg     [ADDR_SIZE:0]   r_bin;          // Registered binary address\n    \n    // Drop extra most significant bit (MSb) for addressing into memory\n    assign r_addr = r_bin[ADDR_SIZE-1:0];\n    \n    // Be ready with next (incremented) address (if inc set and not empty)\n    assign r_bin_next = r_bin + (r_inc & ~r_empty);\n    \n    // Convert next binary address to Gray code value\n    assign r_gray_next = (r_bin_next >> 1) ^ r_bin_next;\n    \n    // If the synced write Gray code is equal to the current read Gray code,\n    // then the pointers have caught up to each other and the FIFO is empty\n    assign r_empty_val = (r_gray_next == r_syn_w_gray);\n    \n    // Register the binary and Gray code pointers in the read clock domain\n    always @ (posedge r_clk or posedge r_rst) begin\n        if (r_rst == 1'b1) begin\n            r_bin <= 0;\n            r_gray <= 0;\n        end else begin\n            r_bin <= r_bin_next;\n            r_gray <= r_gray_next;\n        end\n    end\n    \n    // Register the empty flag\n    always @ (posedge r_clk or posedge r_rst) begin\n        if (r_rst == 1'b1) begin\n            r_empty <= 1'b1;\n        end else begin\n            r_empty <= r_empty_val;\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "10-metastability/solution-async-fifo/w-ptr-full.v",
    "content": "// Implementation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf\n//\n// Module to incrememnt the write address and determine if the FIFO is full.\n//\n// Notes:\n//  - w_* means something is in the \"write clock domain\"\n//  - r_* means something is in the \"read clock domain\"\n//\n// Date: December 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Increment write address and check if FIFO is full\nmodule w_ptr_full #(\n\n    // Parameters\n    parameter   ADDR_SIZE = 4                   // Number of bits for address\n) (\n    \n    // Inputs\n    input       [ADDR_SIZE:0]   w_syn_r_gray,   // Synced read Gray pointer\n    input                       w_inc,          // 1 to increment address\n    input                       w_clk,          // Write domain clock\n    input                       w_rst,          // Write domain reset\n    \n    // Outputs \n    output      [ADDR_SIZE-1:0] w_addr,         // Mem address to write to\n    output  reg [ADDR_SIZE:0]   w_gray,         // Gray adress with +1 MSb\n    output  reg                 w_full          // 1 if FIFO is full   \n);\n\n    // Internal signals\n    wire    [ADDR_SIZE:0]   w_gray_next;    // Gray code version of address\n    wire    [ADDR_SIZE:0]   w_bin_next;     // Binary version of address\n    wire                    w_full_val;     // FIFO is full\n    \n    // Internal storage elements\n    reg     [ADDR_SIZE:0]   w_bin;          // Registered binary address\n    \n    // Drop extra most significant bit (MSb) for addressing into memory\n    assign w_addr = w_bin[ADDR_SIZE-1:0];\n    \n    // Be ready with next (incremented) address (if inc set and not full)\n    assign w_bin_next = w_bin + (w_inc & ~w_full);\n    \n    // Convert next binary address to Gray code value\n    assign w_gray_next = (w_bin_next >> 1) ^ w_bin_next;\n    \n    // Compare write Gray code to synced read Gray code to see if FIFO is full\n    // If:  extra MSb of read and write Gray codes are not equal AND\n    //      2nd MSb of read and write Gray codes are not equal AND\n    //      the rest of the bits are equal\n    // Then: address pointers are same with write pointer ahead by 2^ADDR_SIZE\n    // elements (i.e. wrapped around), so FIFO is full.\n    assign w_full_val = ((w_gray_next[ADDR_SIZE] != w_syn_r_gray[ADDR_SIZE]) &&\n                   (w_gray_next[ADDR_SIZE-1] != w_syn_r_gray[ADDR_SIZE-1]) &&\n                   (w_gray_next[ADDR_SIZE-2:0] == w_syn_r_gray[ADDR_SIZE-2:0]));\n    \n    // Register the binary and Gray code pointers in the write clock domain\n    always @ (posedge w_clk or posedge w_rst) begin\n        if (w_rst == 1'b1) begin\n            w_bin <= 0;\n            w_gray <= 0;\n        end else begin\n            w_bin <= w_bin_next;\n            w_gray <= w_gray_next;\n        end\n    end\n    \n    // Register the full flag\n    always @ (posedge w_clk or posedge w_rst) begin\n        if (w_rst == 1'b1) begin\n            w_full <= 1'b0;\n        end else begin\n            w_full <= w_full_val;\n        end\n    end\n    \nendmodule        "
  },
  {
    "path": "11-risc-v-softcore-cpu/example-01-blinky/Makefile",
    "content": "include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc\n"
  },
  {
    "path": "11-risc-v-softcore-cpu/example-01-blinky/main.c",
    "content": "// Blink 2 LEDs and print info to the serial terminal.\n//\n// Date: December 19, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n#include <femtorv32.h>\n\nint main() {\n        while(1) {\n                printf(\"Hello, world!\\r\\n\");\n                printf(\"Freq: %d MHz\\r\\n\", FEMTORV32_FREQ);\n                *(volatile uint32_t*)(0x400004) = 3;\n                delay(500);\n                *(volatile uint32_t*)(0x400004) = 0;\n\t\tdelay(500);\n\t}\n\treturn 0;\n}\n\n"
  },
  {
    "path": "11-risc-v-softcore-cpu/solution-buttons/Makefile",
    "content": "include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc\n"
  },
  {
    "path": "11-risc-v-softcore-cpu/solution-buttons/main.c",
    "content": "// Count on LEDs as long as button is pressed.\n//\n// Date: December 19, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n#include <femtorv32.h>\n\nint main() {\n    int count = 0;\n    while (1) {\n        if ((IO_IN(IO_BUTTONS) & 1) == 0) {\n            count = (count + 1) % 16;\n            IO_OUT(IO_LEDS, count);\n            delay(250);\n        }\n    }\n    return 0;\n}\n\n"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/C/pwm_test/Makefile",
    "content": "include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc\n"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/C/pwm_test/main.c",
    "content": "// Slowly increase the brightness of the PWM-controlled LED over and over.\n//\n// Date: December 19, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n#include <femtorv32.h>\n\nint main() {\n\twhile (1) {\n\t\tfor (int i = 0; i < 4096; i++) {\n\t\t\t*(volatile uint32_t*)(0x404000) = i;\n                        delay(1);\n\t\t}\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/apio.ini",
    "content": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm.pcf",
    "content": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]      98\nset_io              led[2]      97\nset_io              led[3]      96"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm.v",
    "content": "// PWM driver for FemtoRV: https://github.com/BrunoLevy/learn-fpga\n//\n// Controls brightness of first LED. Set duty cycle with wdata (0..4095).\n//\n// Date: December 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Control brightness of one of the LEDs\nmodule pwm #(\n\n    // Parameters\n    parameter       WIDTH = 12  // Default PWM values 0..4095\n\n) (\n\n    // Inputs\n    input           clk,\n    input           wstrb,  // Write strobe\n    input           sel,    // Select (read/write ignored if low)\n    input   [31:0]  wdata,  // Data to be written (to driver)\n    \n    // Outputs\n    output  [3:0]   led\n);\n\n    // Internal storage elements\n    reg             pwm_led = 1'b0;\n    reg [WIDTH-1:0] pwm_count = 0;\n    reg [WIDTH-1:0] count = 0;\n    \n    // Only control the first LED\n    assign led[0] = pwm_led;\n    \n    // Update PWM duty cycle \n    always @ (posedge clk) begin\n    \n        // If sel is high, record duty cycle count on strobe\n        if (sel && wstrb) begin\n            pwm_count <= wdata[WIDTH-1:0];\n            count <= 0;\n            \n        // Otherwise, continuously count and flash LED as necessary\n        end else begin\n            count <= count + 1;\n            if (count < pwm_count) begin\n                pwm_led <= 1'b1;\n            end else begin\n                pwm_led <= 1'b0;\n            end\n        end\n    end\n    \nendmodule"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm_tb.gtkw",
    "content": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Wed Dec 15 20:37:05 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Documents\\apio\\pwm_01\\pwm_tb.vcd\"\n[dumpfile_mtime] \"Wed Dec 15 20:32:44 2021\"\n[dumpfile_size] 5154\n[savefile] \"C:\\Users\\sgmustadio\\Documents\\apio\\pwm_01\\pwm_tb.gtkw\"\n[timestart] 3820000\n[size] 1000 600\n[pos] 68 104\n*-19.000000 4542030 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1\n[treeopen] pwm_tb.\n[sst_width] 211\n[signals_width] 142\n[sst_expanded] 1\n[sst_vpaned_height] 154\n@28\npwm_tb.clk\npwm_tb.sel\npwm_tb.wstrb\n@22\npwm_tb.wdata[31:0]\npwm_tb.uut.pwm_count[3:0]\n@23\npwm_tb.uut.count[3:0]\n@800022\npwm_tb.led[3:0]\n@28\n(0)pwm_tb.led[3:0]\n(1)pwm_tb.led[3:0]\n(2)pwm_tb.led[3:0]\n(3)pwm_tb.led[3:0]\n@1001200\n-group_end\n[pattern_trace] 1\n[pattern_trace] 0\n"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm_tb.v",
    "content": "// Simulation of PWM driver.\n//\n// Date: December 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define timescale\n`timescale 1 ns / 10 ps\n\n// Testbench\nmodule pwm_tb();\n\n    // Simulation time: 10000 * 1 us = 10 ms\n    localparam DURATION = 10000;\n    \n    // Internal signals\n    wire    [3:0]   led;    \n\n    // Internal storage elements\n    reg             clk = 0;\n    reg             wstrb = 0;\n    reg             sel = 0;\n    reg     [31:0]  wdata = 0;\n\n    // Generate read clock signal (about 12 MHz)\n    always begin\n        #41.667\n        clk = ~clk;\n    end\n    \n    // Instantiate PWM driver\n    pwm #(\n        .WIDTH(4)\n    ) uut (\n        .clk(clk),\n        .wstrb(wstrb),\n        .sel(sel),\n        .wdata(wdata),\n        .led(led)\n    );\n    \n    // Test control: send values to PWM driver and watch LED\n    initial begin\n        \n        // Wait some time to see how LED initializes\n        #1500\n        \n        // Write 0% duty cycle\n        wstrb = 1;\n        sel = 1;\n        wdata = 0;\n        #100\n        wstrb = 0;\n        sel = 0;\n        \n        // Write ~33% duty cycle\n        #1500\n        wstrb = 1;\n        sel = 1;\n        wdata = 5;\n        #100\n        wstrb = 0;\n        sel = 0;\n        \n        // Write 100% duty cycle\n        #1500\n        wstrb = 1;\n        sel = 1;\n        wdata = 15;\n        #100\n        wstrb = 0;\n        sel = 0;\n    end\n    \n    // Run simulation (output to .vcd file)\n    initial begin\n    \n        // Create simulation output file\n        $dumpfile(\"pwm_tb.vcd\");\n        $dumpvars(0, pwm_tb);\n        \n        // Wait for given amount of time for simulation to complete\n        #(DURATION)\n        \n        // Notify and end simulation\n        $display(\"Finished!\");\n        $finish;\n    end\n\nendmodule"
  },
  {
    "path": "README.md",
    "content": "# Introduction to FPGA\n\nWelcome to the demo code and solutions section of my Introduction to FPGA course! This repository houses all of the example code and solutions that you may use as references when working through the FPGA examples.\n\n[![Introduction to FPGA YouTube Series](https://raw.githubusercontent.com/ShawnHymel/introduction-to-fpga/main/images/Intro%20to%20FPGA%20Part%201_Thumbnail.png)](https://www.youtube.com/watch?v=lLg1AgA2Xoo&list=PLEBQazB0HUyT1WmMONxRZn9NmQ_9CIKhb)\n\nThis course is hosted on YouTube that you may take for free. All you need to do is watch the videos and complete the challenge issued at the end of each video. I highly recommend you try each challenge before peeking at the solutions here.\n\nThe first video in the series is found here: [Introduction to FPGA Part 1 - What is an FPGA? | Digi-Key Electronics](https://www.youtube.com/watch?v=lLg1AgA2Xoo&list=PLEBQazB0HUyT1WmMONxRZn9NmQ_9CIKhb)\n\nWritten guides that explain the solutions can be found here:\n\n 1. [What is an FPGA?](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-1-what-is-an-fpga/3ee5f6c8fa594161a655a9f960060893)\n 2. [Toolchain Setup](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-2-toolchain-setup/563a9518cd11466fb6a75cf3cb684d6d)\n 3. [Getting Started with Verilog](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-3-getting-started-with-verilog/9d9dbff29a4b45728521b2664bbd1df4)\n 4. [Clocks and Procedural Assignments](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-4-clocks-and-procedural-assignments/356e12284daf48b5bd9b80af8a6ac5b8)\n 5. [Finite State Machine (FSM)](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-5-finite-state-machine-fsm/4d83e63da76044af9acc8aa7dcf07c22)\n 6. [Verilog Modules and Parameters](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-6-verilog-modules-and-parameters/c7d4d01274be43278d8bc531e6b7acb7)\n 7. [Verilog Testbenches and Simulation](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-7-verilog-testbenches-and-simulation/1b741d1b8b864afeacbe28075b1427cd)\n 8. [Memory and Block RAM](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-8-memory-and-block-ram/df7bcadef0de430ab89d0d9c21e3a14c)\n 9. [Phase-Locked Loop (PLL) and Glitches](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-9-phaselocked-loop-pll-and-glitches/2028ce62001b4cb69335f48e127fa366)\n 10. [Metastability and FIFO](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-10-metastability-and-fifo/74884ed134474e008a1e444ea9dacb0f)\n 11. [RISC-V Softcore Processor](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-11-risc-v-softcore-processor/f0511ddb538f444cae08f7bc43a74dcc)\n 12. [RISC-V Peripheral](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-12-risc-v-custom-peripheral/148dba8ecafe49a1ac7e13641088af4c)\n\n## Directory Structure\n\nExamples and solutions are housed in dirctories that correspond to each chapter or video number. For example, if you watch \"Intro to FPGA Part 3 - Verilog Gate Logic,\" you should refer to the directory *03-verilog-gate-logic*.\n\nIn each directory, you will find example projects. Demonstrations used in the video are listed as *example-\\** and the solution to that part's challenge is listed as *solution-\\**.\n\nThe only exception to this is the *images* directory, which is where I keep images for this repository.\n\n## License\n\nAll code in this repository, unless otherwise noted, is licensed under the [Zero-Clause BSD / Free Public License 1.0.0 (0BSD)](https://opensource.org/licenses/0BSD).\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  }
]