Building Peripherals
Many FPGA systems are built from peripherals: counters, timers, PWM blocks, UARTs, SPI masters, GPIO ports, filters, and custom accelerators. A good peripheral is not just logic; it has a clear contract.
Learning Objectives
You will learn to:
- define a register map;
- separate bus interface logic from core logic;
- design status and control bits;
- think about firmware-visible behavior;
- avoid ambiguous hardware/software contracts.
Peripheral Structure
Keep the interface and the core separate. It makes testing easier and lets you reuse the core behind different buses.
Example Register Map
| Offset | Name | Access | Bits | Purpose |
|---|---|---|---|---|
0x00 |
CTRL |
R/W | bit0 enable | start/stop peripheral |
0x04 |
PERIOD |
R/W | 31:0 | PWM period in clock cycles |
0x08 |
DUTY |
R/W | 31:0 | high-time in clock cycles |
0x0C |
STATUS |
R/C | bit0 done, bit1 error | event flags |
R/C means read/clear or write-one-to-clear depending on your chosen convention. Document it.
PWM Core Example
module pwm_core (
input wire clk,
input wire rst,
input wire enable,
input wire [31:0] period,
input wire [31:0] duty,
output reg pwm
);
reg [31:0] count;
always @(posedge clk) begin
if (rst) begin
count <= 0;
pwm <= 1'b0;
end else if (!enable) begin
count <= 0;
pwm <= 1'b0;
end else begin
count <= (count == period - 1) ? 0 : count + 1;
pwm <= (count < duty);
end
end
endmodule
This core can be tested without any bus.
Hardware/Software Contract
Define:
- reset values;
- which bits are writable;
- whether writes take effect immediately or at period boundary;
- what happens for invalid values such as
duty > period; - how status flags clear;
- interrupt behavior;
- clock domain assumptions.
Firmware engineers should not need to reverse-engineer the RTL.
Worked Example: Safe PWM Update
If firmware changes period and duty mid-cycle, output may glitch. A better design stores shadow registers and loads them at the period boundary.
Common Mistakes
- Mixing bus protocol details into every core.
- Leaving register reset values undocumented.
- Creating status flags that firmware cannot clear safely.
- Updating output-critical registers mid-cycle without a defined rule.
- Forgetting that bus clock and peripheral clock may differ.
Summary
A peripheral is a hardware block plus a contract. Separate bus interface, registers, and core logic. Document register behavior precisely. Test the core by itself and the register interface separately.
Next: Pipelining, Resource Use, and Optimization.
Further Reading
- AMBA AXI4-Lite protocol documentation
- Wishbone bus specification
- Vendor IP design examples
- Open-source FPGA peripheral projects