Sequential Verilog
- We can design combinational circuits using
- Gate-level structural design
- Assign statements
- Behavioural always blocks
- Important to consider that our circuits are purely combinational in all cases
- It is possible to design sequential circuits
- Most designs will be synchronous: synced with a clock
Latches
SR Latch
- Two inputs
- Two outputs
- Two NOR gates
module srlatch(input R, S
output Q, Qbar);
nor N1 (Q, R, Qbar);
nor N2 (Qbar, S, Q);
// Alternatively
assign Q = R ~| Qbar;
assign Qbar = S ~| Q;
endmodule
D Latch
A D latch is synchronous, where an SR isn't:
module dlatch(input EN, D,
output reg Q, Qbar);
always @ (D, EN)
if(EN) begin
Q <= D;
Qbar <= ~D;
end
end
endmodule;
D goes to Q if enable is high: circuit is described succinctly.
Generally, FPGA designs will be synchronous as it allows us to more easily understand the timing of the circuit. Most of the logic we will look at will be edge-triggered, which is described as follows:
module simplereg(input d, clk, output reg q);
always @ (posedge clk)
q <= d;
endmodule
posedge
keyword can can be used in a sensitivity list to define a trigger on the rising edge of a clock (negedge
is also a thing). In this case, a simple register is created. A multi-bit register/flip flop is defined below:
module simplereg(input [3:0] d, input clk, output reg [3:0] q);
always @ (posedge clk)
q <= d;
endmodule
Clocks and Reset
- All circuits should be synchronised based on the same clock signal
- Clock can be named whatever (usually
clk
) and defined as an input to the module - We often need to reset the contents of a register or state of circuit to 0/a default
- Two types of reset:
- Asynchronous: whenever the reset input is asserted, the reset is triggered
- Synchronous: if the reset is asserted on the rising edge, reset is triggered
- In modern FPGA design, we use synchronous reset
- Two types of reset:
An 8 bit register with synchronous reset:
module 8bitreg(input [7:0] d,
input clk, rst,
output reg [7:0] q);
always @ (posedge clk) begin
if(rst)
q <= 8'b00000000;
else
q <= d;
end
endmodule
For an asynchronous reset, the reset signal is added to the sensitivity list so that the block can be triggered independently of the clock. However, this will desynchronise the always block from the rest of the circuit so is not the prefferred way to do it.
module 8bitreg(input [7:0] d,
input clk, rst,
output reg [7:0] q);
always @ (posedge clk or posedge rst) begin
if(rst)
q <= 8'b00000000;
else
q <= d;
end
endmodule
Registers
Can control multiple registers from the same block. Each assignment in a synchronous always block creates a register controlled by the same block. This verilog module contains 3 8-bit registers.
module multireg(input [7:0] a, b, c
input clk, rst
output reg [7:0] q, r, s);
always @ (posedge clk) begin
if(!rst) begin
q <= 0;
r <= 0;
s <= 0;
end
else begin
q <= a;
r <= b;
s <= c;
end
end
endmodule
- When drawing can ignore clock and reset as they should always be there
- Putting a triangle on an input in a block diagram shows that the input is edge-triggered
Non-Blocking assignment
- The
<=
operator is called non-blocking assignment - For combinational always blocks, as use blocking assignment and order matters
- For a synchronous block, order does not matter
- Everything only happens on the rising edge
Counters
A register where the value increments on the rising edge (or decrements if down
signal is asserted).
module simplecount(input clk, rst, down, output reg [3:0] q);
always @ (posedge clk) begin
if(rst)
q <= 4'b0000;
else
if(down)
q <= q - 1'b1;
else
q <= q + 1'b1;
endmodule
Can alter to include an enable
signal. Since it's a synchronous component, don't need to account for all branches.
module simplecount(input clk, rst, down, enable, output reg [3:0] q);
always @ (posedge clk) begin
if(rst)
q <= 4'b0000;
else
if(enable)
if(down)
q <= q - 1'b1;
else
q <= q + 1'b1;
end
endmodule
Can again alter to include the ability to load a value.
module simplecount(input clk, rst, down, load, input [3:0] cnt_in, output reg [3:0] q);
always @ (posedge clk) begin
if(rst)
q <= 4'b0000;
else
if(load)
q <= cnt_in
else
if(down)
q <= q - 1'b1;
else
q <= q + 1'b1;
end
endmodule
Shift Registers
1 bit serial in serial out shift register. Propagation occurs on the rising edge of the clock.
- Order of assignment does not matter
module shiftreg(input clk, y, output reg q);
req q1,q2,q3;
always @ (posedge clk) begin
q1 <= y;
q2 <= q1;
q3 <= q2;
q <= q3;
end
endmodule
Can make the module simpler using vectors, where each stage in the shift register is a separate position in the vector. The LSB is replaced by the input, and the MSB is the output.
module shiftreg(input clk, y, output reg q_out);
req [4:0] q;
always @ (posedge clk) begin
q[0] <= y;
q[4:1] <= q[3:0];
q_out <= q[4];
end
endmodule
Memory
- 64 element memory requires 6-bit address input, with each word as 16 bits
- Declare internal 64-element array, where each position is 16 bits.
module spram(input clk, en, write_en,
input [5:0] addr,
input [15:0] d_in
output reg [15:0] d_out);
reg [15:0] ram [0:63];
always @ (posedge clk) begin
if (en) begin
if (write_en) begin
ram[addr] <= d_in;
end
d_out <= ram [addr];
end
end
endmodule
On each clock cycle:
- output 16 bit word that is on the provided addres
- if
write_en
, thend_in
is stored at the memory locationaddr