Video 4 of 4 · ~8 minutes · Week 2 Capstone
Dr. Mike Borowczak · Electrical & Computer Engineering · CECS · UCF
ARM licenses Verilog IP. Cadence and Synopsys sell Verilog IP. OpenCores distributes free Verilog IP. The IP economy exists because well-designed modules drop into other designers' projects without modification. Engineers' reputations in the industry are built on one thing: has your module been reused? When a module at a large company gets used by 10 different chips, its author is untouchable.
Your Week 1-2 module library now includes ~10 tested modules. Week 3 will build UART and SPI by combining them. Capstone and senior-design projects will reach back into this library for years. Today's practices determine whether that library is usable or merely available.
| Module | Day | Parameters | Tested? |
|---|---|---|---|
sync_2ff | 5 | WIDTH | ✓ |
debounce | 5 | CLKS_STABLE | ✓ |
edge_detect | 5 | — | ✓ |
mod_n_counter | 5 | N | ✓ |
sipo_shift | 5 | WIDTH | ✓ |
piso_shift | 5 | WIDTH | ✓ |
traffic_fsm | 7 | — | ✓ |
pattern_detector | 7 | PATTERN, WIDTH | ✓ |
fifo | 8 | DEPTH, WIDTH | ✓ |
button_array | 8 | N, CLKS_STABLE | ✓ |
piso_shift + mod_n_counter (baud) + FSM. UART RX = sync_2ff + sipo_shift + oversampler FSM. SPI = both + CS debounce. Everything composes.
Hard-coded widths. Assumes particular clock rate. Testbench works only with “my” input pattern. Undocumented. Signal names reflect current project, not purpose. Sub-modules tangled with the top. Only original author can use it — and only in this project.
Parameterized over everything that varies. Clock-rate independence where possible. Testbench covers the module's contract (not a specific application). Documented inputs, outputs, behavior, timing, assumptions. Named for function. Self-contained — no external dependencies. A stranger can drop it in and it works.
//-----------------------------------------------------------------------------
// debounce.v — counter-based mechanical switch debouncer
//
// Takes an asynchronous, potentially bouncing input, and produces
// a clean version that only changes after CLKS_STABLE consecutive
// cycles of input persistence.
//
// Parameters:
// CLKS_STABLE : cycles to wait before accepting a new value
// (default 500_000 = 20ms @ 25MHz)
//
// Ports:
// i_clk : synchronous clock
// i_reset : synchronous reset (active high)
// i_noisy : input from external switch (async OK, but sync first
// externally if clock-domain-crossing applies)
// o_clean : stable debounced output
//
// Latency: up to CLKS_STABLE cycles after a stable input change.
// Usage: debounce #(.CLKS_STABLE(N)) u_deb (...);
//-----------------------------------------------------------------------------
module debounce #(parameter CLKS_STABLE = 500_000) (
input wire i_clk, i_reset, i_noisy,
output reg o_clean
);
// ... implementation ...
endmodule
make stat produces expected cell countPick a module from your Week 1-2 labs. Score it against the reusability checklist. For each unchecked box, name the work you'd do to check it.
25_000_000 or 250_000 → parameterize CLKS_PER_SECtmp, x, cnt → rename for purposemake simBEFORE: “works for me”
module btn (
input clk, rst, x,
output y
);
reg [18:0] cnt;
// ... 20 ms @ 25 MHz ...
// (hard-coded to my project)
endmodule
AFTER: reusable
// Header comment: datasheet
module debounce #(
parameter CLKS_STABLE = 500_000
) (
input wire i_clk, i_reset, i_noisy,
output reg o_clean
);
localparam W = $clog2(CLKS_STABLE);
reg [W-1:0] r_count;
// ... logic with docs ...
endmodule
Ask AI: “Here's my debouncer. Refactor it to be reusable: add a parameter for the debounce window, auto-size the counter width, add a header comment block in a datasheet style, and rename signals with the i_/o_/r_ convention.”
TASK
AI refactors to reusable style.
BEFORE
Predict: parameter added, $clog2 used, renamed signals, datasheet comment.
AFTER
Strong AI documents latency + timing assumptions. Weak AI only does syntactic rename.
TAKEAWAY
“Reusable” means semantic changes + docs, not just renaming.
① A module is reusable when a stranger can use it from the header alone.
② Everything that could vary is a parameter; everything else is documented.
③ The header comment is the IP datasheet. Write it as such.
④ Your 10-module library becomes Week 3's UART + SPI backbone.
Q1: Name three things that should be parameterized in a debouncer module.
Q2: What goes in a header comment block that doesn't go in the Verilog code itself?
Q3: Why is signal naming part of reusability?
sw1_press, fan_on) can't be used in other projects. Signals with functional names (i_noisy, o_clean) work everywhere.Q4: What single question do you ask to tell if a testbench tests a module's contract vs. a specific application?
🔗 End of Week 2
UART · SPI · Integration Projects
▸ WHY THIS MATTERS NEXT
You've now learned the alphabet of hardware design: combinational logic, sequential logic, synchronization, verification, state machines, and reuse. Week 3 is where you compose words and sentences. UART TX + RX — to actually talk to your computer over a serial cable. SPI master — to drive peripherals. Your Week 1-2 module library isn't the byproduct; it's the material of Week 3's designs. You're not going to learn many new primitives next week — you're going to build real things out of the ones you already have. See you Day 9.