4-bit Universal Shift Register

Medium

Problem Statement

Implement a 4-bit universal shift register that supports hold, shift-right, shift-left, and parallel-load operations, selected by a 2-bit mode input. Ports: - `clk` — input, 1 bit, clock - `rst` — input, 1 bit, synchronous active-high reset - `mode` — input, 2 bits (`mode[1:0]`), selects the operation (see below) - `serial_in` — input, 1 bit, serial data used during shift operations - `parallel_in` — input, 4 bits (`parallel_in[3:0]`), data used during parallel load - `data_out` — output, 4 bits (`data_out[3:0]`), registered current contents of the register On every rising edge of `clk`: 1. If `rst` is high, `data_out` synchronously clears to `4'b0000`. Reset overrides `mode` entirely. 2. Else, the operation is selected by `mode`: - `mode = 2'b00` (HOLD): `data_out` does not change. - `mode = 2'b01` (SHIFT RIGHT): every bit shifts one position toward the LSB. The new bit 3 (MSB) is loaded from `serial_in`; the old bit 0 (LSB) is discarded. Formally: `data_out <= {serial_in, data_out[3:1]}`. - `mode = 2'b10` (SHIFT LEFT): every bit shifts one position toward the MSB. The new bit 0 (LSB) is loaded from `serial_in`; the old bit 3 (MSB) is discarded. Formally: `data_out <= {data_out[2:0], serial_in}`. - `mode = 2'b11` (PARALLEL LOAD): `data_out` is loaded directly from `parallel_in`, regardless of its previous value. All behavior is fully synchronous — `data_out` only changes on the rising edge of `clk`, and `mode` may change between any two cycles.

Verilog