Skip to content

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 :

GTKWave capture

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