RTL Design & Verification¶
Homework¶
- Write Verilog for your project’s core module (aim for 10-30 lines to start)
- Integrate with any provided library modules (e.g., debounce, UART, PWM) — create a top-level wrapper
- Simulate with a testbench and examine waveforms in GTKWave
- Run linter (verilator –lint-only) and fix any warnings
Verilog¶
Project : LED display with hexadecimal support with serial input. The display part is a copy of the TIL311 from Texas Instruments The shift register is like a 74xx595, 4 bit wide only.
Decoder module :
module decoder (
// Bits controlling which LED(s) :
//
// 0 1 2
// 3 4
// 3 4
// 5 6 7
// 8 9
// 8 9
// 10 11 12
// Ports
input wire [3:0] bcd,
output reg [12:0] segments
);
always @(*) begin
segments = 13'd0; // 111
case (bcd) // 2109876543210
4'd0: segments = 13'b0101110111010;
4'd1: segments = 13'b1001010010100;
4'd2: segments = 13'b1110101010011;
4'd3: segments = 13'b0111001010011;
4'd4: segments = 13'b1001011111001;
4'd5: segments = 13'b0111001100111;
4'd6: segments = 13'b0101101101010;
4'd7: segments = 13'b1001010010111;
4'd8: segments = 13'b0101101011010;
4'd9: segments = 13'b0101001011010;
4'd10: segments = 13'b1011111111010;
4'd11: segments = 13'b0111101111011;
4'd12: segments = 13'b1100100101110;
4'd13: segments = 13'b0111110111011;
4'd14: segments = 13'b1110101101111;
4'd15: segments = 13'b0010101101111;
endcase
end
endmodule
Shift register module :
module shift (
// Ports
input wire clock, // Clock for the serial data input
input wire data, // Serial data input
input wire reset, // Reset every register to zero
input wire load, // Load the parallel output register
output reg [3:0] bcd,
output reg 3:0] stage // stage[3] is the serial data output
);
// First stage
always @(posedge clock or posedge reset) begin
if (reset) begin
stage <= 0;
end
else begin
stage[0] <= data;
stage[1] <= stage[0];
stage[2] <= stage[1];
stage[3] <= stage[2];
end
end
// Second stage
always @(posedge load or posedge reset) begin
if (reset) begin
bcd <= 0;
end
else begin
bcd <= stage;
end
end
endmodule
Top module :
`include "decoder.v"
`include "shift.v"
module til311 (
// Inputs
//[3:0] bcd, // optionnal parallel input
clock, // Clock for the serial data input
data, // Serial data input
reset, // Reset every register to zero
load, // Load the parallel output register
// Outputs
segments,
data_out // Serial data output
);
// Inputs
input clock;
input data;
input reset;
input load;
// Outputs
output [12:0] segments;
output data_out;
// Internal nets and registers
wire [3:0] stage;
wire [3:0] bcd;
assign data_out = stage[3];
// Instantiations
decoder dec (
.segments (segments),
.bcd (bcd)
);
shift shiftreg (
.clock (clock),
.reset (reset),
.data (data),
.stage (stage),
.bcd (bcd),
.load (load)
);
endmodule
The testbench :
`timescale 1ns/1ps
module tb;
// Inputs
reg clock; // Clock for the serial data input
reg data; // Serial data input
reg reset; // Reset every register to zero
reg load; // Load the parallel output register
// Outputs
wire [12:0] segments;
wire data_out; // Serial data output
til311 dut(clock, data, reset, load, segments, data_out);
initial begin
$dumpfile("til311_tb.vcd");
$dumpvars(0, dut);
// Init
clock = 0;
reset = 1;
data = 0;
load = 0;
// Start
#40 reset = 0;
// Send 4 bits, LSB first
#20 data = 1;
#10 clock = 1;
#10 clock = 0;
#20 data = 1;
#10 clock = 1;
#10 clock = 0;
#20 data = 1;
#10 clock = 1;
#10 clock = 0;
#20 data = 0;
#10 clock = 1;
#10 clock = 0;
// Load the stage-2 registers
#10 load = 1;
#10 load = 0;
// Test the reset
#40 reset = 1;
#40 reset = 0;
#100 $finish;
end
endmodule
I can then compile it with iverilog -o til311.vvp til311_tb.v til311.v
Then run vvp til311.vvp
We can then verify that the waveform is what we expect :

It’s not obvious but 0x0BBA should draw a 0 and 1D6F a E, the value sent : 0b1110.