module SiPo_ShiftRegister_4( input i_Clk, input i_Latch, input i_Data, input i_Reset, output o_Data0, output o_Data1, output o_Data2, output o_Data3 ); reg [3:0] r_Data; reg [3:0] r_Incoming; reg [2:0] r_Pos; reg r_didLatch; always @ (posedge i_Clk & i_Reset) begin r_Data <= 0; r_Incoming <= 0; r_Pos <= 0; r_didLatch <= 0; end always @ (posedge i_Clk) begin if (i_Latch & !r_didLatch) begin r_Incoming[0] <= i_Data; r_Incoming[3:1] <= r_Incoming[2:0]; r_Pos <= r_Pos + 1; r_didLatch <= 1; end if (r_didLatch & !i_Latch) begin r_didLatch <= 0; if (r_Pos == 4) begin r_Data[3:0] <= r_Incoming[3:0]; r_Incoming <= 0; r_Pos <= 0; end end end assign o_Data0 = r_Data[0]; assign o_Data1 = r_Data[1]; assign o_Data2 = r_Data[2]; assign o_Data3 = r_Data[3]; endmodule module Test_SIPO(); task assert(input condition); if (!condition) $error; endtask reg r_Data = 1'b0, r_Clk = 1'b0, r_Latch = 1'b0, r_Reset = 1'b0; wire w_Data0, w_Data1, w_Data2, w_Data3; always #2 r_Clk <= !r_Clk; SiPo_ShiftRegister_4 UUT( .i_Clk(r_Clk), .i_Data(r_Data), .i_Latch(r_Latch), .i_Reset(r_Reset), .o_Data0(w_Data0), .o_Data1(w_Data1), .o_Data2(w_Data2), .o_Data3(w_Data3) ); initial begin $dumpfile("test.vcd"); $dumpvars; r_Data <= 1'b1; r_Reset <= 1'b1; @(posedge r_Clk); r_Reset <= 1'b0; @(posedge r_Clk); r_Latch <= 1'b1; @(posedge r_Clk); r_Latch <= 1'b0; @(posedge r_Clk); r_Data <= 0; r_Latch <= 1'b1; @(posedge r_Clk); r_Latch <= 1'b0; @(posedge r_Clk); r_Latch <= 1'b1; @(posedge r_Clk); r_Latch <= 1'b0; @(posedge r_Clk); r_Data <= 1; r_Latch <= 1'b1; @(posedge r_Clk); r_Latch <= 1'b0; @(posedge r_Clk); #5; $finish(); end endmodule