main 79d295449987 cached
116 files
104.9 KB
35.2k tokens
3 symbols
1 requests
Download .txt
Repository: ShawnHymel/introduction-to-fpga
Branch: main
Commit: 79d295449987
Files: 116
Total size: 104.9 KB

Directory structure:
gitextract_qazi7qst/

├── .gitignore
├── 02-install-apio/
│   └── solution-turn-off-led/
│       ├── apio.ini
│       ├── info
│       ├── leds.pcf
│       ├── leds.v
│       ├── leds_tb.gtkw
│       └── leds_tb.v
├── 03-verilog-gate-logic/
│   ├── example-01-and-gate/
│   │   ├── and_gate.pcf
│   │   ├── and_gate.v
│   │   └── apio.ini
│   ├── example-02-vectors/
│   │   ├── apio.ini
│   │   ├── vectors.pcf
│   │   └── vectors.v
│   └── solution-full-adder/
│       ├── apio.ini
│       ├── full-adder.pcf
│       └── full-adder.v
├── 04-clocks-and-procedural-assignments/
│   ├── example-01-button-counter/
│   │   ├── apio.ini
│   │   ├── button-counter.pcf
│   │   └── button-counter.v
│   └── solution-clock-counter/
│       ├── apio.ini
│       ├── clock-counter.pcf
│       └── clock-counter.v
├── 05-finite-state-machines/
│   ├── example-01-moore-fsm/
│   │   ├── apio.ini
│   │   ├── moore-fsm.pcf
│   │   └── moore-fsm.v
│   ├── example-02-mealy-fsm/
│   │   ├── apio.ini
│   │   ├── mealy-fsm.pcf
│   │   └── mealy-fsm.v
│   └── solution-button-debouncing/
│       ├── apio.ini
│       ├── solution-button-debouncing.pcf
│       └── solution-button-debouncing.v
├── 06-modules-and-parameters/
│   ├── example-01-parameters/
│   │   ├── apio.ini
│   │   ├── clock-divider.v
│   │   ├── top-design.pcf
│   │   └── top-design.v
│   ├── example-02-ansi-parameters/
│   │   ├── apio.ini
│   │   ├── clock-divider.v
│   │   ├── top-design.pcf
│   │   └── top-design.v
│   └── solution-count-up-down/
│       ├── apio.ini
│       ├── clock-divider.v
│       ├── count-up-down-top.v
│       ├── count-up-down.pcf
│       └── counter-fsm.v
├── 07-simulation-and-testbenches/
│   ├── example-01-testbench/
│   │   ├── apio.ini
│   │   ├── clk-div_tb.gtkw
│   │   ├── clk-div_tb.v
│   │   └── clock-divider.v
│   └── solution-debounce-testbench/
│       ├── apio.ini
│       ├── button-debouncing.v
│       ├── button-debouncing_tb.gtkw
│       └── button-debouncing_tb.v
├── 08-memory/
│   ├── example-01-memory/
│   │   ├── apio.ini
│   │   ├── memory.v
│   │   ├── memory_tb.gtkw
│   │   ├── memory_tb.v
│   │   └── test.pcf
│   ├── example-02-memory-initialization/
│   │   ├── apio.ini
│   │   ├── mem_init.txt
│   │   ├── memory.v
│   │   ├── memory_tb.gtkw
│   │   ├── memory_tb.v
│   │   └── test.pcf
│   └── solution-sequencer/
│       ├── apio.ini
│       ├── clock-divider.v
│       ├── debouncer.v
│       ├── mem_init.txt
│       ├── memory.v
│       ├── sequencer-top.pcf
│       ├── sequencer-top.v
│       ├── sequencer-top_tb.gtkw
│       └── sequencer-top_tb.v
├── 09-pll-and-glitches/
│   ├── example-01-pll/
│   │   ├── apio.ini
│   │   ├── pll_test.pcf
│   │   └── pll_test.v
│   ├── example-02-glitches/
│   │   ├── apio.ini
│   │   ├── empty.v
│   │   ├── glitch-test_tb.gtkw
│   │   └── glitch-test_tb.v
│   └── solution-gray-code-counter/
│       ├── apio.ini
│       ├── empty.v
│       ├── gray-code-counter_tb.gtkw
│       └── gray-code-counter_tb.v
├── 10-metastability/
│   ├── example-01-metastability-test/
│   │   ├── apio.ini
│   │   ├── dual-sqwv.dwf3work
│   │   ├── metastability-test.pcf
│   │   └── metastability-test.v
│   ├── example-02-better-clock-divider/
│   │   ├── apio.ini
│   │   ├── clock-divider.v
│   │   ├── clock-divider_tb.gtkw
│   │   ├── clock-divider_tb.v
│   │   ├── slow-blink.pcf
│   │   └── slow-blink.v
│   ├── example-03-better-debouncer/
│   │   ├── apio.ini
│   │   ├── debouncer.v
│   │   ├── debouncer_tb.gtkw
│   │   └── debouncer_tb.v
│   └── solution-async-fifo/
│       ├── apio.ini
│       ├── async-fifo.v
│       ├── async-fifo_tb.gtkw
│       ├── async-fifo_tb.v
│       ├── dummy.pcf
│       ├── r-ptr-empty.v
│       └── w-ptr-full.v
├── 11-risc-v-softcore-cpu/
│   ├── example-01-blinky/
│   │   ├── Makefile
│   │   └── main.c
│   └── solution-buttons/
│       ├── Makefile
│       └── main.c
├── 12-risc-v-custom-peripheral/
│   └── example-01-pwm/
│       ├── C/
│       │   └── pwm_test/
│       │       ├── Makefile
│       │       └── main.c
│       └── RTL/
│           ├── apio.ini
│           ├── pwm.pcf
│           ├── pwm.v
│           ├── pwm_tb.gtkw
│           └── pwm_tb.v
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# yosys - Verilog synthesis
# nextpnr - Place and route
# Icarus Verilog - Simulation
# GTKWate - Simulation viewer
*.dblite
*.history
*.asc
*.bin
*.json
*.out
*.vcd
*.out

================================================
FILE: 02-install-apio/solution-turn-off-led/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 02-install-apio/solution-turn-off-led/info
================================================
Hello world example for the Icestick board. Turning all the leds on


================================================
FILE: 02-install-apio/solution-turn-off-led/leds.pcf
================================================
# -----------------------------------------------------------------------------
#- Leds example for the iCEstick board
#- Constraint file (.pcf)
# -----------------------------------------------------------------------------
# --  Pinout: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/images/icestick_pinout.png
# --  Guide: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/icestickusermanual.pdf

# ------------ User Leds ------------------------------------------------------
set_io  D1  99
set_io  D2  98
set_io  D3  97
set_io  D4  96
set_io  D5  95


================================================
FILE: 02-install-apio/solution-turn-off-led/leds.v
================================================
//------------------------------------------------------------------
//-- Hello world example for the iCEstick board
//-- Turn on all the leds
//------------------------------------------------------------------

module leds(output wire D1,
            output wire D2,
            output wire D3,
            output wire D4,
            output wire D5);

assign D1 = 1'b1;
assign D2 = 1'b1;
assign D3 = 1'b1;
assign D4 = 1'b1;
assign D5 = 1'b0;

endmodule


================================================
FILE: 02-install-apio/solution-turn-off-led/leds_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.66 (w)1999-2015 BSI
[*] Mon Aug 29 09:12:21 2016
[*]
[dumpfile] "/home/jesus/code/apio-examples/icestick-leds/leds_tb.vcd"
[dumpfile_mtime] "Mon Aug 29 09:10:49 2016"
[dumpfile_size] 606
[savefile] "/home/jesus/code/apio-examples/icestick-leds/leds_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] 507 137
*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
[treeopen] leds_tb.
[sst_width] 223
[signals_width] 78
[sst_expanded] 1
[sst_vpaned_height] 160
@28
leds_tb.UUT.D1
leds_tb.UUT.D2
leds_tb.UUT.D3
leds_tb.UUT.D4
@29
leds_tb.UUT.D5
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 02-install-apio/solution-turn-off-led/leds_tb.v
================================================
//-------------------------------------------------------------------
//-- leds_tb.v
//-- Testbench
//-------------------------------------------------------------------
//-- Juan Gonzalez (Obijuan)
//-- Jesus Arroyo Torrens
//-- GPL license
//-------------------------------------------------------------------
`default_nettype none
`define DUMPSTR(x) `"x.vcd`"
`timescale 100 ns / 10 ns

module leds_tb();

//-- Simulation time: 1us (10 * 100ns)
parameter DURATION = 10;

//-- Clock signal. It is not used in this simulation
reg clk = 0;
always #0.5 clk = ~clk;

//-- Leds port
wire d1, d2, d3, d4, d5;

//-- Instantiate the unit to test
leds UUT (
           .D1(d1),
           .D2(d2),
           .D3(d3),
           .D4(d4),
           .D5(d5)
         );


initial begin

  //-- File were to store the simulation results
  $dumpfile(`DUMPSTR(`VCD_OUTPUT));
  $dumpvars(0, leds_tb);

   #(DURATION) $display("End of simulation");
  $finish;
end

endmodule


================================================
FILE: 03-verilog-gate-logic/example-01-and-gate/and_gate.pcf
================================================
# LEDs
set_io              led_0   99

# PMOD I/O
set_io  -pullup yes pmod_0  78
set_io  -pullup yes pmod_1  79

================================================
FILE: 03-verilog-gate-logic/example-01-and-gate/and_gate.v
================================================
// AND gate example
//
// Inputs:
//      pmod_0  - pushbutton
//      pmod_1  - pushbutton
// Outputs:
//      led_0   - LED
//
// LED will turn on if both pushbuttons are pressed (~pmod_0 & ~pmod_1).
//
// Date: October 13, 2021
// Author: Shawn Hymel
// License: 0BSD

// Module: when buttons 1 and 2 are pressed, turn on LED
module and_gate (

    // Inputs
    input   pmod_0,
    input   pmod_1,
    
    // Outputs
    output  led_0
);

    // Continuous assignment: NOT and AND operators
    assign led_0 = ~pmod_0 & ~pmod_1;
    
endmodule

================================================
FILE: 03-verilog-gate-logic/example-01-and-gate/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 03-verilog-gate-logic/example-02-vectors/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 03-verilog-gate-logic/example-02-vectors/vectors.pcf
================================================
# LEDs
set_io              led[0]  99
set_io              led[1]  98
set_io              led[2]  97
set_io              led[3]  96
set_io              led[4]  95

# PMOD I/O
set_io  -pullup yes pmod[0] 78
set_io  -pullup yes pmod[1] 79

================================================
FILE: 03-verilog-gate-logic/example-02-vectors/vectors.v
================================================
// Vector and intermediate (wire) value example
//
// Inputs:
//      pmod[1:0]   - pushbuttons (x2)
//
// Outputs:
//      led[2:0]    - LEDs (x3)
//
// LEDs 0 and 1 turn on if pmod[0] button is pressed. LED 2 turns on if pmod[0]
// and pmod[1] are pressed together.
//
// Date: October 13, 2021
// Author: Shawn Hymel
// License: 0BSD

// Module: button 0 lights up 2 LEDs, button 0 and 1 light up another LED
module and_gate (

    // Inputs
    input   [1:0]   pmod,
    
    // Output
    output  [2:0]   led
);

    // Wire (net) declarations (internal to module)
    wire not_pmod_0;

    // Continuous assignment: replicate 1 wire to 2 outputs
    assign not_pmod_0 = ~pmod[0];
    assign led[1:0] = {2{not_pmod_0}};
    
    // Continuous assignment: NOT and AND operators
    assign led[2] = not_pmod_0 & ~pmod[1];
    
endmodule

================================================
FILE: 03-verilog-gate-logic/solution-full-adder/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 03-verilog-gate-logic/solution-full-adder/full-adder.pcf
================================================
# LEDs
set_io              led[0]  99
set_io              led[1]  98

# PMOD I/O
set_io  -pullup yes pmod[0] 78
set_io  -pullup yes pmod[1] 79
set_io  -pullup yes pmod[2] 80

================================================
FILE: 03-verilog-gate-logic/solution-full-adder/full-adder.v
================================================
// Solution to full adder challenge
//
// Inputs:
//      pmod[2:0]   - pushbuttons (x3)
//
// Outputs:
//      led[1:0]    - LEDs (x2)
//
// LED 0 turns on if 1 or 3 buttons are pressed. LED 1 turns on if 2 or 3
// buttons are pressed.
//
// Date: October 25, 2021
// Author: Shawn Hymel
// License: 0BSD

// Full adder with button inputs
module full_adder (

    // Inputs
    input   [2:0]   pmod,
    
    // Output
    output  [1:0]   led
);

    // Wire (net) declarations (internal to module)
    wire a;
    wire b;
    wire c_in;
    wire a_xor_b;
    
    // A, B, and C_IN are inverted button logic
    assign a = ~pmod[0];
    assign b = ~pmod[1];
    assign c_in = ~pmod[2];
    
    // Create intermediate wire (net)
    assign a_xor_b = a ^ b;

    // Create output logic
    assign led[0] = a_xor_b ^ c_in;
    assign led[1] = (a_xor_b & c_in) | (a & b);
    
endmodule

================================================
FILE: 04-clocks-and-procedural-assignments/example-01-button-counter/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 04-clocks-and-procedural-assignments/example-01-button-counter/button-counter.pcf
================================================
# LEDs
set_io              led[0]  99
set_io              led[1]  98
set_io              led[2]  97
set_io              led[3]  96

# PMOD I/O
set_io  -pullup yes pmod[0] 78
set_io  -pullup yes pmod[1] 79

================================================
FILE: 04-clocks-and-procedural-assignments/example-01-button-counter/button-counter.v
================================================
// Button counter
//
// Inputs:
//      pmod[0]     - pushbutton (RESET)
//      pmod[1]     - pushbutton (CLOCK)
// Outputs:
//      led[3:0]    - LEDs (count from 0x0 to 0xf)
//
// LEDs will count up in binary on each CLOCK button press. Note: there will
// be a lot of button bounce, so don't worry if the numbers seem to skip around!
//
// Date: October 26, 2021
// Author: Shawn Hymel
// License: 0BSD

// Count up on each button press and display on LEDs
module button_counter (

    // Inputs
    input       [1:0]   pmod,
    
    // Outputs
    output  reg [3:0]   led
);

    wire rst;
    wire clk;

    // Reset is the inverse of the first button
    assign rst = ~pmod[0];

    // Clock signal is the inverse of second button
    assign clk = ~pmod[1];

    // Count up on clock rising edge or reset on button push
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            led <= 4'b0;
        end else begin
            led <= led + 1'b1;
        end
    end
    
endmodule

================================================
FILE: 04-clocks-and-procedural-assignments/solution-clock-counter/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 04-clocks-and-procedural-assignments/solution-clock-counter/clock-counter.pcf
================================================
# Oscillator
set_io              clk     21

# LEDs
set_io              led[0]  99
set_io              led[1]  98
set_io              led[2]  97
set_io              led[3]  96

# PMOD I/O
set_io  -pullup yes rst_btn 78

================================================
FILE: 04-clocks-and-procedural-assignments/solution-clock-counter/clock-counter.v
================================================
// Clock-divided counter
//
// Inputs:  
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
//      
// Outputs:
//      led[3:0]    - LEDs (count from 0x0 to 0xf)
//
// LEDs will display a binary number that increments by one each second.
//
// Date: October 26, 2021
// Author: Shawn Hymel
// License: 0BSD

// Count up each second
module clock_counter (

    // Inputs
    input               clk,
    input               rst_btn,
    
    // Outputs
    output  reg [3:0]   led
);

    wire rst;
    reg div_clk;
    reg [31:0] count;
    localparam [31:0] max_count = 6000000 - 1;

    // Reset is the inverse of the reset button
    assign rst = ~rst_btn;

    // Count up on (divided) clock rising edge or reset on button push
    always @ (posedge div_clk or posedge rst) begin
        if (rst == 1'b1) begin
            led <= 4'b0;
        end else begin
            led <= led + 1'b1;
        end
    end
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count <= 32'b0;
        end else if (count == max_count) begin
            count <= 32'b0;
            div_clk <= ~div_clk;
        end else begin
            count <= count + 1;
        end
    end
    
endmodule


================================================
FILE: 05-finite-state-machines/example-01-moore-fsm/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 05-finite-state-machines/example-01-moore-fsm/moore-fsm.pcf
================================================
# Oscillator
set_io              clk         21

# LEDs
set_io              led[0]      99
set_io              led[1]      98
set_io              led[2]      97
set_io              led[3]      96
set_io              done_sig    95

# PMOD I/O
set_io  -pullup yes rst_btn     78
set_io  -pullup yes go_btn      79

================================================
FILE: 05-finite-state-machines/example-01-moore-fsm/moore-fsm.v
================================================
// Count up on button press and stop (Moore state machine)
// 
// Inputs:
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
//      go_btn      - pushbutton (GO)
// 
// Outputs:
//      led[3:0]    - LEDs (count from 0x0 to 0xf)
//      done_sig    - LED that flashes once when counting is done_sig
// 
// Press GO button to start counting. When max value (0xf) is reached, green
// LED will flash once, and the state machine will return to the Idle state.
//
// Date: November 4, 2021
// Author: Shawn Hymel
// License: 0BSD

// State machine that counts up when button is pressed
module moore_fsm (

    // Inputs
    input               clk,
    input               rst_btn,
    input               go_btn,
    
    // Outputs
    output  reg [3:0]   led,
    output  reg         done_sig
);

    // States
    localparam  STATE_IDLE      = 2'd0;
    localparam  STATE_COUNTING  = 2'd1;
    localparam  STATE_DONE      = 2'd2;
    
    // Max counts for clock divider and counter
    localparam  MAX_CLK_COUNT   = 24'd1500000;
    localparam  MAX_LED_COUNT   = 4'hF;
    
    // Internal signals
    wire rst;
    wire go;
    
    // Internal storage elements
    reg         div_clk;
    reg [1:0]   state;
    reg [23:0]  clk_count;
    
    // Invert active-low buttons
    assign rst = ~rst_btn;
    assign go = ~go_btn;
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            clk_count <= 24'b0;
        end else if (clk_count == MAX_CLK_COUNT) begin
            clk_count <= 24'b0;
            div_clk <= ~div_clk;
        end else begin
            clk_count <= clk_count + 1;
        end
    end
    
    // State transition logic
    always @ (posedge div_clk or posedge rst) begin
    
        // On reset, return to idle state
        if (rst == 1'b1) begin
            state <= STATE_IDLE;
            
        // Define the state transitions
        end else begin
            case (state)
            
                // Wait for go button to be pressed
                STATE_IDLE: begin
                    if (go == 1'b1) begin
                        state <= STATE_COUNTING;
                    end
                end
                
                // Go from counting to done if counting reaches max
                STATE_COUNTING: begin
                    if (led == MAX_LED_COUNT) begin
                        state <= STATE_DONE;
                    end
                end
                
                // Spend one clock cycle in done state
                STATE_DONE: state <= STATE_IDLE;
                
                // Go to idle if in unknown state
                default: state <= STATE_IDLE;
            endcase
        end
    end
    
    // Handle the LED counter
    always @ (posedge div_clk or posedge rst) begin
        if (rst == 1'b1) begin
            led <= 4'd0;
        end else begin
            if (state == STATE_COUNTING) begin
                led <= led + 1;
            end else begin
                led <= 4'd0;
            end
        end
    end
    
    // Handle done LED output
    always @ ( * ) begin
        if (state == STATE_DONE) begin
            done_sig = 1'b1;
        end else begin
            done_sig = 1'b0;
        end
    end
    
endmodule


================================================
FILE: 05-finite-state-machines/example-02-mealy-fsm/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 05-finite-state-machines/example-02-mealy-fsm/mealy-fsm.pcf
================================================
# Oscillator
set_io              clk         21

# LEDs
set_io              led[0]      99
set_io              led[1]      98
set_io              led[2]      97
set_io              led[3]      96
set_io              done_sig    95

# PMOD I/O
set_io  -pullup yes rst_btn     78
set_io  -pullup yes go_btn      79

================================================
FILE: 05-finite-state-machines/example-02-mealy-fsm/mealy-fsm.v
================================================
// Count up on button press and stop (Mealy state machine)
// 
// Inputs:
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
//      go_btn      - pushbutton (GO)
// 
// Outputs:
//      led[3:0]    - LEDs (count from 0x0 to 0xf)
//      done_sig    - LED that flashes once when counting is done_sig
// 
// Press GO button to start counting. When max value (0xf) is reached, green
// LED will flash once, and the state machine will return to the Idle state.
//
// Date: November 4, 2021
// Author: Shawn Hymel
// License: 0BSD

// State machine that counts up when button is pressed
module mealy_fsm (

    // Inputs
    input               clk,
    input               rst_btn,
    input               go_btn,
    
    // Outputs
    output  reg [3:0]   led,
    output  reg         done_sig
);

    // States
    localparam  STATE_IDLE      = 1'd0;
    localparam  STATE_COUNTING  = 1'd1;
    
    // Max counts for clock divider and counter
    localparam  MAX_CLK_COUNT   = 24'd1500000;
    localparam  MAX_LED_COUNT   = 4'hF;
    
    // Internal signals
    wire rst;
    wire go;
    
    // Internal storage elements
    reg         div_clk;
    reg         state;
    reg [23:0]  clk_count;
    
    // Invert active-low buttons
    assign rst = ~rst_btn;
    assign go = ~go_btn;
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            clk_count <= 24'b0;
        end else if (clk_count == MAX_CLK_COUNT) begin
            clk_count <= 24'b0;
            div_clk <= ~div_clk;
        end else begin
            clk_count <= clk_count + 1;
        end
    end
    
    // State transition logic
    always @ (posedge div_clk or posedge rst) begin
    
        // On reset, return to idle state
        if (rst == 1'b1) begin
            state <= STATE_IDLE;
            
        // Define the state transitions
        end else begin
            case (state)
            
                // Wait for go button to be pressed
                STATE_IDLE: begin
                    done_sig <= 1'b0;
                    if (go == 1'b1) begin
                        state <= STATE_COUNTING;
                    end
                end
                
                // Go from counting to done if counting reaches max
                STATE_COUNTING: begin
                    if (led == MAX_LED_COUNT) begin
                        done_sig <= 1'b1;
                        state <= STATE_IDLE;
                    end
                end
                
                // Go to idle if in unknown state
                default: state <= STATE_IDLE;
            endcase
        end
    end
    
    // Handle the LED counter
    always @ (posedge div_clk or posedge rst) begin
        if (rst == 1'b1) begin
            led <= 4'd0;
        end else begin
            if (state == STATE_COUNTING) begin
                led <= led + 1;
            end else begin
                led <= 4'd0;
            end
        end
    end
    
endmodule
            
    
      
       
    

================================================
FILE: 05-finite-state-machines/solution-button-debouncing/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 05-finite-state-machines/solution-button-debouncing/solution-button-debouncing.pcf
================================================
# Oscillator
set_io              clk         21

# LEDs
set_io              led[0]      99
set_io              led[1]      98
set_io              led[2]      97
set_io              led[3]      96

# PMOD I/O
set_io  -pullup yes rst_btn     78
set_io  -pullup yes inc_btn     79

================================================
FILE: 05-finite-state-machines/solution-button-debouncing/solution-button-debouncing.v
================================================
// One possible way to debounce a button press (using a Moore state machine)
// 
// Inputs:
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
//      inc_btn     - pushbutton (INCREMENT)
// 
// Outputs:
//      led[3:0]    - LEDs (count from 0x0 to 0xf)
// 
// One press of the increment button should correspond to one and only one
// increment of the counter. Use a state machine to identify the edge on the
// button line, wait 40 ms, and sample again to see if the button is still
// pressed.
//
// Date: November 5, 2021
// Author: Shawn Hymel
// License: 0BSD

// Use a state machine to debounce the button, which increments a counter
module debounced_counter (

    // Inputs
    input               clk,
    input               rst_btn,
    input               inc_btn,
    
    // Outputs
    output  reg [3:0]   led
);

    // States
    localparam STATE_HIGH       = 2'd0;
    localparam STATE_LOW        = 2'd1;    
    localparam STATE_WAIT       = 2'd2;
    localparam STATE_PRESSED    = 2'd3;
    
    // Max counts for wait state (40 ms with 12 MHz clock)
    localparam MAX_CLK_COUNT    = 20'd480000 - 1;
    
    // Internal signals
    wire rst;
    wire inc;
    
    // Internal storage elements
    reg [1:0]   state;
    reg [19:0]  clk_count;
    
    // Invert active-low buttons
    assign rst = ~rst_btn;
    assign inc = ~inc_btn;
    
    // State transition logic
    always @ (posedge clk or posedge rst) begin
    
        // On reset, return to idle state and restart counters
        if (rst == 1'b1) begin
            state <= STATE_HIGH;
            led <= 4'd0;
            
        // Define the state transitions
        end else begin
            case (state)
            
                // Wait for increment signal to go from high to low
                STATE_HIGH: begin
                    if (inc == 1'b0) begin
                        state <= STATE_LOW;
                    end
                end
            
                // Wait for increment signal to go from low to high
                STATE_LOW: begin
                    if (inc == 1'b1) begin
                        state <= STATE_WAIT;
                    end
                end
                
                // Wait for count to be done and sample button again
                STATE_WAIT: begin
                    if (clk_count == MAX_CLK_COUNT) begin
                        if (inc == 1'b1) begin
                            state <= STATE_PRESSED;
                        end else begin
                            state <= STATE_HIGH;
                        end
                    end
                end
                
                // If button is still pressed, increment LED counter
                STATE_PRESSED: begin
                    led <= led + 1;
                    state <= STATE_HIGH;
                end
                
                    
                // Default case: return to idle state
                default: state <= STATE_HIGH;
            endcase
        end
    end
    
    // Run counter if in wait state
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            clk_count <= 20'd0;
        end else begin
            if (state == STATE_WAIT) begin
                clk_count <= clk_count + 1;
            end else begin
                clk_count <= 20'd0;
            end
        end
    end
    
endmodule


================================================
FILE: 06-modules-and-parameters/example-01-parameters/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 06-modules-and-parameters/example-01-parameters/clock-divider.v
================================================
// Simple clock divider
//
// Parameters:
//      COUNT_WIDTH - Bus width for counter
//      MAX_COUNT   - Maximum value of counter
// 
// Inputs:
//      clk         - Input clock
//      rst         - Reset signal
// 
// Outputs:
//      out         - Divided clock output
// 
// Toggles out line at a divided rate given clk input.
//
// Date: November 8, 2021
// Author: Shawn Hymel
// License: 0BSD

// Clock divider
module clock_divider (

    // Inputs
    input       clk,
    input       rst,
    
    // Outputs
    output  reg out    
);

    // Parameters
    parameter                   COUNT_WIDTH = 24;
    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1;

    // Internal signals
    wire rst;
    reg div_clk;
    reg [COUNT_WIDTH:0] count;
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count <= 0;
            out <= 0;
        end else if (count == MAX_COUNT) begin
            count <= 0;
            out <= ~out;
        end else begin
            count <= count + 1;
        end
    end
    
endmodule

================================================
FILE: 06-modules-and-parameters/example-01-parameters/top-design.pcf
================================================
# Oscillator
set_io              clk     21

# LEDs
set_io              led[0]  99
set_io              led[1]  98

# PMOD I/O
set_io  -pullup yes rst_btn 78

================================================
FILE: 06-modules-and-parameters/example-01-parameters/top-design.v
================================================
// Example of a top-level design with 2 different clocks.
// 
// Inputs:
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
// 
// Outputs:
//      led[1:0]    - LEDs
// 
// LED[0] should flash at 4 Hz and LED[1] should flash at 1 Hz.
//
// Date: November 8, 2021
// Author: Shawn Hymel
// License: 0BSD

// Top-level design that produces 2 different divided clocks
module top_design (

    // Inputs
    input           clk,
    input           rst_btn,
    
    // Outputs
    output  [1:0]   led         // Not reg element!
);

    // Internal signals
    wire rst;
    
    // Invert active-low button
    assign rst = ~rst_btn;

    // Instantiate the first clock divider module
    clock_divider div_1 (
        .clk(clk), 
        .rst(rst), 
        .out(led[0])
    );
    defparam div_1.COUNT_WIDTH  = 32;
    defparam div_1.MAX_COUNT    = 1500000 - 1;
    
    // Instantiate the second clock divider module
    clock_divider div_2 (
        .clk(clk),
        .rst(rst),
        .out(led[1])
    );
                    
endmodule

================================================
FILE: 06-modules-and-parameters/example-02-ansi-parameters/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 06-modules-and-parameters/example-02-ansi-parameters/clock-divider.v
================================================
// Simple clock divider
//
// Parameters:
//      COUNT_WIDTH - Bus width for counter
//      MAX_COUNT   - Maximum value of counter
// 
// Inputs:
//      clk         - Input clock
//      rst         - Reset signal
// 
// Outputs:
//      out         - Divided clock output
// 
// Toggles out line at a divided rate given clk input.
//
// Date: November 8, 2021
// Author: Shawn Hymel
// License: 0BSD

// Clock divider
module clock_divider #(

    // Parameters
    parameter                   COUNT_WIDTH = 24,
    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1
) (

    // Inputs
    input       clk,
    input       rst,
    
    // Outputs
    output  reg out    
);

    // Internal signals
    wire rst;
    reg div_clk;
    reg [COUNT_WIDTH:0] count;
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count <= 0;
            out <= 0;
        end else if (count == MAX_COUNT) begin
            count <= 0;
            out <= ~out;
        end else begin
            count <= count + 1;
        end
    end
    
endmodule

================================================
FILE: 06-modules-and-parameters/example-02-ansi-parameters/top-design.pcf
================================================
# Oscillator
set_io              clk     21

# LEDs
set_io              led[0]  99
set_io              led[1]  98

# PMOD I/O
set_io  -pullup yes rst_btn 78

================================================
FILE: 06-modules-and-parameters/example-02-ansi-parameters/top-design.v
================================================
// Example of a top-level design with 2 different clocks.
// 
// Inputs:
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
// 
// Outputs:
//      led[1:0]    - LEDs
// 
// LED[0] should flash at 4 Hz and LED[1] should flash at 1 Hz.
//
// Date: November 8, 2021
// Author: Shawn Hymel
// License: 0BSD

// Top-level design that produces 2 different divided clocks
module top_design (

    // Inputs
    input           clk,
    input           rst_btn,
    
    // Outputs
    output  [1:0]   led         // Not reg element!
);

    // Internal signals
    wire rst;
    
    // Invert active-low button
    assign rst = ~rst_btn;

    // Instantiate the first clock divider module
    clock_divider #(.COUNT_WIDTH(32), .MAX_COUNT(1500000 - 1)) div_1 (
        .clk(clk), 
        .rst(rst), 
        .out(led[0])
    );
    
    // Instantiate the second clock divider module
    clock_divider div_2 (
        .clk(clk),
        .rst(rst),
        .out(led[1])
    );
                    
endmodule

================================================
FILE: 06-modules-and-parameters/solution-count-up-down/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 06-modules-and-parameters/solution-count-up-down/clock-divider.v
================================================
// Simple clock divider
//
// Parameters:
//      COUNT_WIDTH - Bus width for counter
//      MAX_COUNT   - Maximum value of counter
// 
// Inputs:
//      clk         - Input clock
//      rst         - Reset signal
// 
// Outputs:
//      out         - Divided clock output
// 
// Toggles out line at a divided rate given clk input.
//
// Date: November 8, 2021
// Author: Shawn Hymel
// License: 0BSD

// Clock divider
module clock_divider #(

    // Parameters
    parameter                   COUNT_WIDTH = 24,
    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1
) (

    // Inputs
    input       clk,
    input       rst,
    
    // Outputs
    output  reg out    
);

    // Internal signals
    wire rst;
    reg div_clk;
    reg [COUNT_WIDTH:0] count;
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count <= 0;
            out <= 0;
        end else if (count == MAX_COUNT) begin
            count <= 0;
            out <= ~out;
        end else begin
            count <= count + 1;
        end
    end
    
endmodule

================================================
FILE: 06-modules-and-parameters/solution-count-up-down/count-up-down-top.v
================================================
// One possible solution to the count up and down challenge
//
// Inputs:
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
//
// Outputs:
//      led[3:0]    - LEDs (connected to counter outputs)
//
// LEDs continuously count up and down.
//
// Date: November 9, 2021
// Author: Shawn Hymel
// License: 0BSD

// Top-level design that controls the clock divider and counter FSMs
module count_up_down_top (

    // Inputs
    input               clk,
    input               rst_btn,
    
    // Outputs
    output  reg [3:0]   led
);

    // Internal signals
    wire            rst;
    wire            div_clk;
    wire            up_done;
    wire            down_done;
    wire    [3:0]   up_out;
    wire    [3:0]   down_out;
    
    // Storage elements
    reg             init_go;
    reg             counting_up;
    
    // Invert active-low buttons
    assign rst = ~rst_btn;
    
    // Use the reset button to start the endless loop of counters
    always @ (posedge div_clk or posedge rst) begin
        if (rst == 1'b1) begin
            init_go <= 1'b1;
        end else begin
            init_go <= 1'b0;
        end
    end
    
    // Remember if we're counting up or down
    always @ (posedge div_clk or posedge rst) begin
        if (rst == 1'b1) begin
            counting_up <= 1'b1;
        end else begin
            if (up_done == 1'b1) begin
                counting_up <= 1'b0;
            end else if (down_done == 1'b1) begin
                counting_up <= 1'b1;
            end
        end
    end
    
    // Multiplexer to switch which counter is controlling the LEDs
    always @ ( * ) begin
        if (counting_up == 1'b1) begin
            led = up_out;
        end else begin
            led = down_out;
        end
    end
    
    // Clock divider
    clock_divider #(.COUNT_WIDTH(24), .MAX_COUNT(1500000 - 1)) div (
        .clk(clk),
        .rst(rst),
        .out(div_clk)
    );
    
    // Counter (up)
    counter_fsm #(.COUNT_UP(1), .MAX_COUNT(4'hF)) up_counter (
        .clk(div_clk),
        .rst(rst),
        .go(down_done | init_go),
        .out(up_out),
        .done(up_done)
    );
    
    // Counter (down)
    counter_fsm #(.COUNT_UP(0), .MAX_COUNT(4'hF)) down_counter (
        .clk(div_clk),
        .rst(rst),
        .go(up_done),
        .out(down_out),
        .done(down_done)
    );
    
endmodule

================================================
FILE: 06-modules-and-parameters/solution-count-up-down/count-up-down.pcf
================================================
# Oscillator
set_io              clk         21

# LEDs
set_io              led[0]      99
set_io              led[1]      98
set_io              led[2]      97
set_io              led[3]      96

# PMOD I/O
set_io  -pullup yes rst_btn     78

================================================
FILE: 06-modules-and-parameters/solution-count-up-down/counter-fsm.v
================================================
// Count up on button signal and stop.
//
// Parameters:
//      COUNT_UP    - 1 to count up, 0 to count down
//      MAX_COUNT   - Maximum number to count to
// 
// Inputs:
//      clk         - Clock input to module
//      rst         - Reset signal to clear state machine and counter
//      go          - Go signal to start state machine
// 
// Outputs:
//      out[3:0]    - Bus that counts from 0x0 to 0xf or 0xf to 0x0
//      done        - Signal that pulses on 1 clock cycle when FSM is complete
// 
// Send rising edge on go input to start counter. If up is 1, counter will
// count up. Otherwise, it will count down. 
//
// Date: November 9, 2021
// Author: Shawn Hymel
// License: 0BSD

// Mealy state machine that counts when go signal is sent
module counter_fsm #(

    // Parameters
    parameter   COUNT_UP = 1'b1,    // 1'b1 to count up
    parameter   MAX_COUNT = 4'hF    // Maximum number to count to
) (

    // Inputs
    input               clk,
    input               rst,
    input               go,
    
    // Outputs
    output  reg [3:0]   out,
    output  reg         done
);

    // States
    localparam  STATE_IDLE      = 1'd0;
    localparam  STATE_COUNTING  = 1'd1;
    
    // Internal storage elements
    reg         state;
    
    // State transition logic
    always @ (posedge clk or posedge rst) begin
    
        // On reset, return to idle state
        if (rst == 1'b1) begin
            state <= STATE_IDLE;
            
        // Define the state transitions
        end else begin
            case (state)
            
                // Wait for go signal
                STATE_IDLE: begin
                    done <= 1'b0;
                    if (go == 1'b1) begin
                        state <= STATE_COUNTING;
                    end
                end
                
                // Go from counting to done if counting reaches max
                STATE_COUNTING: begin
                    if (COUNT_UP == 1'b1 && out == MAX_COUNT) begin
                        done <= 1'b1;
                        state <= STATE_IDLE;
                    end else if (COUNT_UP == 1'b0 && out == 0) begin
                        done <= 1'b1;
                        state <= STATE_IDLE;
                    end
                end
                
                // Go to idle if in unknown state
                default: state <= STATE_IDLE;
            endcase
        end
    end
    
    // Handle the counter output
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            out <= 4'd0;
        end else begin
            case (state)
            
                // Start counter at the right value
                STATE_IDLE: begin
                    if (COUNT_UP == 1'b1) begin
                        out <= 4'd0;
                    end else begin
                        out <= MAX_COUNT;
                    end
                end
                
                // Count up or down
                STATE_COUNTING: begin
                    if (COUNT_UP == 1'b1) begin
                        if (out != MAX_COUNT) out <= out + 1;
                    end else begin
                        if (out != 4'h0) out <= out - 1;
                    end
                end
                
                default: out <= out;
            endcase
        end
    end
    
endmodule


================================================
FILE: 07-simulation-and-testbenches/example-01-testbench/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 07-simulation-and-testbenches/example-01-testbench/clk-div_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Thu Nov 11 19:42:09 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\07-simulation-and-testbenches\example-01-testbench\clk-div_tb.vcd"
[dumpfile_mtime] "Thu Nov 11 19:40:47 2021"
[dumpfile_size] 4709
[savefile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\07-simulation-and-testbenches\example-01-testbench\clk-div_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] -1 -1
*-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
[treeopen] clock_divider_tb.
[sst_width] 211
[signals_width] 110
[sst_expanded] 1
[sst_vpaned_height] 154
@28
clock_divider_tb.div_1.clk
@22
clock_divider_tb.div_1.count[4:0]
@28
clock_divider_tb.div_1.out
clock_divider_tb.div_1.rst
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 07-simulation-and-testbenches/example-01-testbench/clk-div_tb.v
================================================
// Testbench for clock divider
//
// Date: November 11, 2021
// Author: Shawn Hymel
// License: 0BSD

// Defines timescale for simulation: <time_unit> / <time_precision>
`timescale 1 ns / 10 ps

// Define our testbench
module clock_divider_tb();

    // Internal signals
    wire    out;

    // Storage elements (set initial values to 0)
    reg     clk = 0;
    reg     rst = 0;            

    // Simulation time: 10000 * 1 ns = 10 us
    localparam DURATION = 10000;
    
    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz
    always begin
        
        // Delay for 41.67 time units
        // 10 ps precision means that 41.667 is rounded to 41.67
        #41.667
        
        // Toggle clock line
        clk = ~clk;
    end
    
    // Instantiate the unit under test (UUT)
    clock_divider #(.COUNT_WIDTH(4), .MAX_COUNT(6 - 1)) uut (
        .clk(clk),
        .rst(rst),
        .out(out)
    );
    
    // Pulse reset line high at the beginning
    initial begin
        #10
        rst = 1'b1;
        #1
        rst = 1'b0;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("clk-div_tb.vcd");
        $dumpvars(0, clock_divider_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 07-simulation-and-testbenches/example-01-testbench/clock-divider.v
================================================
// Simple clock divider
//
// Parameters:
//      COUNT_WIDTH - Bus width for counter
//      MAX_COUNT   - Maximum value of counter
// 
// Inputs:
//      clk         - Input clock
//      rst         - Reset signal
// 
// Outputs:
//      out         - Divided clock output
// 
// Toggles out line at a divided rate given clk input.
//
// Date: November 8, 2021
// Author: Shawn Hymel
// License: 0BSD

// Clock divider
module clock_divider (

    // Inputs
    input       clk,
    input       rst,
    
    // Outputs
    output  reg out    
);

    // Parameters
    parameter                   COUNT_WIDTH = 24;
    parameter [COUNT_WIDTH-1:0]   MAX_COUNT   = 6000000 - 1;

    // Internal signals
    wire rst;
    reg div_clk;
    reg [COUNT_WIDTH:0] count;
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count <= 0;
            out <= 0;
        end else if (count == MAX_COUNT) begin
            count <= 0;
            out <= ~out;
        end else begin
            count <= count + 1;
        end
    end
    
endmodule


================================================
FILE: 07-simulation-and-testbenches/solution-debounce-testbench/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing.v
================================================
// One possible way to debounce a button press (using a Moore state machine)
//
// Parameters:
//      MAX_CLK_COUNT   - How long to wait (cycles) before sampling button again
// 
// Inputs:
//      clk             - Input clock
//      rst_btn         - Pushbutton (RESET)
//      inc_btn         - Pushbutton (INCREMENT)
// 
// Outputs:
//      led[3:0]        - LEDs (count from 0x0 to 0xf)
// 
// One press of the increment button should correspond to one and only one
// increment of the counter. Use a state machine to identify the edge on the
// button line, wait 40 ms, and sample again to see if the button is still
// pressed.
//
// Date: November 11, 2021
// Author: Shawn Hymel
// License: 0BSD

// Use a state machine to debounce the button, which increments a counter
module debounced_counter #(

    // Parameters
    parameter MAX_CLK_COUNT     = 20'd480000 - 1
) (

    // Inputs
    input               clk,
    input               rst_btn,
    input               inc_btn,
    
    // Outputs
    output  reg [3:0]   led
);

    // States
    localparam STATE_HIGH       = 2'd0;
    localparam STATE_LOW        = 2'd1;    
    localparam STATE_WAIT       = 2'd2;
    localparam STATE_PRESSED    = 2'd3;
    
    // Internal signals
    wire rst;
    wire inc;
    
    // Internal storage elements
    reg [1:0]   state;
    reg [19:0]  clk_count;
    
    // Invert active-low buttons
    assign rst = ~rst_btn;
    assign inc = ~inc_btn;
    
    // State transition logic
    always @ (posedge clk or posedge rst) begin
    
        // On reset, return to idle state and restart counters
        if (rst == 1'b1) begin
            state <= STATE_HIGH;
            led <= 4'd0;
            
        // Define the state transitions
        end else begin
            case (state)
            
                // Wait for increment signal to go from high to low
                STATE_HIGH: begin
                    if (inc == 1'b0) begin
                        state <= STATE_LOW;
                    end
                end
            
                // Wait for increment signal to go from low to high
                STATE_LOW: begin
                    if (inc == 1'b1) begin
                        state <= STATE_WAIT;
                    end
                end
                
                // Wait for count to be done and sample button again
                STATE_WAIT: begin
                    if (clk_count == MAX_CLK_COUNT) begin
                        if (inc == 1'b1) begin
                            state <= STATE_PRESSED;
                        end else begin
                            state <= STATE_HIGH;
                        end
                    end
                end
                
                // If button is still pressed, increment LED counter
                STATE_PRESSED: begin
                    led <= led + 1;
                    state <= STATE_HIGH;
                end
                
                    
                // Default case: return to idle state
                default: state <= STATE_HIGH;
            endcase
        end
    end
    
    // Run counter if in wait state
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            clk_count <= 0;
        end else begin
            if (state == STATE_WAIT) begin
                clk_count <= clk_count + 1;
            end else begin
                clk_count <= 0;
            end
        end
    end
    
endmodule

================================================
FILE: 07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Thu Nov 11 22:58:44 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\07-simulation-and-testbenches\solution-debounce-testbench\button-debouncing_tb.vcd"
[dumpfile_mtime] "Thu Nov 11 22:56:49 2021"
[dumpfile_size] 4760913
[savefile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\07-simulation-and-testbenches\solution-debounce-testbench\button-debouncing_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] -1 -1
*-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
[treeopen] button_debouncing_tb.
[sst_width] 211
[signals_width] 110
[sst_expanded] 1
[sst_vpaned_height] 154
@28
button_debouncing_tb.uut.clk
button_debouncing_tb.uut.inc_btn
@29
button_debouncing_tb.uut.state[1:0]
@22
button_debouncing_tb.uut.led[3:0]
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing_tb.v
================================================
// Testbench for button debounce design
//
// Date: November 11, 2021
// Author: Shawn Hymel
// License: 0BSD

// Define timescale
`timescale 1 us / 10 ps

// Define our testbench
module button_debouncing_tb();

    // Internal signals
    wire    [3:0]   out;
    
    // Storage elements (buttons are active low!)
    reg             clk = 0;
    reg             rst_btn = 1;
    reg             inc_btn = 1;
    integer         i;              // Used in for loop
    integer         j;              // Used in for loop
    integer         prev_inc;       // Previous increment button state
    integer         nbounces;       // Holds random number
    integer         rdelay;         // Holds random number
    
    // Simulation time: 10000 * 1 us = 10 ms
    localparam DURATION = 10000;
    
    // Generate clock signal (about 12 MHz)
    always begin
        #0.04167
        clk = ~clk;
    end
    
    // Instantiate debounce/counter module (use about 400 us wait time)
    debounced_counter #(.MAX_CLK_COUNT(4800 - 1)) uut (
        .clk(clk),
        .rst_btn(rst_btn),
        .inc_btn(inc_btn),
        .led(out)
    );
    
    // Test control: pulse reset and create some (bouncing) button presses
    initial begin
    
        // Pulse reset low to reset state machine
        #10
        rst_btn = 0;
        #1
        rst_btn = 1;
        
        // We can use for loops in simulation!
        for (i = 0; i < 32; i = i + 1) begin
        
            // Wait some time before pressing button
            #1000
            
            // Simulate a bouncy/noisy button press
            // $urandom generates a 32-bit unsigned (pseudo) random number
            // "% 10" is "modulo 10"
            prev_inc = inc_btn;
            nbounces = $urandom % 20;
            for (j = 0; j < nbounces; j = j + 1) begin
                #($urandom % 10)
                inc_btn = ~inc_btn;
            end
            
            // Make sure button ends up in the opposite state
            inc_btn = ~prev_inc;
        end
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("button-debouncing_tb.vcd");
        $dumpvars(0, button_debouncing_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 08-memory/example-01-memory/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 08-memory/example-01-memory/memory.v
================================================
// Simple block RAM example
// 
// Inputs:
//      clk             - Input clock
//      w_en            - Write enable
//      r_en            - Read enable
//      w_addr[3:0]     - Write address
//      r_addr[3:0]     - Read address
//      w_data[7:0]     - Data to be written
// 
// Outputs:
//      r_data[7:0]     - Data to be read
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Inferred block RAM
module memory (

    // Inputs
    input               clk,
    input               w_en,
    input               r_en,
    input       [3:0]   w_addr,
    input       [3:0]   r_addr,
    input       [7:0]   w_data,
    
    // Outputs
    output  reg [7:0]   r_data
);

    // Declare memory
    reg [7:0]  mem [0:15];
    
    // Interact with the memory block
    always @ (posedge clk) begin
    
        // Write to memory
        if (w_en == 1'b1) begin
            mem[w_addr] <= w_data;
        end
        
        // Read from memory
        if (r_en == 1'b1) begin
            r_data <= mem[r_addr];
        end
    end
    
endmodule

================================================
FILE: 08-memory/example-01-memory/memory_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Mon Nov 15 20:31:41 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\08-memory\example-01-memory\memory_tb.vcd"
[dumpfile_mtime] "Mon Nov 15 20:31:26 2021"
[dumpfile_size] 4133
[savefile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\08-memory\example-01-memory\memory_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] -1 -1
*-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
[sst_width] 211
[signals_width] 118
[sst_expanded] 1
[sst_vpaned_height] 154
@28
memory_tb.clk
@22
memory_tb.r_addr[3:0]
memory_tb.r_data[7:0]
@28
memory_tb.r_en
@22
memory_tb.w_addr[3:0]
memory_tb.w_data[7:0]
@28
memory_tb.w_en
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 08-memory/example-01-memory/memory_tb.v
================================================
// Testbench for memory
//
// First, read from address in memory (should be garbage or unknown). Next,
// write to that location and read from it again. Output should match input.
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Defines timescale for simulation: <time_unit> / <time_precision>
`timescale 1 ns / 10 ps

// Define our testbench
module memory_tb();

    // Internal signals
    wire    [7:0]  r_data;
    

    // Storage elements (set initial values to 0)
    reg             clk = 0;
    reg             w_en = 0;
    reg             r_en = 0;
    reg     [3:0]   w_addr;
    reg     [3:0]   r_addr;
    reg     [7:0]   w_data;

    // Simulation time: 10000 * 1 ns = 10 us
    localparam DURATION = 10000;
    
    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz
    always begin
        #41.67
        clk = ~clk;
    end
    
    // Instantiate the unit under test (UUT)
    memory uut (
        .clk(clk),
        .w_en(w_en),
        .r_en(r_en),
        .w_addr(w_addr),
        .r_addr(r_addr),
        .w_data(w_data),
        .r_data(r_data)
    );
    
    // Run test: write to location and read value back
    initial begin
    
        // Test 1: read from address 0x10 (should be garbage)
        #(2 * 41.67)
        r_addr = 'h0f;
        r_en = 1;
        #(2 * 41.67)
        r_addr = 0;
        r_en = 0;
        
        // Test 2: Write to address 0x0f and read it back
        #(2 * 41.67)
        w_addr = 'h0f;
        w_data = 'hA5;
        w_en = 1;
        #(2 * 41.67)
        w_addr = 0;
        w_data = 0;
        w_en = 0;
        r_addr = 'h0f;
        r_en = 1;
        #(2 * 41.67)
        r_addr = 0;
        r_en = 0;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("memory_tb.vcd");
        $dumpvars(0, memory_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 08-memory/example-01-memory/test.pcf
================================================
# Oscillator
set_io  clk         21

# Dummy ports
set_io  w_en        44
set_io  r_en        45

set_io  w_addr[0]   78
set_io  w_addr[1]   79
set_io  w_addr[2]   80
set_io  w_addr[3]   81

set_io  r_addr[0]   87
set_io  r_addr[1]   88
set_io  r_addr[2]   90
set_io  r_addr[3]   91

set_io  w_data[0]   112
set_io  w_data[1]   113
set_io  w_data[2]   114
set_io  w_data[3]   115
set_io  w_data[4]   116
set_io  w_data[5]   117
set_io  w_data[6]   118
set_io  w_data[7]   119

set_io  r_data[0]   95
set_io  r_data[1]   96
set_io  r_data[2]   97
set_io  r_data[3]   98
set_io  r_data[4]   99
set_io  r_data[5]   60
set_io  r_data[6]   61
set_io  r_data[7]   62


================================================
FILE: 08-memory/example-02-memory-initialization/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 08-memory/example-02-memory-initialization/mem_init.txt
================================================
00
01
02
03
04
05
06
07
b8
b9
ba
bb
bc
bd
be
bf

================================================
FILE: 08-memory/example-02-memory-initialization/memory.v
================================================
// Simple block RAM example
// 
// Inputs:
//      clk             - Input clock
//      w_en            - Write enable
//      r_en            - Read enable
//      w_addr[3:0]     - Write address
//      r_addr[3:0]     - Read address
//      w_data[7:0]     - Data to be written
// 
// Outputs:
//      r_data[7:0]     - Data to be read
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Inferred block RAM
module memory #(

    // Parameters
    parameter   INIT_FILE = ""
) (

    // Inputs
    input               clk,
    input               w_en,
    input               r_en,
    input       [3:0]   w_addr,
    input       [3:0]   r_addr,
    input       [7:0]   w_data,
    
    // Outputs
    output  reg [7:0]   r_data
);

    // Declare memory
    reg [7:0]  mem [0:15];
    
    // Interact with the memory block
    always @ (posedge clk) begin
    
        // Write to memory
        if (w_en == 1'b1) begin
            mem[w_addr] <= w_data;
        end
        
        // Read from memory
        if (r_en == 1'b1) begin
            r_data <= mem[r_addr];
        end
    end
    
    // Initialization (if available)
    initial if (INIT_FILE) begin
        $readmemh(INIT_FILE, mem);
    end
    
endmodule

================================================
FILE: 08-memory/example-02-memory-initialization/memory_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Mon Nov 15 20:27:07 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\08-memory\example-02-memory-initialization\memory_tb.vcd"
[dumpfile_mtime] "Mon Nov 15 20:25:26 2021"
[dumpfile_size] 5178
[savefile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\08-memory\example-02-memory-initialization\memory_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] 1230 252
*-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
[sst_width] 211
[signals_width] 118
[sst_expanded] 1
[sst_vpaned_height] 154
@28
memory_tb.clk
@420
memory_tb.i
@22
memory_tb.r_addr[3:0]
memory_tb.r_data[7:0]
@28
memory_tb.r_en
@22
memory_tb.w_addr[3:0]
memory_tb.w_data[7:0]
@28
memory_tb.w_en
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 08-memory/example-02-memory-initialization/memory_tb.v
================================================
// Testbench for memory
//
// First, read from address in memory (should be garbage or unknown). Next,
// write to that location and read from it again. Output should match input.
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Defines timescale for simulation: <time_unit> / <time_precision>
`timescale 1 ns / 10 ps

// Define our testbench
module memory_tb();

    // Internal signals
    wire    [7:0]  r_data;
    

    // Storage elements (set initial values to 0)
    reg             clk = 0;
    reg             w_en = 0;
    reg             r_en = 0;
    reg     [3:0]   w_addr;
    reg     [3:0]   r_addr;
    reg     [7:0]   w_data;
    integer         i;

    // Simulation time: 10000 * 1 ns = 10 us
    localparam DURATION = 10000;
    
    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz
    always begin
        #41.67
        clk = ~clk;
    end
    
    // Instantiate the unit under test (UUT)
    memory #(.INIT_FILE("mem_init.txt")) uut (
        .clk(clk),
        .w_en(w_en),
        .r_en(r_en),
        .w_addr(w_addr),
        .r_addr(r_addr),
        .w_data(w_data),
        .r_data(r_data)
    );
    
    // Run test: write to location and read value back
    initial begin
    
        // Test 1: read initial values
        for (i = 0; i < 16; i = i + 1) begin
            #(2 * 41.67)
            r_addr = i;
            r_en = 1;
            #(2 * 41.67)
            r_addr = 0;
            r_en = 0;
        end
        
        // Test 2: Write to address 0x0f and read it back
        #(2 * 41.67)
        w_addr = 'h0f;
        w_data = 'hA5;
        w_en = 1;
        #(2 * 41.67)
        w_addr = 0;
        w_data = 0;
        w_en = 0;
        r_addr = 'h0f;
        r_en = 1;
        #(2 * 41.67)
        r_addr = 0;
        r_en = 0;
        
        // Test 3: Read and write at same time
        #(2 * 41.67)
        w_addr = 'h0a;
        w_data = 'hef;
        w_en = 1;
        r_addr = 'h0a;
        r_en = 1;
        #(2 * 41.67)
        w_addr = 0;
        w_data = 0;
        w_en = 0;
        r_addr = 0;
        r_en = 0;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("memory_tb.vcd");
        $dumpvars(0, memory_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 08-memory/example-02-memory-initialization/test.pcf
================================================
# Oscillator
set_io  clk         21

# Dummy ports
set_io  w_en        44
set_io  r_en        45

set_io  w_addr[0]   78
set_io  w_addr[1]   79
set_io  w_addr[2]   80
set_io  w_addr[3]   81

set_io  r_addr[0]   87
set_io  r_addr[1]   88
set_io  r_addr[2]   90
set_io  r_addr[3]   91

set_io  w_data[0]   112
set_io  w_data[1]   113
set_io  w_data[2]   114
set_io  w_data[3]   115
set_io  w_data[4]   116
set_io  w_data[5]   117
set_io  w_data[6]   118
set_io  w_data[7]   119

set_io  r_data[0]   95
set_io  r_data[1]   96
set_io  r_data[2]   97
set_io  r_data[3]   98
set_io  r_data[4]   99
set_io  r_data[5]   60
set_io  r_data[6]   61
set_io  r_data[7]   62


================================================
FILE: 08-memory/solution-sequencer/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 08-memory/solution-sequencer/clock-divider.v
================================================
// Simple clock divider
//
// Parameters:
//      COUNT_WIDTH - Bus width for counter
//      MAX_COUNT   - Maximum value of counter
// 
// Inputs:
//      clk         - Input clock
//      rst         - Reset signal
// 
// Outputs:
//      out         - Divided clock output
// 
// Toggles out line at a divided rate given clk input.
//
// Date: November 8, 2021
// Author: Shawn Hymel
// License: 0BSD

// Clock divider
module clock_divider #(

    // Parameters
    parameter                   COUNT_WIDTH = 24,
    parameter [COUNT_WIDTH:0]   MAX_COUNT   = 6000000 - 1
) (

    // Inputs
    input       clk,
    input       rst,
    
    // Outputs
    output  reg out    
);

    // Internal signals
    wire rst;
    reg div_clk;
    reg [COUNT_WIDTH:0] count;
    
    // Clock divider
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count <= 0;
            out <= 0;
        end else if (count == MAX_COUNT) begin
            count <= 0;
            out <= ~out;
        end else begin
            count <= count + 1;
        end
    end
    
endmodule

================================================
FILE: 08-memory/solution-sequencer/debouncer.v
================================================
// One possible way to debounce a button press (using a Moore state machine)
// 
// Inputs:
//      clk         - 12 MHz clock
//      rst         - reset signal
//      in          - input signal
// 
// Outputs:
//      out         - output signal (debounced)
// 
// Single pulse sent on out when in signal goes high for some time.
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Use a state machine to debounce a button
module debouncer #(

    // Max counts for wait state (40 ms with 12 MHz clock)
    parameter                   COUNT_WIDTH     = 20,
    parameter [COUNT_WIDTH:0]   MAX_CLK_COUNT   = 480000 - 1
) (

    // Inputs
    input               clk,
    input               rst,
    input               in,
    
    // Outputs
    output  reg         out
);

    // States
    localparam  STATE_HIGH      = 2'd0;
    localparam  STATE_LOW       = 2'd1;    
    localparam  STATE_WAIT      = 2'd2;
    localparam  STATE_PRESSED   = 2'd3;
    
    // Internal storage elements
    reg [1:0]           state;
    reg [COUNT_WIDTH:0] clk_count;
    
    // State transition logic
    always @ (posedge clk or posedge rst) begin
    
        // On reset, return to idle state
        if (rst == 1'b1) begin
            state <= STATE_HIGH;
            out <= 1'b0;
            
        // Define the state transitions
        end else begin
            case (state)
            
                // Wait for increment signal to go from high to low
                STATE_HIGH: begin
                    out <= 1'b0;
                    if (in == 1'b0) begin
                        state <= STATE_LOW;
                    end
                end
                
                // Wait for increment signal to go from low to high
                STATE_LOW: begin
                    if (in == 1'b1) begin
                        state <= STATE_WAIT;
                    end
                end
                
                // Wait for count to be done and sample button again
                STATE_WAIT: begin
                    if (clk_count == MAX_CLK_COUNT) begin
                        if (in == 1'b1) begin
                            state <= STATE_PRESSED;
                        end else begin
                            state <= STATE_HIGH;
                        end
                    end
                end
                
                // If button is still pressed
                STATE_PRESSED: begin
                    out <= 1'b1;
                    state <= STATE_HIGH;
                end
                
                    
                // Default case: return to idle state
                default: state <= STATE_HIGH;
            endcase
        end
    end
    
    // Run counter if in wait state
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            clk_count <= 0;
        end else begin
            if (state == STATE_WAIT) begin
                clk_count <= clk_count + 1;
            end else begin
                clk_count <= 0;
            end
        end
    end
    
endmodule


================================================
FILE: 08-memory/solution-sequencer/mem_init.txt
================================================
0
0
0
0
1
1
1
1

================================================
FILE: 08-memory/solution-sequencer/memory.v
================================================
// Simple block RAM example
// 
// Inputs:
//      clk             - Input clock
//      w_en            - Write enable
//      r_en            - Read enable
//      w_addr[x:0]     - Write address
//      r_addr[x:0]     - Read address
//      w_data[x:0]     - Data to be written
// 
// Outputs:
//      r_data[x:0]     - Data to be read
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Inferred block RAM
module memory #(

    // Parameters
    parameter   MEM_WIDTH = 16,
    parameter   MEM_DEPTH = 256,
    parameter   INIT_FILE = ""
) (

    // Inputs
    input               clk,
    input               w_en,
    input               r_en,
    input       [ADDR_WIDTH - 1:0]   w_addr,
    input       [ADDR_WIDTH - 1:0]   r_addr,
    input       [MEM_WIDTH - 1:0]  w_data,
    
    // Outputs
    output  reg [MEM_WIDTH - 1:0]  r_data
);

    // Calculate the number of bits required for the address
    localparam  ADDR_WIDTH = $clog2(MEM_DEPTH);

    // Declare memory
    reg [MEM_WIDTH - 1:0]  mem [0:MEM_DEPTH - 1];
    
    // Interact with the memory block
    always @ (posedge clk) begin
        
        // Write to memory
        if (w_en) begin
            mem[w_addr] <= w_data;
        end
        
        // Read from memory
        if (r_en) begin
            r_data <= mem[r_addr];
        end
    end
    
    // Initialization (if available)
    initial if (INIT_FILE) begin
        $readmemh(INIT_FILE, mem);
    end
    
endmodule

================================================
FILE: 08-memory/solution-sequencer/sequencer-top.pcf
================================================
# Oscillator
set_io              clk             21

# LEDs
set_io              led[0]          99
set_io              led[1]          98
set_io              unused_led[0]   97
set_io              unused_led[1]   96
set_io              unused_led[2]   95

# PMOD I/O
set_io  -pullup yes rst_btn         78
set_io  -pullup yes set_btn         79
set_io  -pullup yes ptn_0_btn       80
set_io  -pullup yes ptn_1_btn       81

================================================
FILE: 08-memory/solution-sequencer/sequencer-top.v
================================================
// Top-level design for sequencer
// 
// Inputs:
//      clk         - 12 MHz clock
//      rst_btn     - pushbutton (RESET)
//      set_btn     - pushbutton (SET value at next memory address)
//      ptn_0_btn   - pushbutton (PATTERN[0] for sequence)
//      ptn_1_btn   - pushbutton (PATTERN[1] for sequence)
// 
// Outputs:
//      led[1:0]    - LEDs
// 
// Push RESET to set everything to 0. Hold PATTERN[0] and/or PATTERN[1] and 
// press SET to record value in memory. Continue doing this for up to 8 memory
// locations. Sequence will play on LEDs and loop forever.
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Top-level design for the sequencer
module sequencer_top #(

    // Parameters
    parameter   DEBOUNCE_COUNTS = 480000 - 1,   // Counts for debounce wait
    parameter   STEP_COUNTS = 6000000 - 1,      // Clock cycles between steps
    parameter   NUM_STEPS = 8                   // Number of steps

) (

    // Inputs
    input               clk,
    input               rst_btn,
    input               set_btn,
    input               ptn_0_btn,
    input               ptn_1_btn,
    
    // Outputs
    output  reg [1:0]   led,
    output      [2:0]   unused_led
);
    
    // Internal signals
    wire            rst;
    wire            set;
    wire            set_d;
    wire    [1:0]   ptn;
    wire            div_clk;
    wire    [1:0]   r_data;
    
    // Storage elements (initialize some values)
    reg             w_en = 0;
    reg             r_en = 1'b1;    // Always high!
    reg     [2:0]   w_addr = 0;
    reg     [2:0]   r_addr;
    reg     [1:0]   w_data;
    reg     [2:0]   step_counter;
    reg     [2:0]   mem_ptr = 0;
    
    // Turn off unused LEDs
    assign unused_led = 3'b000;
    
    // Invert active-low buttons
    assign rst = ~rst_btn;
    assign set = ~set_btn;
    assign ptn[0] = ~ptn_0_btn;
    assign ptn[1] = ~ptn_1_btn;
    
    // Clock divider
    clock_divider #(
        .COUNT_WIDTH(24), 
        .MAX_COUNT(STEP_COUNTS)
    ) div (
        .clk(clk),
        .rst(rst),
        .out(div_clk)
    );
    
    // Button debouncer for set buttons
    debouncer #(
        .COUNT_WIDTH(24),
        .MAX_CLK_COUNT(DEBOUNCE_COUNTS)
    ) set_debouncer (
        .clk(clk),
        .rst(rst),
        .in(set),
        .out(set_d)
    );
    
    // Memory unit
    memory #(   
        .MEM_WIDTH(2), 
        .MEM_DEPTH(NUM_STEPS), 
        .INIT_FILE("mem_init.txt")
    ) mem (
        .clk(clk),
        .w_en(w_en),
        .r_en(r_en),
        .w_addr(w_addr),
        .r_addr(r_addr),
        .w_data(w_data),
        .r_data(r_data)
    );
    
    // Read from memory each divided clock cycle
    always @ (posedge div_clk or posedge rst) begin
        if (rst == 1'b1) begin
            led <= 0;
            r_addr <= 0;
            step_counter <= 0;
        end else begin
            r_addr <= step_counter;
            step_counter <= step_counter + 1;
            led <= r_data;
        end
    end
    
    // Register write data as soon as debounced set signal goes high
    always @ (posedge set_d) begin
        w_data <= ptn;
    end
    
    // Handle writing pattern to memory
    always @ (posedge clk or posedge rst) begin
    
        // Reset memory address pointer and write enable signal
        if (rst == 1'b1) begin
            mem_ptr <= 0;
            w_en <= 1'b0;
            
        // Set write enable high and increment memory pointer
        end else if (set_d == 1'b1) begin
            w_addr <= mem_ptr;
            w_en <= 1'b1;
            mem_ptr <= mem_ptr + 1;
        
        // Reset write enable signal
        end else begin
            w_en <= 1'b0;
        end
    end
    
endmodule

================================================
FILE: 08-memory/solution-sequencer/sequencer-top_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Tue Nov 16 17:21:28 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\08-memory\solution-sequencer\sequencer-top_tb.vcd"
[dumpfile_mtime] "Tue Nov 16 17:20:28 2021"
[dumpfile_size] 25572
[savefile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\08-memory\solution-sequencer\sequencer-top_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] 143 193
*-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
[treeopen] memory_tb.
[treeopen] memory_tb.uut.
[sst_width] 211
[signals_width] 118
[sst_expanded] 1
[sst_vpaned_height] 154
@28
memory_tb.clk
@29
memory_tb.uut.div_clk
@28
memory_tb.led[1:0]
memory_tb.ptn_0_btn
memory_tb.ptn_1_btn
memory_tb.rst_btn
memory_tb.set_btn
memory_tb.uut.mem.r_addr[2:0]
memory_tb.uut.mem.r_data[1:0]
memory_tb.uut.mem.r_en
memory_tb.uut.mem.w_addr[2:0]
memory_tb.uut.mem.w_data[1:0]
memory_tb.uut.mem.w_en
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 08-memory/solution-sequencer/sequencer-top_tb.v
================================================
// Testbench for sequencer
//
// Make sure the sequencer can store and replay step values.
//
// Date: November 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Defines timescale for simulation: <time_unit> / <time_precision>
`timescale 1 ns / 10 ps

// Define our testbench
module memory_tb();

    // Internal signals
    wire    [1:0]  led;
    
    // Storage elements
    reg             clk = 0;
    reg             rst_btn = 1;
    reg             set_btn = 1;
    reg             ptn_0_btn = 1;
    reg             ptn_1_btn = 1;

    // Simulation time: 50000 * 1 ns = 50 us
    localparam DURATION = 50000;
    
    // Generate clock signal: 1 / ((2 * 41.67) * 1 ns) = 11,999,040.08 MHz
    always begin
        #41.67
        clk = ~clk;
    end
    
    // Instantiate the unit under test (UUT)
    sequencer_top #(
        .DEBOUNCE_COUNTS(2),
        .STEP_COUNTS(10),
        .NUM_STEPS(8)
    ) uut (
        .clk(clk),
        .rst_btn(rst_btn),
        .set_btn(set_btn),
        .ptn_0_btn(ptn_0_btn),
        .ptn_1_btn(ptn_1_btn),
        .led(led),
        .unused_led()
    );
    
    // Run test: write to sequencer and make sure it plays the sequence back
    initial begin
    
        // Toggle reset
        #10
        rst_btn = 0;
        #1
        rst_btn = 1;
        
        // View a few default steps
        #(50 * 41.67)
        
        // Write 'b11 to the sequencer
        #(10 * 41.67)
        ptn_0_btn = 0;
        ptn_1_btn = 0;
        set_btn = 0;
        #(10 * 41.67)
        ptn_0_btn = 1;
        ptn_1_btn = 1;
        set_btn = 1;
        
        // Write 'b11 to the sequencer
        #(10 * 41.67)
        ptn_0_btn = 0;
        ptn_1_btn = 0;
        set_btn = 0;
        #(10 * 41.67)
        ptn_0_btn = 1;
        ptn_1_btn = 1;
        set_btn = 1;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("sequencer-top_tb.vcd");
        $dumpvars(0, memory_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 09-pll-and-glitches/example-01-pll/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 09-pll-and-glitches/example-01-pll/pll_test.pcf
================================================
# Oscillator
set_io              ref_clk     21

# PMOD I/O
set_io              clk         87

================================================
FILE: 09-pll-and-glitches/example-01-pll/pll_test.v
================================================
// Simple block RAM example
// 
// Inputs:
//      ref_clk     - Input reference clock (12 MHz)
// 
// Outputs:
//      clk         - Output of PLL (120 MHz clock)
//
// Date: December 6, 2021
// Author: Shawn Hymel
// License: 0BSD

// Instantiate PLL and output clock signal to pin
module pll_test (

    // Inputs
    input               ref_clk,
    
    // Outputs
    output              clk
);

    // Instantiate PLL (120 MHz)
    SB_PLL40_CORE #(
        .FEEDBACK_PATH("SIMPLE"),   // Don't use fine delay adjust
        .PLLOUT_SELECT("GENCLK"),   // No phase shift on output
        .DIVR(4'b0000),             // Reference clock divider
        .DIVF(7'b1001111),          // Feedback clock divider
        .DIVQ(3'b011),              // VCO clock divider
        .FILTER_RANGE(3'b001)       // Filter range
    ) pll (
        .REFERENCECLK(ref_clk),     // Input clock
        .PLLOUTCORE(clk),           // Output clock
        .LOCK(),                    // Locked signal
        .RESETB(1'b1),              // Active low reset
        .BYPASS(1'b0)               // No bypass, use PLL signal as output
    );
    
endmodule

================================================
FILE: 09-pll-and-glitches/example-02-glitches/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 09-pll-and-glitches/example-02-glitches/empty.v
================================================


================================================
FILE: 09-pll-and-glitches/example-02-glitches/glitch-test_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Mon Dec 06 17:26:08 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\09-pll-and-glitches\example-02-glitches\glitch-test_tb.vcd"
[dumpfile_mtime] "Mon Dec 06 17:25:24 2021"
[dumpfile_size] 153010
[savefile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\09-pll-and-glitches\example-02-glitches\glitch-test_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] -1 -1
*-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
[sst_width] 211
[signals_width] 110
[sst_expanded] 1
[sst_vpaned_height] 154
@28
glitch_test_tb.rst
glitch_test_tb.clk
@c00023
glitch_test_tb.out[3:0]
@28
(0)glitch_test_tb.out[3:0]
(1)glitch_test_tb.out[3:0]
(2)glitch_test_tb.out[3:0]
(3)glitch_test_tb.out[3:0]
@1401201
-group_end
@22
glitch_test_tb.count[3:0]
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 09-pll-and-glitches/example-02-glitches/glitch-test_tb.v
================================================
// Simulation of glitches with a ripple-carry adder.
//
// Date: December 6, 2021
// Author: Shawn Hymel
// License: 0BSD

// Defines timescale for simulation: <time_unit> / <time_precision>
`timescale 1 ns / 1 ps

// Half adder (with gate delays)
module half_adder (

    // Inputs
    input a,
    input b,
    
    // Output
    output sum,
    output c_out
);

    // Create output logic
    assign #1 sum = a ^ b;
    assign #1 c_out = a & b;
    
endmodule

// Define our testbench
module glitch_test_tb();

    // Simulation time: 10000 * 1 ns = 10000 ns
    localparam DURATION = 10000;

    // Internal signals
    wire            c_0;
    wire            c_1;
    wire            c_2;
    wire    [3:0]   out;
    
    // Internal storage elements
    reg             clk = 0;
    reg             rst = 0;
    reg     [3:0]   count;
    
    // Generate clock signal: 1 / ((2 * 4.167) * 1 ns) = 119,990,400.77 Hz
    always begin
        #4.167
        clk = ~clk;
    end
    
    // Instantiate half adders
    half_adder ha_0 (.a(1'b1), .b(count[0]), .sum(out[0]), .c_out(c_0));
    half_adder ha_1 (.a(c_0), .b(count[1]), .sum(out[1]), .c_out(c_1));
    half_adder ha_2 (.a(c_1), .b(count[2]), .sum(out[2]), .c_out(c_2));
    half_adder ha_3 (.a(c_2), .b(count[3]), .sum(out[3]), .c_out());
    
    // Let the counter count
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count = 0;
        end else begin
            count <= out;
        end
    end
    
    // Pulse reset line high at the beginning
    initial begin
        #10
        rst = 1;
        #1
        rst = 0;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("glitch-test_tb.vcd");
        $dumpvars(0, glitch_test_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 09-pll-and-glitches/solution-gray-code-counter/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 09-pll-and-glitches/solution-gray-code-counter/empty.v
================================================
// This file is needed to make apio happy

================================================
FILE: 09-pll-and-glitches/solution-gray-code-counter/gray-code-counter_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Mon Dec 06 17:23:51 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\09-pll-and-glitches\solution-gray-code-counter\gray-code-counter_tb.vcd"
[dumpfile_mtime] "Mon Dec 06 17:23:21 2021"
[dumpfile_size] 65129
[savefile] "C:\Users\sgmustadio\Documents\GitHub\introduction-to-fpga\09-pll-and-glitches\solution-gray-code-counter\gray-code-counter_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] -1 -1
*-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
[sst_width] 211
[signals_width] 94
[sst_expanded] 1
[sst_vpaned_height] 154
@29
glitch_test_tb.rst
@28
glitch_test_tb.clk
@22
glitch_test_tb.out[3:0]
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 09-pll-and-glitches/solution-gray-code-counter/gray-code-counter_tb.v
================================================
// Simulation of a 4-bit gray code counter using a finite state machine.
//
// Date: December 6, 2021
// Author: Shawn Hymel
// License: 0BSD

// Defines timescale for simulation: <time_unit> / <time_precision>
`timescale 1 ns / 1 ps

// 4-bit gray code counter FSM
module gray_counter (

    // Inputs
    input               clk,
    input               rst,
    
    // Outputs
    output  reg [3:0]   count
);

    // State machine transitions (with simulated delays)
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            count <= 0;
        end else begin
            case (count)                            // Gray code state
                4'b0000:    #1 count <= 4'b0001;    // 0
                4'b0001:    #1 count <= 4'b0011;    // 1
                4'b0011:    #1 count <= 4'b0010;    // 2
                4'b0010:    #1 count <= 4'b0110;    // 3
                4'b0110:    #1 count <= 4'b0111;    // 4
                4'b0111:    #1 count <= 4'b0101;    // 5
                4'b0101:    #1 count <= 4'b0100;    // 6
                4'b0100:    #1 count <= 4'b1100;    // 7
                4'b1100:    #1 count <= 4'b1101;    // 8
                4'b1101:    #1 count <= 4'b1111;    // 9
                4'b1111:    #1 count <= 4'b1110;    // 10
                4'b1110:    #1 count <= 4'b1010;    // 11
                4'b1010:    #1 count <= 4'b1011;    // 12
                4'b1011:    #1 count <= 4'b1001;    // 13
                4'b1001:    #1 count <= 4'b1000;    // 14
                4'b1000:    #1 count <= 4'b0000;    // 15
                default:    #1 count <= 4'b0000;
            endcase
        end
    end
    
endmodule

// Define our testbench
module gray_counter_tb();

    // Simulation time: 10000 * 1 ns = 10000 ns
    localparam DURATION = 10000;

    // Internal signals
    wire    [3:0]   out;
    
    // Internal storage elements
    reg             clk = 0;
    reg             rst = 0;
    
    // Generate clock signal: 1 / ((2 * 4.167) * 1 ns) = 119,990,400.77 Hz
    always begin
        #4.167
        clk = ~clk;
    end
    
    // Instantiate gray code counter
    gray_counter gray (.clk(clk), .rst(rst), .count(out));
    
    // Pulse reset line high at the beginning
    initial begin
        #10
        rst = 1;
        #1
        rst = 0;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("gray-code-counter_tb.vcd");
        $dumpvars(0, gray_counter_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule


================================================
FILE: 10-metastability/example-01-metastability-test/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 10-metastability/example-01-metastability-test/metastability-test.pcf
================================================
# PMOD I/O
set_io              clk_in      87
set_io              sig_in      88
set_io              clk_out     90
set_io              sig_out     91

================================================
FILE: 10-metastability/example-01-metastability-test/metastability-test.v
================================================
// Input 2 MHz clock and 1 MHz sqaure wave signal. Phase shift the
// 1 MHz signal to force metastability.
//
// Connections
//  Signal  | IceStick      | AnalogDiscovery 2 | Oscilloscope  
// ---------|---------------|-------------------|---------------
//  VCC     | 3.3V          | vary 0.7 to 3.3V  |
//  GND     | GND           | GND               | ground clips
//  clk_in  | 87            | W1                |
//  sig_in  | 88            | W2                | ch. 1
//  clk_out | 90            |                   | ch. 2
//  sig_out | 91            |                   | ch. 3    
//
// Date: December 18, 2021
// Author: Shawn Hymel
// License: 0BSD

// Sample input waveform and register it
module metastability_test (

    // Inputs
    input               clk_in,
    input               sig_in,    
    
    // Outputs
    output              clk_out,
    output  reg         sig_out = 0
);
    
    // Internal storage elements
    reg     div_sig;
    reg     pipe_0;
    
    // Pass input clock to output pin
    assign clk_out = clk_in;

    // Register input signal
    always @ (posedge clk_in) begin
        sig_out <= sig_in;
        //pipe_0 <= sig_in;
        //sig_out <= pipe_0;
    end
    
endmodule

================================================
FILE: 10-metastability/example-02-better-clock-divider/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 10-metastability/example-02-better-clock-divider/clock-divider.v
================================================
// A better way to create a clock divider that does not use flip-flip outputs
// as clock inputs to other flip-flops. Us the tick pulse in combination with
// other logic to determine when to perform some action.
//
// Based on work by: https://github.com/Paebbels
//
// Date: December 16, 2021
// Author: Shawn Hymel
// License: 0BSD

// Divide the clock by outputting a pulse at the desired time
module clock_divider #(

    // Parameters
    parameter   MODULO  = 6000000
) (
    
    // Inputs
    input   clk,
    input   rst,
    
    // Outputs
    output  tick
);

    // Calculate number of bits needed for the counter
    localparam WIDTH = (MODULO == 1) ? 1 : $clog2(MODULO);

    // Internal storage elements
    reg [WIDTH-1:0] count = 0;

    // Tick is high for one clock cycle at max count
    assign tick = (count == MODULO - 1) ? 1'b1 : 1'b0;
    
    // Count up, reset on tick pulse
    always @ (posedge clk or posedge rst) begin
        if (rst | tick == 1'b1) begin
            count <= 0;
        end else begin
            count <= count + 1;
        end
    end
    
endmodule

================================================
FILE: 10-metastability/example-02-better-clock-divider/clock-divider_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Thu Dec 16 22:08:09 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\apio\better-clock-divider\clock-divider_tb.vcd"
[dumpfile_mtime] "Thu Dec 16 22:08:03 2021"
[dumpfile_size] 5375201
[savefile] "C:\Users\sgmustadio\Documents\apio\better-clock-divider\clock-divider_tb.gtkw"
[timestart] 0
[size] 1000 600
[pos] -1 -1
*-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
[treeopen] clock_divider_tb.
[sst_width] 211
[signals_width] 110
[sst_expanded] 1
[sst_vpaned_height] 154
@28
clock_divider_tb.clk
clock_divider_tb.rst
clock_divider_tb.tick
@25
clock_divider_tb.uut.count[6:0]
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 10-metastability/example-02-better-clock-divider/clock-divider_tb.v
================================================
// Test clock divider operation. The divider output (tick) should
// pulse once at each divided cycle.
//
// Date: December 16, 2021
// Author: Shawn Hymel
// License: 0BSD

// Define timescale
`timescale 1 us / 10 ps

// Define our testbench
module clock_divider_tb();

    // Settings
    localparam  MODULO = 120;   // 12 MHz / 120 = 100 kHz ticks
    
    // Internal signals
    wire    tick;
    
    // Internal storage elements
    reg     clk = 0;
    reg     rst = 0;
    
    // Simulation time: 10000 * 1 us = 10 ms
    localparam DURATION = 10000;
    
    // Generate clock signal
    always begin
        #0.04167
        clk = ~clk;
    end
    
    // Instantiate clock divider
    clock_divider #(
        .MODULO(MODULO)
    ) uut (
        .clk(clk),
        .rst(rst),
        .tick(tick)
    );
    
    // Test control: run for some time, toggle reset, let run some more
    initial begin
        #10
        rst = 1;
        #1
        rst = 0;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("clock-divider_tb.vcd");
        $dumpvars(0, clock_divider_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 10-metastability/example-02-better-clock-divider/slow-blink.pcf
================================================
# Oscillator
set_io              clk         21

# LEDs
set_io              led         99

# PMOD I/O
set_io  -pullup yes rst_btn     78

================================================
FILE: 10-metastability/example-02-better-clock-divider/slow-blink.v
================================================
// Slow blink example using the better clock divider.
//
// Based on work by: https://github.com/Paebbels
//
// Date: December 16, 2021
// Author: Shawn Hymel
// License: 0BSD

// Slow blink top level design
module slow_blink (

    // Inputs
    input           clk,
    input           rst_btn,    
    
    // Outputs
    output  reg     led
);

    // Settings
    localparam MODULO = 6000000;    // Toggle LED every 0.5 s with 12 MHz clk
    
    // Internal signals
    wire    rst;
    wire    tick;
    
    // Invert reset button
    assign rst = ~rst_btn;

    // Instantiate clock divider
    clock_divider #(
        .MODULO(MODULO)
    ) uut (
        .clk(clk),
        .rst(rst),
        .tick(tick)
    );
    
    // Example using clock divider to blink LED
    always @ (posedge clk or posedge rst) begin
        if (rst == 1'b1) begin
            led <= 1'b0;
        end else if (tick == 1'b1) begin
            led <= ~led;
        end
    end
    
endmodule

================================================
FILE: 10-metastability/example-03-better-debouncer/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 10-metastability/example-03-better-debouncer/debouncer.v
================================================
// Debounce signal logic without the use of a clock divider.
//
// Based on: https://forum.digikey.com/t/debounce-logic-circuit-vhdl/12573
//
// Date: December 16, 2021
// Author: Shawn Hymel
// License: 0BSD

// Debouncing logic
module debouncer #(
    
    // Parameters
    parameter MAX_CLK_COUNT = 120000    // 10 ms with 12 MHz clock
) (

    // Inputs
    input           clk,
    input           rst,
    input           sig,
    
    // Outputs
    output  reg     out
);

    // Calculate number of bits needed for the counter
    localparam WIDTH = $clog2(MAX_CLK_COUNT + 1);
    
    // Internal signals
    wire            sig_edge;

    // Internal storage elements
    reg             ff_1;
    reg             ff_2;
    reg [WIDTH-1:0] count = 0;
    
    // Counter starts when outputs of the two flip-flops are different
    assign sig_edge = ff_1 ^ ff_2;
    
    // Logic to sample signal after a period of time
    always @ (posedge clk or posedge rst) begin
    
        // Reset flip-flops
        if (rst == 1'b1) begin
            ff_1 <= 0;
            ff_2 <= 0;
            out <= 0;
        
        // If rising or falling edge on signal, run counter and sample again
        end else begin
            ff_1 <= sig;
            ff_2 <= ff_1;
            if (sig_edge == 1'b1) begin
                count <= 0;
            end else if (count < MAX_CLK_COUNT) begin
                count <= count + 1;
            end else begin
                out <= ff_2;
            end
        end
    end
    
endmodule

================================================
FILE: 10-metastability/example-03-better-debouncer/debouncer_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Thu Dec 16 22:04:13 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\apio\better-debounce\debouncer_tb.vcd"
[dumpfile_mtime] "Thu Dec 16 17:47:23 2021"
[dumpfile_size] 4164257
[savefile] "C:\Users\sgmustadio\Documents\apio\better-debounce\debouncer_tb.gtkw"
[timestart] 0
[size] 1108 600
[pos] -135 173
*-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
[treeopen] debouncer_tb.
[sst_width] 211
[signals_width] 110
[sst_expanded] 1
[sst_vpaned_height] 154
@28
debouncer_tb.clk
debouncer_tb.rst
debouncer_tb.inc_btn
@22
debouncer_tb.uut.count[8:0]
@28
debouncer_tb.out
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 10-metastability/example-03-better-debouncer/debouncer_tb.v
================================================
// Testbench for button debounce design
//
// Date: November 16, 2021
// Author: Shawn Hymel
// License: 0BSD

// Define timescale
`timescale 1 us / 10 ps

// Define our testbench
module debouncer_tb();

    // Internal signals
    wire            out;
    
    // Storage elements (buttons are active low!)
    reg             clk = 0;
    reg             rst = 0;
    reg             inc_btn = 1;
    integer         i;              // Used in for loop
    integer         j;              // Used in for loop
    integer         prev_inc;       // Previous increment button state
    integer         nbounces;       // Holds random number
    integer         rdelay;         // Holds random number
    
    // Simulation time: 10000 * 1 us = 10 ms
    localparam DURATION = 10000;
    
    // Generate clock signal (about 12 MHz)
    always begin
        #0.04167
        clk = ~clk;
    end
    
    // Instantiate debounce/counter module (use about 40 us wait time)
    debouncer #(
        .MAX_CLK_COUNT(480)
    ) uut (
        .clk(clk),
        .rst(rst),
        .sig(inc_btn),
        .out(out)
    );
    
    // Test control: pulse reset and create some (bouncing) button presses
    initial begin
    
        // Pulse reset
        #10
        rst = 1;
        #1
        rst = 0;
        
        // We can use for loops in simulation!
        for (i = 0; i < 32; i = i + 1) begin
        
            // Wait some time before pressing button
            #1000
            
            // Simulate a bouncy/noisy button press
            // $urandom generates a 32-bit unsigned (pseudo) random number
            // "% 10" is "modulo 10"
            prev_inc = inc_btn;
            nbounces = $urandom % 20;
            for (j = 0; j < nbounces; j = j + 1) begin
                #($urandom % 10)
                inc_btn = ~inc_btn;
            end
            
            // Make sure button ends up in the opposite state
            inc_btn = ~prev_inc;
        end
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file 
        $dumpfile("debouncer_tb.vcd");
        $dumpvars(0, debouncer_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end
    
endmodule

================================================
FILE: 10-metastability/solution-async-fifo/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 10-metastability/solution-async-fifo/async-fifo.v
================================================
// Implementation of Clifford Cummings's asynchronous FIFO design from the paper
// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf
//
// Top-level asynchronous FIFO module to be used in designs.
//
// Notes:
//  - w_* means something is in the "write clock domain"
//  - r_* means something is in the "read clock domain"
//  - Single memory element is DATA_SIZE bits wide
//  - Memory is 2^ADDR_SIZE elements deep
//
// Date: December 11, 2021
// Author: Shawn Hymel
// License: 0BSD

// Asynchronous FIFO module
module async_fifo #(

    // Parameters
    parameter   DATA_SIZE = 8,              // Number of data bits
    parameter   ADDR_SIZE = 4               // Number of bits for address
) (

    // Inputs
    input       [DATA_SIZE-1:0] w_data,     // Data to be written to FIFO
    input                       w_en,       // Write data and increment addr.
    input                       w_clk,      // Write domain clock
    input                       w_rst,      // Write domain reset
    input                       r_en,       // Read data and increment addr.
    input                       r_clk,      // Read domain clock
    input                       r_rst,      // Read domain reset
    
    // Outputs
    output                      w_full,     // Flag: 1 if FIFO is full
    output  reg [DATA_SIZE-1:0] r_data,     // Data to be read from FIFO
    output                      r_empty     // Flag: 1 if FIFO is empty
);

    // Constants
    localparam  FIFO_DEPTH  = (1 << ADDR_SIZE);
    
    // Internal signals
    wire    [ADDR_SIZE-1:0] w_addr;
    wire    [ADDR_SIZE:0]   w_gray;
    wire    [ADDR_SIZE-1:0] r_addr;
    wire    [ADDR_SIZE:0]   r_gray;
    
    // Internal storage elements
    reg     [ADDR_SIZE:0]   w_syn_r_gray;
    reg     [ADDR_SIZE:0]   w_syn_r_gray_pipe;
    reg     [ADDR_SIZE:0]   r_syn_w_gray;
    reg     [ADDR_SIZE:0]   r_syn_w_gray_pipe;
    
    // Declare memory
    reg     [DATA_SIZE-1:0] mem [0:FIFO_DEPTH-1];
    
    //--------------------------------------------------------------------------
    // Dual-port memory (should be inferred as block RAM)
    
    // Write data logic for dual-port memory (separate write clock)
    // Do not write if FIFO is full!
    always @ (posedge w_clk) begin
        if (w_en & ~w_full) begin
            mem[w_addr] <= w_data;
        end
    end
    
    // Read data logic for dual-port memory (separate read clock)
    // Do not read if FIFO is empty!
    always @ (posedge r_clk) begin
        if (r_en & ~r_empty) begin
            r_data <= mem[r_addr];
        end
    end
    
    //--------------------------------------------------------------------------
    // Synchronizer logic
    
    // Pass read-domain Gray code pointer to write domain
    always @ (posedge w_clk or posedge w_rst) begin
        if (w_rst == 1'b1) begin
            w_syn_r_gray_pipe <= 0;
            w_syn_r_gray <= 0;
        end else begin
            w_syn_r_gray_pipe <= r_gray;
            w_syn_r_gray <= w_syn_r_gray_pipe;
        end
    end
    
    // Pass write-domain Gray code pointer to read domain
    always @ (posedge r_clk or posedge r_rst) begin
        if (r_rst == 1'b1) begin
            r_syn_w_gray_pipe <= 0;
            r_syn_w_gray <= 0;
        end else begin
            r_syn_w_gray_pipe <= w_gray;
            r_syn_w_gray <= r_syn_w_gray_pipe;
        end
    end
    
    //--------------------------------------------------------------------------
    // Instantiate incrementer and full/empty checker modules
    
    // Write address increment and full check module
    w_ptr_full #(.ADDR_SIZE(ADDR_SIZE)) w_ptr_full (
        .w_syn_r_gray(w_syn_r_gray),
        .w_inc(w_en),
        .w_clk(w_clk),
        .w_rst(w_rst),
        .w_addr(w_addr),
        .w_gray(w_gray),
        .w_full(w_full)
    );
    
    // Read address increment and empty check module
    r_ptr_empty #(.ADDR_SIZE(ADDR_SIZE)) r_ptr_empty (
        .r_syn_w_gray(r_syn_w_gray),
        .r_inc(r_en),
        .r_clk(r_clk),
        .r_rst(r_rst),
        .r_addr(r_addr),
        .r_gray(r_gray),
        .r_empty(r_empty)
    );
    
endmodule

================================================
FILE: 10-metastability/solution-async-fifo/async-fifo_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Sat Dec 11 20:21:30 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\apio\fifo_test_03\async-fifo_tb.vcd"
[dumpfile_mtime] "Sat Dec 11 20:20:07 2021"
[dumpfile_size] 5748705
[savefile] "C:\Users\sgmustadio\Documents\apio\fifo_test_03\async-fifo_tb.gtkw"
[timestart] 0
[size] 1707 897
[pos] -1 -1
*-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
[sst_width] 211
[signals_width] 118
[sst_expanded] 1
[sst_vpaned_height] 259
@28
async_fifo_tb.w_clk
async_fifo_tb.w_rst
@22
async_fifo_tb.w_data[7:0]
@28
async_fifo_tb.w_en
@29
async_fifo_tb.w_full
@28
async_fifo_tb.r_clk
async_fifo_tb.r_rst
@22
async_fifo_tb.r_data[7:0]
@28
async_fifo_tb.r_en
async_fifo_tb.r_empty
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 10-metastability/solution-async-fifo/async-fifo_tb.v
================================================
// Simulation of Clifford Cummings's asynchronous FIFO design from the paper
// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf
//
// Testbench to verify RTL design of the asynchronous FIFO design. Note that
// this does not check for things like metastability and glitches! You would
// likely need to use a gate-level simulation tool for that.
//
// Notes:
//  - w_* means something is in the "write clock domain"
//  - r_* means something is in the "read clock domain"
//  - Single memory element is DATA_SIZE bits wide
//  - Memory is 2^ADDR_SIZE elements deep
//
// Date: December 11, 2021
// Author: Shawn Hymel
// License: 0BSD

// Define timescale
`timescale 1 us / 10 ps

// Define our testbench
module async_fifo_tb();

    // Settings
    localparam  DATA_SIZE = 8;
    localparam  ADDR_SIZE = 4;
    
    // Internal signals
    wire    [DATA_SIZE-1:0]     r_data;
    wire                        r_empty;
    wire                        r_full;
    
    // Internal storage elements
    reg                         r_en = 0;
    reg                         r_clk = 0;
    reg                         r_rst = 0;
    reg     [DATA_SIZE-1:0]     w_data;
    reg                         w_en = 0;
    reg                         w_clk = 0;
    reg                         w_rst = 0;
    
    // Variables
    integer                     i;
    
    // Simulation time: 10000 * 1 us = 10 ms
    localparam DURATION = 10000;
    
    // Generate read clock signal (about 12 MHz)
    always begin
        #0.04167
        r_clk = ~r_clk;
    end
    
    // Generate write clock signal (5 MHz)
    always begin
        #0.1
        w_clk = ~w_clk;
    end
    
    // Instantiate FIFO
    async_fifo #(
        .DATA_SIZE(DATA_SIZE),
        .ADDR_SIZE(ADDR_SIZE)
    ) uut (
        .w_data(w_data),
        .w_en(w_en),
        .w_clk(w_clk),
        .w_rst(w_rst),
        .r_en(r_en),
        .r_clk(r_clk),
        .r_rst(r_rst),
        .w_full(w_full),
        .r_data(r_data),
        .r_empty(r_empty)
    );
    
    // Test control: write and read data to/from FIFO
    initial begin
    
        // Pulse resets high to initialize memory and counters
        #0.1
        w_rst = 1;
        r_rst = 1;
        #0.01
        w_rst = 0;
        r_rst = 0;
        
        // Write some data to the FIFO
        for (i = 0; i < 4; i = i + 1) begin
            #0.2
            w_data = i;
            w_en = 1'b1;
        end
        #0.2
        w_en = 1'b0;
        
        // Try to read more than what's in the FIFO
        for (i = 0; i < 6; i = i + 1) begin
            #0.08334
            r_en = 1'b1;
        end
        #0.08334
        r_en = 1'b0;
        
        // Fill up FIFO (and then some)
        for (i = 0; i < 18; i = i + 1) begin
            #0.2
            w_en = 1'b1;
            w_data = i;
        end
        #0.2
        w_en = 1'b0;
        
        // Read everything in the FIFO (and then some)
        for (i = 0; i < 18; i = i + 1) begin
            #0.08334
            r_en = 1'b1;
        end
        #0.08334
        r_en = 1'b0;
            
    end
    
        // Run simulation
    initial begin
    
        // Create simulation output file 
        $dumpfile("async-fifo_tb.vcd");
        $dumpvars(0, async_fifo_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end

endmodule

================================================
FILE: 10-metastability/solution-async-fifo/dummy.pcf
================================================
# Dummy PCF signals to test synthesis
set_io  r_en        112
set_io  r_clk       113
set_io  w_data[0]   114
set_io  w_data[1]   115
set_io  w_data[2]   116
set_io  w_data[3]   117
set_io  w_data[4]   118
set_io  w_data[5]   119
set_io  w_data[6]   44
set_io  w_data[7]   45
set_io  w_en        47
set_io  w_clk       48
set_io  w_rst       56
set_io  r_rst       60
set_io  r_data[0]   61
set_io  r_data[1]   62
set_io  r_data[2]   78
set_io  r_data[3]   79
set_io  r_data[4]   80
set_io  r_data[5]   81
set_io  r_data[6]   87
set_io  r_data[7]   88
set_io  r_empty     99
set_io  w_full      98

================================================
FILE: 10-metastability/solution-async-fifo/r-ptr-empty.v
================================================
// Implementation of Clifford Cummings's asynchronous FIFO design from the paper
// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf
//
// Module to incrememnt the read address and determine if the FIFO is empty.
//
// Notes:
//  - w_* means something is in the "write clock domain"
//  - r_* means something is in the "read clock domain"
//
// Date: December 11, 2021
// Author: Shawn Hymel
// License: 0BSD

// Increment read address and check if FIFO is empty
module r_ptr_empty #(

    // Parameters
    parameter   ADDR_SIZE = 4                   // Number of bits for address
) (
    
    // Inputs
    input       [ADDR_SIZE:0]   r_syn_w_gray,   // Synced write Gray pointer
    input                       r_inc,          // 1 to increment address
    input                       r_clk,          // Read domain clock
    input                       r_rst,          // Read domain reset

    // Outputs
    output      [ADDR_SIZE-1:0] r_addr,         // Mem address to read from
    output  reg [ADDR_SIZE:0]   r_gray,         // Gray address with +1 MSb
    output  reg                 r_empty         // 1 if FIFO is empty
);
    
    // Internal signals
    wire    [ADDR_SIZE:0]   r_gray_next;    // Gray code version of address
    wire    [ADDR_SIZE:0]   r_bin_next;     // Binary version of address
    wire                    r_empty_val;    // FIFO is empty
    
    // Internal storage elements
    reg     [ADDR_SIZE:0]   r_bin;          // Registered binary address
    
    // Drop extra most significant bit (MSb) for addressing into memory
    assign r_addr = r_bin[ADDR_SIZE-1:0];
    
    // Be ready with next (incremented) address (if inc set and not empty)
    assign r_bin_next = r_bin + (r_inc & ~r_empty);
    
    // Convert next binary address to Gray code value
    assign r_gray_next = (r_bin_next >> 1) ^ r_bin_next;
    
    // If the synced write Gray code is equal to the current read Gray code,
    // then the pointers have caught up to each other and the FIFO is empty
    assign r_empty_val = (r_gray_next == r_syn_w_gray);
    
    // Register the binary and Gray code pointers in the read clock domain
    always @ (posedge r_clk or posedge r_rst) begin
        if (r_rst == 1'b1) begin
            r_bin <= 0;
            r_gray <= 0;
        end else begin
            r_bin <= r_bin_next;
            r_gray <= r_gray_next;
        end
    end
    
    // Register the empty flag
    always @ (posedge r_clk or posedge r_rst) begin
        if (r_rst == 1'b1) begin
            r_empty <= 1'b1;
        end else begin
            r_empty <= r_empty_val;
        end
    end
    
endmodule

================================================
FILE: 10-metastability/solution-async-fifo/w-ptr-full.v
================================================
// Implementation of Clifford Cummings's asynchronous FIFO design from the paper
// at http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf
//
// Module to incrememnt the write address and determine if the FIFO is full.
//
// Notes:
//  - w_* means something is in the "write clock domain"
//  - r_* means something is in the "read clock domain"
//
// Date: December 11, 2021
// Author: Shawn Hymel
// License: 0BSD

// Increment write address and check if FIFO is full
module w_ptr_full #(

    // Parameters
    parameter   ADDR_SIZE = 4                   // Number of bits for address
) (
    
    // Inputs
    input       [ADDR_SIZE:0]   w_syn_r_gray,   // Synced read Gray pointer
    input                       w_inc,          // 1 to increment address
    input                       w_clk,          // Write domain clock
    input                       w_rst,          // Write domain reset
    
    // Outputs 
    output      [ADDR_SIZE-1:0] w_addr,         // Mem address to write to
    output  reg [ADDR_SIZE:0]   w_gray,         // Gray adress with +1 MSb
    output  reg                 w_full          // 1 if FIFO is full   
);

    // Internal signals
    wire    [ADDR_SIZE:0]   w_gray_next;    // Gray code version of address
    wire    [ADDR_SIZE:0]   w_bin_next;     // Binary version of address
    wire                    w_full_val;     // FIFO is full
    
    // Internal storage elements
    reg     [ADDR_SIZE:0]   w_bin;          // Registered binary address
    
    // Drop extra most significant bit (MSb) for addressing into memory
    assign w_addr = w_bin[ADDR_SIZE-1:0];
    
    // Be ready with next (incremented) address (if inc set and not full)
    assign w_bin_next = w_bin + (w_inc & ~w_full);
    
    // Convert next binary address to Gray code value
    assign w_gray_next = (w_bin_next >> 1) ^ w_bin_next;
    
    // Compare write Gray code to synced read Gray code to see if FIFO is full
    // If:  extra MSb of read and write Gray codes are not equal AND
    //      2nd MSb of read and write Gray codes are not equal AND
    //      the rest of the bits are equal
    // Then: address pointers are same with write pointer ahead by 2^ADDR_SIZE
    // elements (i.e. wrapped around), so FIFO is full.
    assign w_full_val = ((w_gray_next[ADDR_SIZE] != w_syn_r_gray[ADDR_SIZE]) &&
                   (w_gray_next[ADDR_SIZE-1] != w_syn_r_gray[ADDR_SIZE-1]) &&
                   (w_gray_next[ADDR_SIZE-2:0] == w_syn_r_gray[ADDR_SIZE-2:0]));
    
    // Register the binary and Gray code pointers in the write clock domain
    always @ (posedge w_clk or posedge w_rst) begin
        if (w_rst == 1'b1) begin
            w_bin <= 0;
            w_gray <= 0;
        end else begin
            w_bin <= w_bin_next;
            w_gray <= w_gray_next;
        end
    end
    
    // Register the full flag
    always @ (posedge w_clk or posedge w_rst) begin
        if (w_rst == 1'b1) begin
            w_full <= 1'b0;
        end else begin
            w_full <= w_full_val;
        end
    end
    
endmodule        

================================================
FILE: 11-risc-v-softcore-cpu/example-01-blinky/Makefile
================================================
include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc


================================================
FILE: 11-risc-v-softcore-cpu/example-01-blinky/main.c
================================================
// Blink 2 LEDs and print info to the serial terminal.
//
// Date: December 19, 2021
// Author: Shawn Hymel
// License: 0BSD

#include <femtorv32.h>

int main() {
        while(1) {
                printf("Hello, world!\r\n");
                printf("Freq: %d MHz\r\n", FEMTORV32_FREQ);
                *(volatile uint32_t*)(0x400004) = 3;
                delay(500);
                *(volatile uint32_t*)(0x400004) = 0;
		delay(500);
	}
	return 0;
}



================================================
FILE: 11-risc-v-softcore-cpu/solution-buttons/Makefile
================================================
include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc


================================================
FILE: 11-risc-v-softcore-cpu/solution-buttons/main.c
================================================
// Count on LEDs as long as button is pressed.
//
// Date: December 19, 2021
// Author: Shawn Hymel
// License: 0BSD

#include <femtorv32.h>

int main() {
    int count = 0;
    while (1) {
        if ((IO_IN(IO_BUTTONS) & 1) == 0) {
            count = (count + 1) % 16;
            IO_OUT(IO_LEDS, count);
            delay(250);
        }
    }
    return 0;
}



================================================
FILE: 12-risc-v-custom-peripheral/example-01-pwm/C/pwm_test/Makefile
================================================
include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc


================================================
FILE: 12-risc-v-custom-peripheral/example-01-pwm/C/pwm_test/main.c
================================================
// Slowly increase the brightness of the PWM-controlled LED over and over.
//
// Date: December 19, 2021
// Author: Shawn Hymel
// License: 0BSD

#include <femtorv32.h>

int main() {
	while (1) {
		for (int i = 0; i < 4096; i++) {
			*(volatile uint32_t*)(0x404000) = i;
                        delay(1);
		}
	}
	return 0;
}


================================================
FILE: 12-risc-v-custom-peripheral/example-01-pwm/RTL/apio.ini
================================================
[env]
board = icestick



================================================
FILE: 12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm.pcf
================================================
# Oscillator
set_io              clk         21

# LEDs
set_io              led[0]      99
set_io              led[1]      98
set_io              led[2]      97
set_io              led[3]      96

================================================
FILE: 12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm.v
================================================
// PWM driver for FemtoRV: https://github.com/BrunoLevy/learn-fpga
//
// Controls brightness of first LED. Set duty cycle with wdata (0..4095).
//
// Date: December 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Control brightness of one of the LEDs
module pwm #(

    // Parameters
    parameter       WIDTH = 12  // Default PWM values 0..4095

) (

    // Inputs
    input           clk,
    input           wstrb,  // Write strobe
    input           sel,    // Select (read/write ignored if low)
    input   [31:0]  wdata,  // Data to be written (to driver)
    
    // Outputs
    output  [3:0]   led
);

    // Internal storage elements
    reg             pwm_led = 1'b0;
    reg [WIDTH-1:0] pwm_count = 0;
    reg [WIDTH-1:0] count = 0;
    
    // Only control the first LED
    assign led[0] = pwm_led;
    
    // Update PWM duty cycle 
    always @ (posedge clk) begin
    
        // If sel is high, record duty cycle count on strobe
        if (sel && wstrb) begin
            pwm_count <= wdata[WIDTH-1:0];
            count <= 0;
            
        // Otherwise, continuously count and flash LED as necessary
        end else begin
            count <= count + 1;
            if (count < pwm_count) begin
                pwm_led <= 1'b1;
            end else begin
                pwm_led <= 1'b0;
            end
        end
    end
    
endmodule

================================================
FILE: 12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm_tb.gtkw
================================================
[*]
[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI
[*] Wed Dec 15 20:37:05 2021
[*]
[dumpfile] "C:\Users\sgmustadio\Documents\apio\pwm_01\pwm_tb.vcd"
[dumpfile_mtime] "Wed Dec 15 20:32:44 2021"
[dumpfile_size] 5154
[savefile] "C:\Users\sgmustadio\Documents\apio\pwm_01\pwm_tb.gtkw"
[timestart] 3820000
[size] 1000 600
[pos] 68 104
*-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
[treeopen] pwm_tb.
[sst_width] 211
[signals_width] 142
[sst_expanded] 1
[sst_vpaned_height] 154
@28
pwm_tb.clk
pwm_tb.sel
pwm_tb.wstrb
@22
pwm_tb.wdata[31:0]
pwm_tb.uut.pwm_count[3:0]
@23
pwm_tb.uut.count[3:0]
@800022
pwm_tb.led[3:0]
@28
(0)pwm_tb.led[3:0]
(1)pwm_tb.led[3:0]
(2)pwm_tb.led[3:0]
(3)pwm_tb.led[3:0]
@1001200
-group_end
[pattern_trace] 1
[pattern_trace] 0


================================================
FILE: 12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm_tb.v
================================================
// Simulation of PWM driver.
//
// Date: December 15, 2021
// Author: Shawn Hymel
// License: 0BSD

// Define timescale
`timescale 1 ns / 10 ps

// Testbench
module pwm_tb();

    // Simulation time: 10000 * 1 us = 10 ms
    localparam DURATION = 10000;
    
    // Internal signals
    wire    [3:0]   led;    

    // Internal storage elements
    reg             clk = 0;
    reg             wstrb = 0;
    reg             sel = 0;
    reg     [31:0]  wdata = 0;

    // Generate read clock signal (about 12 MHz)
    always begin
        #41.667
        clk = ~clk;
    end
    
    // Instantiate PWM driver
    pwm #(
        .WIDTH(4)
    ) uut (
        .clk(clk),
        .wstrb(wstrb),
        .sel(sel),
        .wdata(wdata),
        .led(led)
    );
    
    // Test control: send values to PWM driver and watch LED
    initial begin
        
        // Wait some time to see how LED initializes
        #1500
        
        // Write 0% duty cycle
        wstrb = 1;
        sel = 1;
        wdata = 0;
        #100
        wstrb = 0;
        sel = 0;
        
        // Write ~33% duty cycle
        #1500
        wstrb = 1;
        sel = 1;
        wdata = 5;
        #100
        wstrb = 0;
        sel = 0;
        
        // Write 100% duty cycle
        #1500
        wstrb = 1;
        sel = 1;
        wdata = 15;
        #100
        wstrb = 0;
        sel = 0;
    end
    
    // Run simulation (output to .vcd file)
    initial begin
    
        // Create simulation output file
        $dumpfile("pwm_tb.vcd");
        $dumpvars(0, pwm_tb);
        
        // Wait for given amount of time for simulation to complete
        #(DURATION)
        
        // Notify and end simulation
        $display("Finished!");
        $finish;
    end

endmodule

================================================
FILE: README.md
================================================
# Introduction to FPGA

Welcome 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.

[![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)

This 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.

The 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)

Written guides that explain the solutions can be found here:

 1. [What is an FPGA?](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-1-what-is-an-fpga/3ee5f6c8fa594161a655a9f960060893)
 2. [Toolchain Setup](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-2-toolchain-setup/563a9518cd11466fb6a75cf3cb684d6d)
 3. [Getting Started with Verilog](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-3-getting-started-with-verilog/9d9dbff29a4b45728521b2664bbd1df4)
 4. [Clocks and Procedural Assignments](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-4-clocks-and-procedural-assignments/356e12284daf48b5bd9b80af8a6ac5b8)
 5. [Finite State Machine (FSM)](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-5-finite-state-machine-fsm/4d83e63da76044af9acc8aa7dcf07c22)
 6. [Verilog Modules and Parameters](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-6-verilog-modules-and-parameters/c7d4d01274be43278d8bc531e6b7acb7)
 7. [Verilog Testbenches and Simulation](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-7-verilog-testbenches-and-simulation/1b741d1b8b864afeacbe28075b1427cd)
 8. [Memory and Block RAM](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-8-memory-and-block-ram/df7bcadef0de430ab89d0d9c21e3a14c)
 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)
 10. [Metastability and FIFO](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-10-metastability-and-fifo/74884ed134474e008a1e444ea9dacb0f)
 11. [RISC-V Softcore Processor](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-11-risc-v-softcore-processor/f0511ddb538f444cae08f7bc43a74dcc)
 12. [RISC-V Peripheral](https://www.digikey.com/en/maker/projects/introduction-to-fpga-part-12-risc-v-custom-peripheral/148dba8ecafe49a1ac7e13641088af4c)

## Directory Structure

Examples 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*.

In 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-\**.

The only exception to this is the *images* directory, which is where I keep images for this repository.

## License

All 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).

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.

THE 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.
Download .txt
gitextract_qazi7qst/

├── .gitignore
├── 02-install-apio/
│   └── solution-turn-off-led/
│       ├── apio.ini
│       ├── info
│       ├── leds.pcf
│       ├── leds.v
│       ├── leds_tb.gtkw
│       └── leds_tb.v
├── 03-verilog-gate-logic/
│   ├── example-01-and-gate/
│   │   ├── and_gate.pcf
│   │   ├── and_gate.v
│   │   └── apio.ini
│   ├── example-02-vectors/
│   │   ├── apio.ini
│   │   ├── vectors.pcf
│   │   └── vectors.v
│   └── solution-full-adder/
│       ├── apio.ini
│       ├── full-adder.pcf
│       └── full-adder.v
├── 04-clocks-and-procedural-assignments/
│   ├── example-01-button-counter/
│   │   ├── apio.ini
│   │   ├── button-counter.pcf
│   │   └── button-counter.v
│   └── solution-clock-counter/
│       ├── apio.ini
│       ├── clock-counter.pcf
│       └── clock-counter.v
├── 05-finite-state-machines/
│   ├── example-01-moore-fsm/
│   │   ├── apio.ini
│   │   ├── moore-fsm.pcf
│   │   └── moore-fsm.v
│   ├── example-02-mealy-fsm/
│   │   ├── apio.ini
│   │   ├── mealy-fsm.pcf
│   │   └── mealy-fsm.v
│   └── solution-button-debouncing/
│       ├── apio.ini
│       ├── solution-button-debouncing.pcf
│       └── solution-button-debouncing.v
├── 06-modules-and-parameters/
│   ├── example-01-parameters/
│   │   ├── apio.ini
│   │   ├── clock-divider.v
│   │   ├── top-design.pcf
│   │   └── top-design.v
│   ├── example-02-ansi-parameters/
│   │   ├── apio.ini
│   │   ├── clock-divider.v
│   │   ├── top-design.pcf
│   │   └── top-design.v
│   └── solution-count-up-down/
│       ├── apio.ini
│       ├── clock-divider.v
│       ├── count-up-down-top.v
│       ├── count-up-down.pcf
│       └── counter-fsm.v
├── 07-simulation-and-testbenches/
│   ├── example-01-testbench/
│   │   ├── apio.ini
│   │   ├── clk-div_tb.gtkw
│   │   ├── clk-div_tb.v
│   │   └── clock-divider.v
│   └── solution-debounce-testbench/
│       ├── apio.ini
│       ├── button-debouncing.v
│       ├── button-debouncing_tb.gtkw
│       └── button-debouncing_tb.v
├── 08-memory/
│   ├── example-01-memory/
│   │   ├── apio.ini
│   │   ├── memory.v
│   │   ├── memory_tb.gtkw
│   │   ├── memory_tb.v
│   │   └── test.pcf
│   ├── example-02-memory-initialization/
│   │   ├── apio.ini
│   │   ├── mem_init.txt
│   │   ├── memory.v
│   │   ├── memory_tb.gtkw
│   │   ├── memory_tb.v
│   │   └── test.pcf
│   └── solution-sequencer/
│       ├── apio.ini
│       ├── clock-divider.v
│       ├── debouncer.v
│       ├── mem_init.txt
│       ├── memory.v
│       ├── sequencer-top.pcf
│       ├── sequencer-top.v
│       ├── sequencer-top_tb.gtkw
│       └── sequencer-top_tb.v
├── 09-pll-and-glitches/
│   ├── example-01-pll/
│   │   ├── apio.ini
│   │   ├── pll_test.pcf
│   │   └── pll_test.v
│   ├── example-02-glitches/
│   │   ├── apio.ini
│   │   ├── empty.v
│   │   ├── glitch-test_tb.gtkw
│   │   └── glitch-test_tb.v
│   └── solution-gray-code-counter/
│       ├── apio.ini
│       ├── empty.v
│       ├── gray-code-counter_tb.gtkw
│       └── gray-code-counter_tb.v
├── 10-metastability/
│   ├── example-01-metastability-test/
│   │   ├── apio.ini
│   │   ├── dual-sqwv.dwf3work
│   │   ├── metastability-test.pcf
│   │   └── metastability-test.v
│   ├── example-02-better-clock-divider/
│   │   ├── apio.ini
│   │   ├── clock-divider.v
│   │   ├── clock-divider_tb.gtkw
│   │   ├── clock-divider_tb.v
│   │   ├── slow-blink.pcf
│   │   └── slow-blink.v
│   ├── example-03-better-debouncer/
│   │   ├── apio.ini
│   │   ├── debouncer.v
│   │   ├── debouncer_tb.gtkw
│   │   └── debouncer_tb.v
│   └── solution-async-fifo/
│       ├── apio.ini
│       ├── async-fifo.v
│       ├── async-fifo_tb.gtkw
│       ├── async-fifo_tb.v
│       ├── dummy.pcf
│       ├── r-ptr-empty.v
│       └── w-ptr-full.v
├── 11-risc-v-softcore-cpu/
│   ├── example-01-blinky/
│   │   ├── Makefile
│   │   └── main.c
│   └── solution-buttons/
│       ├── Makefile
│       └── main.c
├── 12-risc-v-custom-peripheral/
│   └── example-01-pwm/
│       ├── C/
│       │   └── pwm_test/
│       │       ├── Makefile
│       │       └── main.c
│       └── RTL/
│           ├── apio.ini
│           ├── pwm.pcf
│           ├── pwm.v
│           ├── pwm_tb.gtkw
│           └── pwm_tb.v
└── README.md
Download .txt
SYMBOL INDEX (3 symbols across 3 files)

FILE: 11-risc-v-softcore-cpu/example-01-blinky/main.c
  function main (line 9) | int main() {

FILE: 11-risc-v-softcore-cpu/solution-buttons/main.c
  function main (line 9) | int main() {

FILE: 12-risc-v-custom-peripheral/example-01-pwm/C/pwm_test/main.c
  function main (line 9) | int main() {
Condensed preview — 116 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (122K chars).
[
  {
    "path": ".gitignore",
    "chars": 171,
    "preview": "# yosys - Verilog synthesis\n# nextpnr - Place and route\n# Icarus Verilog - Simulation\n# GTKWate - Simulation viewer\n*.db"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/info",
    "chars": 68,
    "preview": "Hello world example for the Icestick board. Turning all the leds on\n"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds.pcf",
    "chars": 616,
    "preview": "# -----------------------------------------------------------------------------\n#- Leds example for the iCEstick board\n#"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds.v",
    "chars": 456,
    "preview": "//------------------------------------------------------------------\n//-- Hello world example for the iCEstick board\n//-"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds_tb.gtkw",
    "chars": 638,
    "preview": "[*]\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-exa"
  },
  {
    "path": "02-install-apio/solution-turn-off-led/leds_tb.v",
    "chars": 962,
    "preview": "//-------------------------------------------------------------------\n//-- leds_tb.v\n//-- Testbench\n//------------------"
  },
  {
    "path": "03-verilog-gate-logic/example-01-and-gate/and_gate.pcf",
    "chars": 111,
    "preview": "# 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",
    "chars": 548,
    "preview": "// AND gate example\n//\n// Inputs:\n//      pmod_0  - pushbutton\n//      pmod_1  - pushbutton\n// Outputs:\n//      led_0   "
  },
  {
    "path": "03-verilog-gate-logic/example-01-and-gate/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "03-verilog-gate-logic/example-02-vectors/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "03-verilog-gate-logic/example-02-vectors/vectors.pcf",
    "chars": 235,
    "preview": "# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\nset_io              led[2]  97\nset_io              "
  },
  {
    "path": "03-verilog-gate-logic/example-02-vectors/vectors.v",
    "chars": 839,
    "preview": "// Vector and intermediate (wire) value example\n//\n// Inputs:\n//      pmod[1:0]   - pushbuttons (x2)\n//\n// Outputs:\n//  "
  },
  {
    "path": "03-verilog-gate-logic/solution-full-adder/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "03-verilog-gate-logic/solution-full-adder/full-adder.pcf",
    "chars": 173,
    "preview": "# 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  "
  },
  {
    "path": "03-verilog-gate-logic/solution-full-adder/full-adder.v",
    "chars": 885,
    "preview": "// Solution to full adder challenge\n//\n// Inputs:\n//      pmod[2:0]   - pushbuttons (x3)\n//\n// Outputs:\n//      led[1:0]"
  },
  {
    "path": "04-clocks-and-procedural-assignments/example-01-button-counter/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "04-clocks-and-procedural-assignments/example-01-button-counter/button-counter.pcf",
    "chars": 204,
    "preview": "# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\nset_io              led[2]  97\nset_io              "
  },
  {
    "path": "04-clocks-and-procedural-assignments/example-01-button-counter/button-counter.v",
    "chars": 1020,
    "preview": "// Button counter\n//\n// Inputs:\n//      pmod[0]     - pushbutton (RESET)\n//      pmod[1]     - pushbutton (CLOCK)\n// Out"
  },
  {
    "path": "04-clocks-and-procedural-assignments/solution-clock-counter/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "04-clocks-and-procedural-assignments/solution-clock-counter/clock-counter.pcf",
    "chars": 218,
    "preview": "# Oscillator\nset_io              clk     21\n\n# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\nset_io"
  },
  {
    "path": "04-clocks-and-procedural-assignments/solution-clock-counter/clock-counter.v",
    "chars": 1272,
    "preview": "// Clock-divided counter\n//\n// Inputs:  \n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RESET)\n// "
  },
  {
    "path": "05-finite-state-machines/example-01-moore-fsm/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "05-finite-state-machines/example-01-moore-fsm/moore-fsm.pcf",
    "chars": 312,
    "preview": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]   "
  },
  {
    "path": "05-finite-state-machines/example-01-moore-fsm/moore-fsm.v",
    "chars": 3318,
    "preview": "// Count up on button press and stop (Moore state machine)\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst"
  },
  {
    "path": "05-finite-state-machines/example-02-mealy-fsm/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "05-finite-state-machines/example-02-mealy-fsm/mealy-fsm.pcf",
    "chars": 312,
    "preview": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]   "
  },
  {
    "path": "05-finite-state-machines/example-02-mealy-fsm/mealy-fsm.v",
    "chars": 3074,
    "preview": "// Count up on button press and stop (Mealy state machine)\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst"
  },
  {
    "path": "05-finite-state-machines/solution-button-debouncing/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "05-finite-state-machines/solution-button-debouncing/solution-button-debouncing.pcf",
    "chars": 277,
    "preview": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]   "
  },
  {
    "path": "05-finite-state-machines/solution-button-debouncing/solution-button-debouncing.v",
    "chars": 3429,
    "preview": "// One possible way to debounce a button press (using a Moore state machine)\n// \n// Inputs:\n//      clk         - 12 MHz"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/clock-divider.v",
    "chars": 1100,
    "preview": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum valu"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/top-design.pcf",
    "chars": 156,
    "preview": "# Oscillator\nset_io              clk     21\n\n# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\n\n# PMO"
  },
  {
    "path": "06-modules-and-parameters/example-01-parameters/top-design.v",
    "chars": 1066,
    "preview": "// Example of a top-level design with 2 different clocks.\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/clock-divider.v",
    "chars": 1104,
    "preview": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum valu"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/top-design.pcf",
    "chars": 156,
    "preview": "# Oscillator\nset_io              clk     21\n\n# LEDs\nset_io              led[0]  99\nset_io              led[1]  98\n\n# PMO"
  },
  {
    "path": "06-modules-and-parameters/example-02-ansi-parameters/top-design.v",
    "chars": 1026,
    "preview": "// Example of a top-level design with 2 different clocks.\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/clock-divider.v",
    "chars": 1104,
    "preview": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum valu"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/count-up-down-top.v",
    "chars": 2393,
    "preview": "// One possible solution to the count up and down challenge\n//\n// Inputs:\n//      clk         - 12 MHz clock\n//      rst"
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/count-up-down.pcf",
    "chars": 242,
    "preview": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]   "
  },
  {
    "path": "06-modules-and-parameters/solution-count-up-down/counter-fsm.v",
    "chars": 3376,
    "preview": "// Count up on button signal and stop.\n//\n// Parameters:\n//      COUNT_UP    - 1 to count up, 0 to count down\n//      MA"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/clk-div_tb.gtkw",
    "chars": 827,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Nov 11 19:42:09 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/clk-div_tb.v",
    "chars": 1482,
    "preview": "// Testbench for clock divider\n//\n// Date: November 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Defines timesca"
  },
  {
    "path": "07-simulation-and-testbenches/example-01-testbench/clock-divider.v",
    "chars": 1103,
    "preview": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum valu"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing.v",
    "chars": 3494,
    "preview": "// One possible way to debounce a button press (using a Moore state machine)\n//\n// Parameters:\n//      MAX_CLK_COUNT   -"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing_tb.gtkw",
    "chars": 885,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Nov 11 22:58:44 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "07-simulation-and-testbenches/solution-debounce-testbench/button-debouncing_tb.v",
    "chars": 2469,
    "preview": "// Testbench for button debounce design\n//\n// Date: November 11, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define"
  },
  {
    "path": "08-memory/example-01-memory/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "08-memory/example-01-memory/memory.v",
    "chars": 1078,
    "preview": "// Simple block RAM example\n// \n// Inputs:\n//      clk             - Input clock\n//      w_en            - Write enable\n"
  },
  {
    "path": "08-memory/example-01-memory/memory_tb.gtkw",
    "chars": 775,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Nov 15 20:31:41 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "08-memory/example-01-memory/memory_tb.v",
    "chars": 2123,
    "preview": "// Testbench for memory\n//\n// First, read from address in memory (should be garbage or unknown). Next,\n// write to that "
  },
  {
    "path": "08-memory/example-01-memory/test.pcf",
    "chars": 661,
    "preview": "# 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"
  },
  {
    "path": "08-memory/example-02-memory-initialization/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "08-memory/example-02-memory-initialization/mem_init.txt",
    "chars": 47,
    "preview": "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",
    "chars": 1251,
    "preview": "// Simple block RAM example\n// \n// Inputs:\n//      clk             - Input clock\n//      w_en            - Write enable\n"
  },
  {
    "path": "08-memory/example-02-memory-initialization/memory_tb.gtkw",
    "chars": 825,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Nov 15 20:27:07 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "08-memory/example-02-memory-initialization/memory_tb.v",
    "chars": 2530,
    "preview": "// Testbench for memory\n//\n// First, read from address in memory (should be garbage or unknown). Next,\n// write to that "
  },
  {
    "path": "08-memory/example-02-memory-initialization/test.pcf",
    "chars": 661,
    "preview": "# 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"
  },
  {
    "path": "08-memory/solution-sequencer/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "08-memory/solution-sequencer/clock-divider.v",
    "chars": 1104,
    "preview": "// Simple clock divider\n//\n// Parameters:\n//      COUNT_WIDTH - Bus width for counter\n//      MAX_COUNT   - Maximum valu"
  },
  {
    "path": "08-memory/solution-sequencer/debouncer.v",
    "chars": 3105,
    "preview": "// One possible way to debounce a button press (using a Moore state machine)\n// \n// Inputs:\n//      clk         - 12 MHz"
  },
  {
    "path": "08-memory/solution-sequencer/mem_init.txt",
    "chars": 15,
    "preview": "0\n0\n0\n0\n1\n1\n1\n1"
  },
  {
    "path": "08-memory/solution-sequencer/memory.v",
    "chars": 1485,
    "preview": "// Simple block RAM example\n// \n// Inputs:\n//      clk             - Input clock\n//      w_en            - Write enable\n"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top.pcf",
    "chars": 422,
    "preview": "# Oscillator\nset_io              clk             21\n\n# LEDs\nset_io              led[0]          99\nset_io              l"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top.v",
    "chars": 3738,
    "preview": "// Top-level design for sequencer\n// \n// Inputs:\n//      clk         - 12 MHz clock\n//      rst_btn     - pushbutton (RE"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top_tb.gtkw",
    "chars": 999,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Tue Nov 16 17:21:28 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "08-memory/solution-sequencer/sequencer-top_tb.v",
    "chars": 2228,
    "preview": "// Testbench for sequencer\n//\n// Make sure the sequencer can store and replay step values.\n//\n// Date: November 15, 2021"
  },
  {
    "path": "09-pll-and-glitches/example-01-pll/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "09-pll-and-glitches/example-01-pll/pll_test.pcf",
    "chars": 94,
    "preview": "# 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",
    "chars": 1141,
    "preview": "// Simple block RAM example\n// \n// Inputs:\n//      ref_clk     - Input reference clock (12 MHz)\n// \n// Outputs:\n//      "
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/empty.v",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/glitch-test_tb.gtkw",
    "chars": 898,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Dec 06 17:26:08 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "09-pll-and-glitches/example-02-glitches/glitch-test_tb.v",
    "chars": 2050,
    "preview": "// Simulation of glitches with a ripple-carry adder.\n//\n// Date: December 6, 2021\n// Author: Shawn Hymel\n// License: 0BS"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/empty.v",
    "chars": 41,
    "preview": "// This file is needed to make apio happy"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/gray-code-counter_tb.gtkw",
    "chars": 757,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Mon Dec 06 17:23:51 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "09-pll-and-glitches/solution-gray-code-counter/gray-code-counter_tb.v",
    "chars": 2759,
    "preview": "// Simulation of a 4-bit gray code counter using a finite state machine.\n//\n// Date: December 6, 2021\n// Author: Shawn H"
  },
  {
    "path": "10-metastability/example-01-metastability-test/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/example-01-metastability-test/metastability-test.pcf",
    "chars": 150,
    "preview": "# PMOD I/O\nset_io              clk_in      87\nset_io              sig_in      88\nset_io              clk_out     90\nset_"
  },
  {
    "path": "10-metastability/example-01-metastability-test/metastability-test.v",
    "chars": 1228,
    "preview": "// Input 2 MHz clock and 1 MHz sqaure wave signal. Phase shift the\n// 1 MHz signal to force metastability.\n//\n// Connect"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/clock-divider.v",
    "chars": 1102,
    "preview": "// A better way to create a clock divider that does not use flip-flip outputs\n// as clock inputs to other flip-flops. Us"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/clock-divider_tb.gtkw",
    "chars": 712,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Dec 16 22:08:09 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/clock-divider_tb.v",
    "chars": 1387,
    "preview": "// Test clock divider operation. The divider output (tick) should\n// pulse once at each divided cycle.\n//\n// Date: Decem"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/slow-blink.pcf",
    "chars": 137,
    "preview": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led         99\n\n# PMOD I/O\nset_io  -pullup y"
  },
  {
    "path": "10-metastability/example-02-better-clock-divider/slow-blink.v",
    "chars": 979,
    "preview": "// Slow blink example using the better clock divider.\n//\n// Based on work by: https://github.com/Paebbels\n//\n// Date: De"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/debouncer.v",
    "chars": 1536,
    "preview": "// Debounce signal logic without the use of a clock divider.\n//\n// Based on: https://forum.digikey.com/t/debounce-logic-"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/debouncer_tb.gtkw",
    "chars": 701,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Thu Dec 16 22:04:13 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "10-metastability/example-03-better-debouncer/debouncer_tb.v",
    "chars": 2394,
    "preview": "// Testbench for button debounce design\n//\n// Date: November 16, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define"
  },
  {
    "path": "10-metastability/solution-async-fifo/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "10-metastability/solution-async-fifo/async-fifo.v",
    "chars": 4173,
    "preview": "// Implementation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/pa"
  },
  {
    "path": "10-metastability/solution-async-fifo/async-fifo_tb.gtkw",
    "chars": 804,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Sat Dec 11 20:21:30 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "10-metastability/solution-async-fifo/async-fifo_tb.v",
    "chars": 3513,
    "preview": "// Simulation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/papers"
  },
  {
    "path": "10-metastability/solution-async-fifo/dummy.pcf",
    "chars": 597,
    "preview": "# 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_"
  },
  {
    "path": "10-metastability/solution-async-fifo/r-ptr-empty.v",
    "chars": 2655,
    "preview": "// Implementation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/pa"
  },
  {
    "path": "10-metastability/solution-async-fifo/w-ptr-full.v",
    "chars": 3081,
    "preview": "// Implementation of Clifford Cummings's asynchronous FIFO design from the paper\n// at http://www.sunburst-design.com/pa"
  },
  {
    "path": "11-risc-v-softcore-cpu/example-01-blinky/Makefile",
    "chars": 55,
    "preview": "include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc\n"
  },
  {
    "path": "11-risc-v-softcore-cpu/example-01-blinky/main.c",
    "chars": 452,
    "preview": "// Blink 2 LEDs and print info to the serial terminal.\n//\n// Date: December 19, 2021\n// Author: Shawn Hymel\n// License: "
  },
  {
    "path": "11-risc-v-softcore-cpu/solution-buttons/Makefile",
    "chars": 55,
    "preview": "include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc\n"
  },
  {
    "path": "11-risc-v-softcore-cpu/solution-buttons/main.c",
    "chars": 365,
    "preview": "// Count on LEDs as long as button is pressed.\n//\n// Date: December 19, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n#i"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/C/pwm_test/Makefile",
    "chars": 55,
    "preview": "include ../../learn-fpga/FemtoRV/FIRMWARE/makefile.inc\n"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/C/pwm_test/main.c",
    "chars": 325,
    "preview": "// Slowly increase the brightness of the PWM-controlled LED over and over.\n//\n// Date: December 19, 2021\n// Author: Shaw"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/apio.ini",
    "chars": 24,
    "preview": "[env]\nboard = icestick\n\n"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm.pcf",
    "chars": 195,
    "preview": "# Oscillator\nset_io              clk         21\n\n# LEDs\nset_io              led[0]      99\nset_io              led[1]   "
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm.v",
    "chars": 1372,
    "preview": "// PWM driver for FemtoRV: https://github.com/BrunoLevy/learn-fpga\n//\n// Controls brightness of first LED. Set duty cycl"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm_tb.gtkw",
    "chars": 798,
    "preview": "[*]\n[*] GTKWave Analyzer v3.3.77 (w)1999-2016 BSI\n[*] Wed Dec 15 20:37:05 2021\n[*]\n[dumpfile] \"C:\\Users\\sgmustadio\\Docum"
  },
  {
    "path": "12-risc-v-custom-peripheral/example-01-pwm/RTL/pwm_tb.v",
    "chars": 1780,
    "preview": "// Simulation of PWM driver.\n//\n// Date: December 15, 2021\n// Author: Shawn Hymel\n// License: 0BSD\n\n// Define timescale\n"
  },
  {
    "path": "README.md",
    "chars": 4276,
    "preview": "# Introduction to FPGA\n\nWelcome to the demo code and solutions section of my Introduction to FPGA course! This repositor"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the ShawnHymel/introduction-to-fpga GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 116 files (104.9 KB), approximately 35.2k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!