Systemverilog Progressive Example Approach
Systemverilog Progressive Example Approach
module adder4(sum,cout,a,b,cin);
output[3:0] sum;
output cout;
input[3:0] a,b;
input cin;
wire[2:0] c;
fulladder fa0 (.s(sum[0]) , .cout(c[0]) , .a(a[0]) , .b(b[0]) , .cin(cin));
fulladder fa1 (.s(sum[1]) , .cout(c[1]) , .a(a[1]) , .b(b[1]) , .cin(c[0]));
fulladder fa2 (.s(sum[2]) , .cout(c[2]) , .a(a[2]) , .b(b[2]) , .cin(c[1]));
fulladder fa3 (.s(sum[3]) , .cout(cout) , .a(a[3]) , .b(b[3]) , .cin(c[2]));
endmodule
Four bit Adder (Behavioral)
module adder_behave #(parameter width = 8)(sum,cout,a,b,cin);
output [width-1:0] sum;
output cout;
input [width-1:0] a,b;
input cin;
assign {cout,sum} = a + b + cin;
endmodule
MUX (Behavioral)
module mux2to1#(parameter width = 8)(f,I0,I1,sel);
output [width-1:0] f;
input [width-1:0] I0,I1;
input sel;
assign f = sel? I1:I0;
endmodule
4to1 MUX
module mux4to1 #(parameter width= 8)(f,i3,i2,i1,i0,sel);
output [width-1:0] f;
input [width-1:0] i3,i2,i1,i0;
input [1:0] sel;
assign f = sel[1] ? (sel[0]? i3 : i2): (sel[0]? i1 : i0);
endmodule
ALU (Behavioral)
module ALU#(parameter width = 4)(result,cout,a,b,cont);
output [width-1:0] result;
output cout;
input [width-1:0] a, b;
input [1:0]cont;
wire [width-1:0] b_bar, mux2to1_out, sum, and_N_out, or_N_out;
assign and_N_out = a & b;
assign or_N_out = a | b;
assign b_bar = ~b;
mux2to1#(width)mux1(mux2to1_out,b,b_bar,cont[0]);
adder#(width) add1(sum,cout,a,mux2to1_out,cont[0]);
mux4to1 #(width)mux2(result,or_N_out,and_N_out,sum,sum,cont);
endmodule
Process
• Initial Process
initial
begin
sequential statements
end
• Sequential process
always @ (sensitivity-list)
begin
sequential statements
end
Process
Assignments
• Type of Assignments
– Continuous Assignments
• Explicit Assignment
• Implicit Assignment
– Procedural Assignments
• Blocking Assignment
• Non-blocking Assignment
Procedural Assignments
Delay
• Inertial Delay
• Transport Delay
`timescale 1ns/1ps
module delay (z1, z2, z3, a);
output z1,z2,z3;
output z4;
input a;
reg z1,z2;
// Inertial Delay
a
assign #10 z3 = a;
always@(*)
z1 Begin
// Inertial Delay in process
#10 z2 <= a;
z2/z3 end
// Transport Delay
always@(a)
begin
z1 <= #10 (a);
end
endmodule
Test Benches
module FA_TB();
module FA(s,cout,a,b,cin);
reg a,b,cin;
input a,b,cin;
wire s,cout;
output s,cout;
// Applying test signal from test bench
assign s = a^b^cin;
initial
assign cout =
begin
(a&b)|(a&cin)|(b&cin);
a = 0; b = 0; cin = 0; #10;
endmodule
a = 0; b = 0; cin = 1; #10;
a = 0; b = 1; cin = 0; #10;
a = 0; b = 1; cin = 1; #10;
a = 1; b = 0; cin = 0; #10;
a = 1; b = 0; cin = 1; #10;
a = 1; b = 1; cin = 0; #10;
a = 1; b = 1; cin = 1;#10;
end
//Instantiating Fulladder module
FA dut(s,cout,a,b,cin);
endmodule
Test Benches
module FA_TB();
reg a,b,cin;
wire s,cout;
// Applying test signal from test bench
initial
begin
a = 0; b = 0; cin = 0; #10;
a = 0; b = 0; cin = 1; #10;
a = 0; b = 1; cin = 0; #10;
a = 0; b = 1; cin = 1; #10;
a = 1; b = 0; cin = 0; #10;
a = 1; b = 0; cin = 1; #10;
a = 1; b = 1; cin = 0; #10;
a = 1; b = 1; cin = 1;#10;
end
//Instantiating Fulladder module
FA dut(s,cout,a,b,cin);
endmodule
module FA_TB_complete();
reg a,b,cin; wire s, cout;
initial
begin
a = 0; b = 0; cin = 0; #5;
assert ((s===0)&&(cout===0)) else $error("000 failed");
Test Benches
#10; a = 0; b = 0; cin = 1; #5;
assert ((s===1)&&(cout===0)) else $error("001 failed");
#10; a = 0; b = 1; cin = 0; #5;
assert ((s===1)&&(cout===0)) else $error("010 failed");
#10; a = 0; b = 1; cin = 1; #5;
assert ((s===0)&&(cout===1)) else $error("011 failed");
#10; a = 1; b = 0; cin = 0; #5;
assert ((s===1)&&(cout===0)) else $error("100 failed");
#10; a = 1; b = 0; cin = 1; #5;
assert ((s===0)&&(cout===1)) else $error("101 failed");
#10; a = 1; b = 1; cin = 0; #5;
assert ((s===0)&&(cout===1)) else $error("110 failed");
#10; a = 1; b = 1; cin = 1; #5;
assert ((s===1)&&(cout===1)) else $error("111 failed"); #10;
end
FA dut(s,cout,a,b,cin);
endmodule
Test Benches
Sequential Circuits (D Flip Flop)
module DFF(q,d,clk);
output q;
input d, clk;
reg q;
always @(posedge clk)
begin
q <= d;
end
endmodule
Sequential Circuits (D Flip Flop TB)
`timescale 1ns/1ps initial
module TB_DFF(); begin
logic clk, d, q; #5; assert(q === 0) else $error("1 cycle failed");
initial #10; assert(q === 1) else $error("2 cycle failed");
begin #10; assert(q === 1) else $error("3 cycle failed");
d = 0; #5; #10; assert(q === 0) else $error("4 cycle failed"); #5;
d = 1; #10; $stop;
d = 0; #2; end
d = 1; #10; DFF ff1(q,d,clk);
d = 0; endmodule
end
always
begin
clk =1; #5;
clk =0; #5;
end
Sequential Circuits (D Latch)
module Dlatch(q,d,clk);
output q;
input d,clk;
reg q;
always @(clk,d)
begin
if (clk)
q <= d;
end
endmodule
Combinational Ckt through process
module transmission_gate(y,x,en);
output y;
input x,en;
reg y;
always @(x,en)
begin
if (en)
y = x;
else
y = 1'bz;
end
endmodule
Combinational Ckt (Decoder/Encoder)
module bin_decoder(a,z);
input [2:0] a;
output [7:0] z;
reg [7:0] z;
always @(*)
begin
case(a)
3'b000: z = 8'b00000001;
3'b001: z = 8'b00000010;
3'b010: z = 8'b00000100;
3'b011: z = 8'b00001000;
3'b100: z = 8'b00010000;
3'b101: z = 8'b00100000;
3'b110: z = 8'b01000000;
3'b111: z = 8'b10000000;
endcase
end
endmodule
Combinational Ckt (Decoder TB)
module tb_bin_decoder(); always@(posedge clk)
logic clk, reset; begin
logic [2:0] a; {a,z_expected} = testvector[iter];
logic [7:0] z; end
logic [7:0] z_expected; // checking result on falling edge of clock
logic [2:0] iter, error; always @(negedge clk)
logic [11:0] testvector[7:0]; begin
bin_decoder decode1(a,z); if (~reset)
always begin
begin if (z !== z_expected)
clk = 1; #5; begin
clk = 0; #5; $display("Error: input =%b", a);
end $display("Error: output = %b(%b expected)",z,z_expected);
initial error = error + 1;
begin end
$readmemb("test_vector.txt",testvector); if (iter === 3'b111)
iter = 0; begin
error = 0; $display("%d total error",error);
reset = 1; #22; $stop;
reset = 0; end
end iter = iter + 1;
end
end
endmodule
Sequential Circuits (Register)
module register #(parameter width = 4)(q,d,clr,ld,clk);
output reg [width-1:0] q;
input [width-1:0] d;
input clr,ld,clk;
always @(posedge clk)
begin
if (clr)
q <= {width{1'b0}};
else if (ld)
q <= d;
end
endmodule
Sequential Circuits (Shift Register)
module shift_register
#(parameter width = 4)
(q,d,clr,ls,ld,rin,clk) ;
output reg [width-1:0] q;
input [width-1:0] d;
input clr, ls, ld, rin, clk;
always @(posedge clk, posedge clr)
if(clr)
q <= {width{1'b0}};
else if(ld)
q <= d;
else if(ls)
q <= {q[width-2:0],rin};
endmodule
Sequential Circuits (Counter)
module c74163(LdN, ClrN, P, T, Clk, D, Cout, Qout);
input LdN;
input ClrN;
input P;
input T;
input Clk;
input [3:0] D;
output Cout;
output [3:0] Qout;
reg [3:0] Q;
assign Qout = Q;
assign Cout = Q[3] & Q[2] & Q[1] & Q[0] & T;
always @(posedge Clk)
begin
if (~ClrN) Q <= 4'b0000;
else if (~LdN) Q <= D;
else if (P & T) Q <= Q + 1;
end
endmodule
module clk_divider(clk, clk_50);
input clk_50;
output reg clk;
reg [31:0] count;
initial
count = 32'h00000000;
//reg count;
always@(posedge (clk_50))
begin
Clock Divider
if (count >= 32'd50000000)
count <= 32'h00000000;
else
begin
if (count<=32'd25000000)
clk <= 1;
else
clk <= 0;
count <= count + 1;
end
end
endmodule
RAM
module ram #(parameter N =6, M=32)(clk, we, adr, din, dout);
input logic clk, we;
input logic [N-1:0] adr;
input logic [M-1:0] din;
output logic [M-1:0] dout;
logic [M-1:0] mem [2**N-1:0];
always @ (posedge clk)
begin
if(we)
mem[adr] <= din;
end
assign dout = mem[adr];
endmodule
ROM/Combinational Ckt through ROM
module parity_gen(X, Y);
input [3:0] X;
output [4:0] Y;
wire ParityBit;
parameter [0:15] OT = {1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b1, 1'b1,
1'b0, 1'b1, 1'b0, 1'b0, 1'b1};
assign ParityBit = OT[X];
assign Y = {X, ParityBit};
endmodule
ROM/Combinational Ckt through ROM
module parity_gen(X,Y);
input [2:0] X;
output [3:0] Y;
parameter [3:0] OT[7:0] =
{5'b1000,
5'b0001,
5'b0010,
5'b1011,
5'b0100,
5'b1101,
5'b1110,
5'b0111};
assign Y = OT[X];
endmodule
State Machines
4'd9:begin
done = 0; reset = 0; load_l = 0;
shift = 1; add = 0; ns = 4'd10;
end
4'd10:begin
done = 1; reset = 0; load_l = 0;
shift = 0; add = 0; ns = 4'd0;
end
default:begin
done = 0; reset = 0; load_l = 0;
shift = 0; add = 0; ns = 4'd0;
end
endcase
always @(posedge clk)
begin
cs <= ns;
end
endmodule
Multiplication (Controller – State Machine- Verilog Code- style2)
module 4'd1:begin
controller(done,reset,load_l,shift,add,st,m,clk); done = 0; reset = 0; load_l = 1;
output reg done, reset, load_l, shift, add; shift = 0; add = 0; ns = 4'd2;
input st,m,clk; reg [3:0] cs,ns; end
initial 4'd2,4'd4,4'd6,4'd8:begin
begin if (m === 1) begin
done = 0;reset = 0;load_l = 0;shift = 0;add = 0; done = 0; reset = 0; load_l = 0;
end shift = 0; add = 1; ns = cs+4'd1;
always @(cs,st,m) end
begin else begin
case(cs) done = 0; reset = 0; load_l = 0;
4'd0:begin shift = 1; add = 0; ns = cs+4'd2;
if(st === 1) begin end
done = 0; reset = 1; load_l = 0; end
shift = 0; add = 0; ns = 4'd1; 4'd3,4'd5,4'd7,4'd9:begin
end done = 0; reset = 0; load_l = 0;
else begin shift = 1; add = 0; ns = cs+4'd1;
done = 0; reset = 0; load_l = 0; end
shift = 0; add = 0; ns = 4'd0;
end
end
Multiplication (Controller – State Machine- Verilog Code- style2)
4'd10:begin
done = 1; reset = 0; load_l = 0;
shift = 0; add = 0; ns = 4'd0;
end
default:begin
done = 0; reset = 0; load_l = 0;
shift = 0; add = 0; ns = 4'd0;
end
endcase
end
always @(posedge clk)
begin
cs <= ns;
end
Test bench Result for Controller
Multiplication(Top Entity)
module top(qout,st,clk,mplier,mpcand);
output[8:0] qout;
input[3:0] mplier, mpcand;
input st, clk;
wire m,done,reset,load_l,shift,add,st_edge;
edge_detector ed0(st,st_edge,clk);
data_path d0(qout,m,mplier,mpcand,done,reset,load_l,shift,add,clk);
controller c0(done,reset,load_l,shift,add,st_edge,m,clk);
endmodule
Micro-Program
Controller_MicroProgram
Controller_MicroProgram
Controller_MicroProgram
State CS Test NSF NST Reset Load_l Shift Add Done
SO 0000 0 0000 0001 0 0 0 0 0
S1 0001 0 0010 0010 1 0 0 0 0
S2 0010 0 0011 0011 0 1 0 0 0
S3 0011 1 0101 0100 0 0 0 0 0
S4 0100 1 0101 0101 0 0 0 1 0
S5 0101 1 0110 0110 0 0 1 0 0
S6 0110 1 1000 0111 0 0 0 0 0
S7 0111 1 1000 1000 0 0 0 1 0
S8 1000 1 1001 1001 0 0 1 0 0
S9 1001 1 1011 1010 0 0 0 0 0
S10 1010 1 1011 1011 0 0 0 1 0
S11 1011 1 1100 1100 0 0 1 0 0
S12 1100 1 1110 1101 0 0 0 0 0
S13 1101 1 1110 1110 0 0 0 1 0
S14 1110 1 1111 1111 0 0 1 0 0
S15 1111 1 0000 0000 0 0 0 0 1
Controller_MicroProgram_Components
module mux module u_rom(data_out,add);
#(parameter width = 4)(z,sel,in0,in1); output logic[13:0] data_out; input logic[3:0] add;
output [width-1:0] z; always @(*) begin
case(add)
input [width-1:0] in0,in1;
4'b0000: data_out = 14'b0_0000_0001_00000;
input sel;
4'b0001: data_out = 14'b0_0010_0010_10000;
assign z = sel?in1:in0; 4'b0010: data_out = 14'b0_0011_0011_01000;
endmodule 4'b0011: data_out = 14'b0_0101_0100_00000;
module register 4'b0100: data_out = 14'b1_0101_0101_00010;
#(parameter width=9)(q,d,done,clk); 4'b0101: data_out = 14'b1_0110_0110_00100;
output reg [width-1:0] q; 4'b0110: data_out = 14'b1_1000_0000_00000;
input[width-1:0] d; 4'b0111: data_out = 14'b1_1000_1000_00010;
input done,clk; 4'b1000: data_out = 14'b1_1001_1001_00100;
always@(posedge clk) 4'b1001: data_out = 14'b1_1011_1010_00000;
4'b1010: data_out = 14'b1_1011_1011_00010;
begin
4'b1011: data_out = 14'b1_1100_1100_00100;
if(done)
4’b1100: data_out = 14'b1_1110_1101_00000;
q <= d; 4’b1101: data_out = 14'b1_1110_1110_00010;
end 4’b1110: data_out = 14'b1_1111_1111_00100;
endmodule 4’b1110: data_out = 14'b1_0000_0000_00001;
endcase
end
endmodule
Controller_MicroProgram
module Controller_uprog(done,reset,load_l,shift,add,st,m,clk);
output reg done, reset, load_l, shift, add;
input st,m,clk;
logic [3:0] state;
logic [13:0] data_out;
logic z0;
logic [3:0] z1;
initial
begin
state = 4'b0000;
z0 = 0;
z1 = 4'b0000;
end
u_rom rom0(data_out,state);
mux #(1)mux0(z0,data_out[13],st,m);
mux #(4)mux1(z1,z0,data_out[12:9],data_out[8:5]);
register #(4)reg0(state,z1,1'b1,clk);
assign {reset,load_l,shift,add,done} = data_out[4:0];
endmodule
Constant
Constant
• Number of way to declare constant,
Define
Parameter
Localparm
const
Constant data types
`define FETCH 3'h0 always @(State)
`define WRITE 3'h1 begin
`define ADD 3'h2 case(State)
`define SUB 3'h3 WAIT: NextState = LOAD;
`define MULT 3'h4 LOAD: NextState = STORE;
`define DIV 3'h5 STORE: NextState = WAIT;
`define SHIFT 3'h6 endcase
`define NOP 3'h7 end
module controller(output reg read, write, always @(State, instruction)
input wire[3:0] begin
instruction, input wire clock, resetN); read = 0; write = 0;
parameter WAIT = 0, LOAD =1, STORE = 2; if (State == LOAD && instruction == `FETCH)
reg [1:0] State, NextState; read = 1;
else if (State == STORE && instruction ==
always @(posedge clock, negedge resetN) `WRITE)
begin write = 1;
if(!resetN) State <= WAIT; end
else State <= NextState; endmodule
end
User-Defined and Enumerated Data
Type
• User defined and Enumerated data type are
feature specific to system Verilog.
• Can be use for both digital circuit synthesis
and verification.
• Help to make code self documented and
easier to read.
• May reduce code to fewer lines.
User-Defined Data Type
• Local User-Defined Type
module alu (….);
typedef bit [3:0] nibble;
nibble opA, opB; //Variables of the nibble data type
nibble [7:0] data; // a 32-bit vector made from 8 nibble types
…..
…..
endmodule
User-Defined Data Type
• External User-Defined Type
`ifdef TWO_STATE
typedef bit dtype_t; //external typedef
`else
typedef logic dtype_t;
`endif
initial wait_for_1(signal);