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.
[](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.
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
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.