verilog (베릴로그)

created : 2020-06-25T11:46:51+00:00
modified : 2020-07-01T11:53:18+00:00
verilog

개요

출처

port, reg, wire, parameter declaration submodule instance primitive gate always, initial assign, funciton, task declaration function, task definition

endmodule


### Hello World

```verilog
module main;
  initial
  begin
    $display("Hello World");
    $finish;
  end
endmodule

D flip-flop Code

module d_ff (d, clk, q, q_bar);
input d, clk;
output q, q_bar;
wire d, clk;
reg q, q_bar;

always @ (posedge clk)

begin
  q <= d;
  q_bar <= !d;
end

endmodule

Data Type (English)

Opertators

Operator Type Operator Symbol Operation Performed
Arithmetic * Multiply
  / Division
  + Add
  - Subtract
  % Modulus
  + Unary plus
  - Unary minus
Logical ! Logical negation
  && Logical and
  || Logical or
  > Greater than
  < Less than
  >= Greater than or equal
  <= Less than or equal
Equality == Equality
  != inequality
Reduction ~ Bitwize negation
  ~& nand
  | or
  ~| nor
  ^ xor
  ^~ xnor
  ~^ xnor
Shift >> Right shift
  << Left shift
Concatenation {} Concatenation
Conditional ? conditional

Control Statements

If-else

// begin and end act like curly braces in C/C++.
if (enable == 1'b1) begin
  data = 10;         // Decimal assigned
  address = 16'hDEAD; // Hexadecimal
  wr_enable = 1'b1; // Binary
end else begin
  data = 32'b0;
  wr_enable = 1'b0;
  address = address +1;
end

Case

case(address)
  0: $display ("It is 11:40PM");
  1: $display ("I am feeling sleepy");
  2: $display ("Let me skip this tutorial");
  default: $display ("Need to complete");
endcase

while

while (free_time) begin
  $display ("Continue with webpage development");
end

Counter example

module counter (clk, rst, enable, count);
input clk, rst, enabl;
output [3:0] count;
reg [3:0] count;

always @ (posedge clk or posedge rst)
if (rst) begin
  count <= 0;
end else begin: COUNT
  while (enable) begin
    count <= count + 1;
    disable COUNT;
  end
end

endmodule

For loop

for (i = 0; i < 15; i = i + 1) begin
  $display ("Current value of i is %d", i);
end

Repeat

repeat (16) begin
  $display ("Current value of i is %d", i);
  i = i + 1;
end

Initial Blocks

initial begin
  clk = 0;
  reset = 0;
  req_0 = 0;
  req_1 = 0;
end

Always Blocks

always @ (a or b or sel)
begin
  y = 0;
  if (sel == 0) begin
    y = a;
  end else begin
    y = b;
  end
end
always begin
  #5 clk = ~clk;
end

Assign Statement

assign out = (enable) ? data : 1'bz;
assign out = data;

Task and Function

function parity;
input [31:0] data;
integer i;
begin
  parity = 0;
  for (i = 0; i< 32; i = i + 1) begin
    parity = parity ^ data[i];
  end
end
endfunction
 
module parity (d, p);
  output reg p;
  input [31:0] d;

  function parity;
    input [31:0] data;
    integer i;

    begin
      parity = 0;
      for (i = 0; i< 32; i = i + 1) begin
        parity = parity ^ data[i];
      end
    end
  endfunction

  always @ (d)
    p = parity(d);

endmodule

Task Benches

module arbiter (
clock,
reset,
req_0,
req_1,
gnt_0,
gnt_1
);

input clock, reset, req_0, req_1;
output gnt_0, gnt_1;

reg gnt_0, gnt_1;

always @ (posedge clock or posedge reset)

if (reset) begin
  gnt_0 <= 0;
  gnt_1 <= 0;
end else if (req_0) begin
  gnt_0 <= 1;
  gnt_1 <= 0;
end else if (req_1) begin
  gnt_0 <= 0;
  gnt_1 <= 1;
end

endmodule
// Testbench Code Goes here
module arbiter_tb;

reg clock, reset, req0, req1;
wire gnt0, gnt1;

initial begin
  $monitor ("req0=%b,req1=%b,gnt0=%b,gnt1=%b", req0, req1, gnt0, gnt1);
  clock = 0;
  reset = 0;
  req0 = 0;
  req1 = 0;
  #5 reset = 1;
  #15 reset = 0;
  #10 req0 = 1;
  #10 req0 = 0;
  #10 req1 = 1;
  #10 req1 = 0;
  #10 {req0, req1} = 2'b11;
  #10 {req0, req1} = 2'b00;
  #10 $finish;
end

always begin
  #5 clock = !clock;
end

arbiter U0 (
.clock (clock),
.reset (reset),
.req_0 (req0),
.req_1 (req1),
.gnt_0 (gnt0),
.gnt_1 (gnt1)
);


endmodule

Counter Design

//-----
// Function : This is a 4 bit up-counter with
// Synchronous active high reset and
// with active high enable signal
//-----
module first_counter (
clock,
reset,
enable,
counter_out
);

input clock;
input reset;
input enable;

output [3:0] counter_out;

wire clock;
wire reset;
wire enable;

reg [3:0] counter_out;

always @ (posedge clock)
begin: COUNTER // Block Name
  if (reset == 1'b1) begin
    counter_out <= # 4'b0000;
  end
  
  else if (enable == 1'b1) begin
    counter_out <= #1 counter_out + 1;
  end
end

endmodule
`include "first_counter.v"
module first_counter_tb();
// Declare inputs as regs and outputs as wires
reg clock, reset, enable;
wire [3:0] counter_out;

// Initialize all variables

initial begin
  $display ("time\t clk reset enable counter");
  $monitor ("%g\t %b %b %b %b");
    $time, clock, reset, enable, counter_out;
    
  clock = 1;
  reset = 0;
  enable = 0;
  #5 reset = 1;
  #10 reset = 0;
  #10 enable = 1;
  #100 enable = 0;
  #5 $finish;
end

always begin
  #5 clock = ~clock;
end

first_counter U_counter (
clock,
reset,
enable,
counter_out
);

endmoudle

Comments

/* This is a
  Multi line comment
  example */
module addbit (
a,
b,
ci,
sum,
co);

input a;
input b;
input ci;
output sum;
output co;
wire a;
wire b;
wire ci;
wire sum;
wire co;

endmodule

Numbers in Verilog

Integer Number

Integer Stored as
1 00000000000000000000000000000001
8’hAA 10101010
6’b10_0011 100011
‘hF 00000000000000000000000000001111

Real Numbers

Modules

Ports

module addbit(
a,
b,
ci, sum,
co
);
input a;
input b;
input ci;
output sum;
output co;

wire a;
wire b;
wire ci;
wire sum;
wire co;

assign {co, sum} = a + b + ci;

endmodule
Modules connected by port order (implicit)
module adder_implicit (
result,
carry,
r1,
r2,
ci
);

input [3:0] r1;
input [3:0] r2;
input ci;

output [3:0] result;
ouput carry;

wire [3:0] r1;
wire [3:0] r2;
wire ci;
wire [3:0] result;
wire crarry;

wire c1;
wire c2;
wire c3;

addbit u0 (
r1[0],
r2[0],
ci ,
result[0],
c1
);

addbit u1 (
r1[1] ,
r2[1] ,
c1,
result[1],
c2
);

addbit u2 (
r1[2] ,
r2[2], 
c2,
result[2],
c3
);

addbit u3(
r1[3],
r2[3],
c3,
result[3],
carry
);

endmodule
Modules connected by name
module adder_explicit (
result,
carry,
r1,
r2,
ci
);

input [3:0] r1;
input [3:0] r2;
input ci;

ouput [3:0] result;
ouput carry;

wire [3:0] r1;
wire [3:0] r2;
wire ci;
wire [3:0] result;
wire carry;

wire c1;
wire c2;
wire c3;

addbit u0 (
.a (r1[0]),
.b (r2[0]),
.ci (ci),
.sum (result[0]),
.sum (result[0]),
co (c1)
);

addbit u1 (
.a (r1[1]),
.b (r2[1]),
.ci (c1),
.sum (result[1]),
.co (c2)
);

addbit u2 (
.a (r1[2]),
.b (r2[2]),
.ci (c2),
.sum (result[2]),
.co (3)
);

addbit u3 (
.a (r1[3]),
.b (r2[3]),
.ci (c3),
.sum (result[3]),
.co (carry)
);

endmodule
Instantiating a module
module parity (
a,
b,
c,
d,
y
);

input a;
input b;
input c;
input d;

ouput y;

wire a;
wire b;
wire c;
wire d;
wire y;

wire out_0;
wire out_1;

xor u0 (out_0, a, b);
xor u1 (out_1, c, d);

xor u2 (y, out_0, out_1);

endmodule

Port Connection Rules

Example - Implicit Unconnected Port
module implicit();
reg clk, d, rst, pre;
wire q;

dff u0 (q,, clk, d, rst, pre);

end module

module dff (q, q_bar, clk, d, rst, pre);
input clk, d, rst, pre;
output q, q_bar;
reg q;

assign a_bar = ~q;

always @ (posedge clk)

if 9rst ==1'b1) gegin
  q <= 0;
end else if (pre == 1'b1) begin
  q <= 1;
end else being
  q <= d;
end

endmodule
Example - Explicit Unconnected Port
module explicit();
reg clk, d, rst, pre;
wire q;

dff u0 (
.q (q),
.d (d),
.clk (clk),
.q_bar (),
.rst (rst),
.pre (pre)
);

endmodule


module dff (q, q_bar, clk, d, rst, pre);
input clk, d, rst, pe;
output q, q-bar;
reg q;

assign q_bar = ~q;

always @ (posedge clk)

if (rst == 1'b1) begin
  q <= 0;
end else if (pre == 1'b1) begin
  q <= 1;
end else begin
  q <= d;
end

endmodule

Hierarchical Identifiers

`include "addbit.v"
module adder_hier (
result,
carry,
r1,
r2,
ci
);

input [3:0] r1;
input [3:0] r2;
input ci;

output [3:0] result;
output carry;

wire [3:0] r1;
wire [3:0] r2;
wire ci;
wire [3:0] result;
wire carry;

wire c1;
wire c2;
wire c3;


addbit u0 (r1[0], r2[0],ci,result[0],c1);
addbit u1 (r1[1], r2[1],c1,result[1],c2);
addbit u2 (r1[2], r2[2],c2,result[2],c3);
addbit u3 (r1[3], r2[3],c3,result[3],carry);

endmodule

module tb();

reg [3:0] r1, r2;
reg ci;
wire [3:0] result;
wire carry;

initial begin
  r1 = 0;
  r2 = 0;
  ci = 0;
  #10 r1 = 10;
  #10 r2 = 2;
  #10 ci = 1;
  #10 $display("+-----------------+");
  $finish;
end


adder_hier U (result, carry, r1, r2, ci);

initial begin
  $display("+---------------+");
  $display("|r1|r2|ci|u0.sum|u1.sum|u2.sum|u3.sum|");
  $display("+---------------+");
  $monitoer("|%h|%h|%h|%h|h|%h|%h|",
    r1, r2, ci, tb.U.u0.sum, tb.U.u1.sum, tb.U.u2.sum, tb.U.u3.sum);
end

endmodule

Data Types

Types of Nets
Net Data Type Functionality 간략 번역
wire, tri Interconnecting wire - nospecial resolution function 상호 연결
wor, trior Wired outputs Or together (models ECL) 연결된 것들끼리 or한 값
wand, triand Wired outputs And together (models open-collector) 연결된 것들끼리 and 한 값
tri0, tri1 Net pulls-down or pulls-up when not driven tri와 동일한데, z 일때 0이거나 1
supply0, supply1 Net has a constant logic 0 or logic 1 (supply strenth) 상수 ground, vdd
trireg Retains last value, when driven by z(tristate). z일때 예전 값을 기억
Example - wor
module test_wor();
wor a;
reg b, c;
assign a = b;
assign a = c;

initial begin
  $monitor("%g a = %b b = %b c = %b", $time, a, b, c);
  #1 b = 0;
  #1 c = 0;
  #1 b = 1;
  #1 b = 0;
  #1 c = 1;
  #1 b = 1;
  #1 b = 0;
  #1 $finish;
end

endmoudle
Example - tri
module test_tri();

tri a;
reg b, c;


assign a = (b) ? c : 1'bz;

initial begin
  $monitor("%g a = %b b = %b c= %b", $time, a, b, c);
  b = 0;
  c = 0;
  #1 b = 1;
  #1 b = 0;
  #1 c = 1;
  #1 b = 1;
  #1 b = 0;
  #1 $finish;
end

endmodule
Example - trireg
module test_trireg();
trireg a;
reg b, c;

assign a = (b) ? c : 1'bz;

initial begin
  $monitor("%g a = %b b = %b c= %b", $time, a, b, c);
  b = 0;
  c = 0;
  #1 b = 1;
  #1 b = 0;
  #1 c = 1;
  #1 b = 1;
  #1 b = 0;
  #1 $finish;
end

endmodule

Register Data Types

Data types Functionality
reg Unsigned variable
integer Signed variable - 32 bits
time Unsigned integer - 64 bits
real Double precision floating point variable

Strings

Character Description
\n New line character
\t Tab character
\ Backslash () character
" Double quote (“) Character
\ddd A character specified in 1-3 octal digits (0 <= d <= 7)
%% Percent (%) character

Gate Primitives

module gates();

wire out0;
wire out1;
wire out2;
reg in1, in2, in3, in4;

not U1(out0, in1);
and U2(out1, in1, in2, in3, in4);
xor U3(out2, in1, in2, in3);

initial begin
  $monitor("in1 = %b in2= %b in3=%b out0=%b out1=%b out2=%b",
    in1, in2, in3, in4, out0, out1, out2);
  in1 = 0;
  in2 = 0;
  in3 = 0;
  in4 = 0;
  
  #1 in1 = 1;
  #1 in2 = 1;
  #1 in3 = 1;
  #1 in4 = 1;
  #1 $finish;
end

endmodule

Transmission Gate Primitives

module transmission_gates();

reg data_enable_low, in;
wire data_bus, out1, out2;

bufif0 u1(data_bus, in, data_enable_low);
buf U2(out1, in);
not U3(out2, in);

initial begin
  $monitor(
    "@%g in = %b data_enable_low=%b out1=%b out2=%b data_bus=%b",
    $time, in, data_enable_low, out1, out2, data_bus);
  data_enable_low = 0;
  in = 0;
  #4 data_enable_low = 1;
  #8 $finish;
end

always #2 in = ~in;

endmodule

Switch Primitives

module switch_primitives();

wire net1, net2, net3;
wire n4, net5, net6;

tranif0 my_gate1 (net1, net2, net3);
rtranif1 my_gate2 (net4, net5, net6);

endmodule

Logic Values and signal Strengths

Logic Value Description
0 zero, low, false
1 one, high, true
z or Z high impedance, floating
x or X unknown, uninitialized, contention

Verilog Strength Levels

Strengtth Level Specification Keyword
7 Supply Drive supply0 supply1
6 Strong Pull strong0 strong1
5 Pull Drive pull0 pull1
4 Large Capacitance large
3 Weak Drive weak0 weak1
2 Medium Capacitance medium
1 Small Capacitance small
0 Hi Impedance highz0 highz1

User Defined Primitives

Syntax

primitive udp_syntax (
a,
b,
c,
d
);
output a;
input b,c,d;

endprimitive

UDP ports rules

Body

primitive udp_body (
a,
b,
c
);

ouput a;
input b, c;

// A = B | C;
table
  ? 1 : 1;
  1 ? : 1;
  0 0 : 0;
endtable

endprimitive
`include "udp_body.v"
module udp_body_tb();

reg b,c;
wire a;

udp_body udp (a, b, c);

initial begin
  $monitor(" B = %b C = %b A = %b", b, c, a);
  b = 0;
  c = 0;
  #1 b = 1;
  #1 b = 0;
  #1 c = 1;
  #1 b = 1'bx;
  #1 c = 0;
  #1 b = 1;
  #1 c = 1'bx;
  #1 b = 0;
  #1 $finish;
end

endmodule

Symbols

Symbol interpretation Explanation
? 0 or 1 or X ? means the variable can be 0 or 1 or x
b 0 or 1 Same as ?, but x is not included
f (10) Falling edge on an input
r (01) Rising edge on an input
p (01) or (0x) or (x1) or (1z0 or (z1)) Rising edge including x and z
n (10) or (1x) or (x0) or (0z) or (z0) Falling edge including x and z
* (??) All transitions
- No change No Change

System Task and Function

실습

parameter MAX_SIZE = 128;

input wire [31:0] d; input wire is_insert; input wire enable; input wire clock; input wire reset;

output reg signed [31:0] ret;

integer node[MAX_SIZE - 1:0]; integer count; integer tmp1, tmp2, tmp3; integer i;

initial begin for (i = 0; i < MAX_SIZE; i = i + 1) begin node[i] = 0; end $display(“time | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 “); $monitor(“%g | %d | %d | %d | %d | %d | %d | %d | %d”, $time, node[1], node[2], node[3], node[4], node[5], node[6], node[7], node[8]); count = 0; end

always @ (posedge clock) begin if (enable) begin /* insert */ if (is_insert) begin count = count + 1; node[count] = d;

  tmp1 = count;
  while (tmp1 > 1 && node[tmp1 / 2] < node[tmp1]) begin
    tmp2 = node [tmp1/2];
    node [tmp1/2] = node[tmp1];
    node [tmp1] = tmp2;

    tmp1 = tmp1 / 2;
  end
end
/* pop */
else begin
  ret = node[1];
  
  node[1] = node[count];
  node[count] = node[1];
  count = count - 1;

  tmp1 = 1;
  tmp2 = tmp1 * 2;
  if (tmp2 + 1 <= count) begin
  tmp2 = (node[tmp2] > node[tmp2 + 1]) ? tmp2 : tmp2 + 1;
  end

  while (tmp2 <= count && node[tmp1] < node[tmp2]) begin
    tmp3 = node[tmp1];
    node[tmp1] = node[tmp2];
    node[tmp2] = tmp3;

    tmp1 = tmp2;
    tmp2 = tmp2 * 2;

    if (tmp2 + 1 <= count) begin
      tmp2 = (node[tmp2] > node[tmp2 +1]) ? tmp2 : tmp2 + 1;
    end
  end

  node[count + 1] = 0; /* to display */
end   end end

endmodule


```verilog
/* test.v */
`include "heap.v" // to fix syntax highlight`

module heap_test();

reg clock, reset, enable, is_insert;
integer data;
wire [31:0] ret;

initial begin
  clock = 0;
  reset = 0;
  enable = 1;
  is_insert = 1;
  data = 0;
  #5 data = 5;
  #10 data = 10;
  #10 data = 7;
  #10 is_insert = 0;
  #5 $finish;
end

always begin 
  #5 clock = ~clock;
end

heap U(data, is_insert, ret, enable, clock, reset);

endmodule