Day 1 of making a UART š² I made a SIPO shift register
I donāt think Iāve mentioned this on here before but, Iām loosely following the fromthetransistor course here and there when I have the time and energy.
Obviously, Iāve made this work correctly so I know how to do it. But I wanted to write this down to see how well I could articulate the concepts Iāve learned.
The first place I went to was wikipedia and I found this exact diagram.
It made the concept of a shift register much clearer and gave me the blueprint on what I should be working on to make it happen. The first thing this inspired me to make was a D flip flop which I learned about in this article and by doing some exercises on HDLBits. This ressource was also very helpful to my understanding of flip flops and latches.
D Flip-flop
This is the first thing I had to implement because itās the main piece of the puzzle. The flip flop is what holds the data in transit, itās a very basic form of memory. Hereās my dff module in verilog:
module dff (
input d,
input clk,
input reg reset,
output reg q
);
always @ (posedge clk or negedge clk) begin
if (reset) begin
q <= 1'b0;
end else begin
q <= d;
end
end
endmodule
You can see how this closely reflects the flip flops in the previous image, the only thing thatās missing here is the set input, but itās not something that I felt was necessary for our use case so I simply decided not to include it. As you can see itās pretty simple, the output q
updates to match the input d
at posedge or negedge of clk, unless reset is active high, in which case q
is set to 0
.
SIPO
As the name states (Serial-in parallel-out) the goal of this register is to take serial data and convert it to parallel. Meaning, it will come in bit-by-bit and come out as a data block.
To hold values, I implemented a simple wire called hold_value
and used ternary operators on the flip flop instantiationsā input d
pins, that serves as a multiplexer that choses between shifting in new data or recycling its own output.
Hereās my SIPO module in verilog:
module sipoUnit #(parameter WIDTH = 8) (
input wire data_in,
input wire hold_value,
input wire reset,
input wire clk,
output reg [WIDTH-1:0] q
);
dff dff0 (
.d(hold_value ? q[0] : data_in),
.reset(reset),
.clk(clk),
.q(q[0])
);
generate
for (genvar i = 0; i < WIDTH-1; i++) begin
dff dff_inst (
.d(hold_value ? q[i+1] : q[i]),
.reset(reset),
.clk(clk),
.q(q[i+1])
);
end
endgenerate
endmodule
I feel that there is nothing else to add. Really, the SIPO register seemed daunting to me at first but when I started breaking the pieces down it became clearer what the next implementation should be.
If thereās anything thatās unclear, or you need clarification on any of the decisions made in this code, feel free to contact me on twitter: @pindjouf.