Loadable Shift Register

An 8-bit shift register. When load is high, capture pdata. Otherwise shift left one position per clock, din entering at bit 0. dout always shows bit 7. Synchronous reset clears the register.

Port Dir Width Meaning
clk, rst in 1 clock, sync reset
load in 1 1: capture pdata (wins over shifting)
pdata in 8 parallel load value
din in 1 serial input (enters at LSB)
dout out 1 q[7]

Refresher: the shift registers lesson.

Show the testbench (the grader)
tb.v — locked
`timescale 1ns/1ps
module tb;
    reg clk=0, rst=1, load=0, din=0; reg [7:0] pdata=0;
    wire dout; reg [7:0] model = 0;
    integer i, errors=0; reg [31:0] lfsr = 32'hC0DE;
    challenge dut (.clk(clk), .rst(rst), .load(load), .pdata(pdata),
                   .din(din), .dout(dout));
    always #5 clk = ~clk;
    initial begin
        $dumpfile("wave.vcd"); $dumpvars(0, tb);
        repeat (2) @(negedge clk); rst = 0;
        for (i = 0; i < 300; i = i + 1) begin
            @(negedge clk);
            lfsr = {lfsr[30:0], lfsr[31]^lfsr[21]^lfsr[1]^lfsr[0]};
            load = (lfsr[3:0] == 4'd0);   // occasional load
            pdata = lfsr[15:8]; din = lfsr[4];
            @(posedge clk);
            if (load) model = pdata;
            else      model = {model[6:0], din};
            #1;
            if (dout !== model[7]) begin
                errors = errors + 1;
                if (errors < 6)
                    $display("FAIL @%0t: dout=%b want=%b", $time, dout, model[7]);
            end
        end
        if (errors == 0) $display("TB PASS");
        else $display("TB FAIL (%0d errors)", errors);
        $finish;
    end
endmodule