Index

# Lecture 02

### 1.1 Hierarchical Design

module 4_bit_adder(output c_out, output [3:0] sum,
input  c_in,  input [3:0] a, b);
wire [3:1] carry;
full_adder fa0(carry[1], sum[0], c_in,     a[0], b[0]);
full_adder fa1(carry[2], sum[1], carry[1], a[1], b[1]);
full_adder fa2(carry[3], sum[2], carry[2], a[2], b[2]);
full_adder fa3(c_out,    sum[3], carry[3], a[3], b[3]);
endmodule

## 2 Dataflow Modelling

• Describes combinational circuits with continuous assignment statements
• the RHS is re-evaluated and assigned to the LHS whenever any inputs change
• operators
• logical: !(not), &&(and), ||(or)
• arithmetic: +, -, *, /, %, **(exponentiation)
• relations: <, >, <=, >=
• equality: ==, != (check $$0$$, $$1$$) (===, !== check $$0$$, $$1$$, $$x$$, $$z$$)
• bit-wise: ~ (negate), &(and), |(or), ^(xor), ^~(xnor)
• shift: <<, >> (logical), <<<, >>> (arithmetic)
• concatenation: {, }
• replication: {n {a}} (replicate 'a' $$n$$ times)
• conditional: ? (e.g. assign out = sel ? in1: in2;)

e.g.

assign sum = a ^ b ^ c;
assign c_out = (a ^ b) & c_in | a & b;
assign out = sel ? in1: in2;
assign {b[3:0], b[7:4]} = a[7:0]
assign b[7:0] = {{4{a[3]}}, a[3:0]};
full_adder_dataflow.sv
module full_adder(output c_out, sum, input, c_in, a, b);
assign sum = a ^ b ^ c_in;
assign c_out = (a ^ b) & c_in | a & b;
endmodule

or

module full_adder(output c_out, sum, input, c_in, a, b);
assign {c_out, sum} = a + b + c_in;
endmodule
adder_4_bit_dataflow.sv
module 4_bit_adder(output c_out, output [3:0] sum,
input  c_in,  input [3:0] a, b);
assign {c_out, sum} = a + b + c_in;
endmodule

## 3 Behavioural Modelling

• Procedural blocks prefaced with initial (run once at $$t=0$$) or always (run continuously from $$t=0$$)
• Can use always@* to match all inputs
• Procedural constructs
• synthesizable
• if-else: if (expr) statements {else statements}
• case-switch: case (expr) {expr: state}(1 or more) + {default: statements}(0 or 1)
• simulatable only (avoid)
• for loop
• while loop
• repeat loop
full_adder_bhvr.sv
module full_adder(output reg, c_out, sum, input c_in, a, b);
// sensitivity list
always@(c_in, a, b) begin
// LHS must be of type reg or logic
sum = a ^ b ^ c_in;
c_out = (a ^ b) & c_in | a & b;
end
endmodule
mux_2x1.sv
module mux_2x1(output reg d, input i0, i1, sel);
always@*
case(sel)
0: d = i0;
1: d = i1;
default: d=z;
endcase
endmodule

### 3.1 Synchronous Designs

• Outputs only update on clock edge
• in testbench:

reg clk;
initial begin
clk = 1; forever #5 clk = ~clk;
end
• blocks are triggered by edge events: always@(posedge clk) (or negedge clk)
• use non-blocking assignment:
• = block assignment
• evaluation order is sequential
• creates combinations logic
• <= non-blocking assignment
• evaluation order is parallel
• create registered/latched output

e.g.

       | a | b |        | a | b
--------------------------------
before | 1 | 2 | before | 1 | 2
a = b; | 2 |   | a <= b |   |
b = a; |   | 2 | b <= a |   |
after  | 2 | 2 | after  | 2 | 1

e.g. counter with reset and enable

counter.sv
module counter(output reg [1:0] d, input clk, reset, enable);
always@(posedge clk or posedge reset)
if (reset) d <= 0;
else if (enable) d <= d + 1;
endmodule

Index