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;
endendmodule
Data Type (English)
Hardware does have two kinds of drivers.
A driver is a data type which can drive a load. Basically, in a physical circuit, a driver would be anything that electrons can move through/into.
Driver that can store a value (example: flip-flop).
Driver that can not store value, but connects two points (example: wire).
The first type of driver is called a reg in Verilog (short for “register”). The Second data type is called a wire (for… well, “wire”). You can refer to tidbits section to understand it better.
Data Type (한국어)
하드웨어는 2가지 종류의 드라이버가 있으며, 기본적으로 물리적인 회로이며, 드라이버는 전자가 들어오거나 나갈수 있는 무엇이든 될 수 있다.
드라이버는 값을 저장할 수 있다. (예를 들어 플립플롯) -> reg(register의 준말)
드라이버는 값을 저장하지 못하는 대신, 두 지점을 연결 시킬수 있다. (예를 들어 wire) -> wire
Opertators
Operator Type
Operator Symbol
Operation Performed
Arithmetic
*
Multiply
/
Division
+
Add
-
Subtract
%
Modulus
+
Unary plus
-
Unary minus
Logical
!
Logical negation
&&
Logical and
`
>
Greater than
<
Less than
>=
Greater than or equal
<=
Less than or equal
Equality
==
Equality
!=
inequality
Reduction
~
Bitwize negation
~&
nand
`
`
`~
`
^
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
endelsebegin 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 orposedge rst)
if (rst) begin count <=0;
endelsebegin: COUNT
while (enable) begin count <= count +1;
disable COUNT;
endendendmodule
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
initialbegin 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;
endelsebegin y = b;
endend
?? 이건 근데 mux랑 똑같은거 아닌가? mux 만들어 놓고, initial block 에서 wire 연결 해두면 안되는 건가?
always block의 쓰임을 잘 모르겠네, 어떻게 되는 거지?
=> 주변에 있는 다른 분께 물어보니 같은 동작을 하는건 맞고, 실제 기판으로 나오는게 똑같으면 어떻게 코딩하든 상관 없다고 하심.
alwaysbegin #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];
endendendfunction
흠… for을 도는건 delay 없이 도는 거니 위에 내용은 실제로 컴파일 되면 data의 모든 bit를 한번에 xor하는 결과가 나오는건가?
그래서 한번 만들고 compile 해봤다.
module parity (d, p);
outputreg 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];
endendendfunctionalways @ (d)
p = parity(d);
endmodule
처음에 initial block 에서 monitor로 변수 값 바뀔때 tracking 해주고, req0 = 0, req1 = 0 이 설정 되고, gnt는 설정이 안되서 0, 0, x, x 가 나오고 나머지는 다 delay 걸려서 실행 안되고 있고, arbiter 호출해준다.
5 delays 뒤에 reset 이 1 이 되면서 gnt_0, gnt_1 이 되면서 0, 0, 0, 0 이 출력
10 delays 뒤에 req0 가 1이 되면서, 1, 0, 0, 0
그러면서 1, 0, 1, 0
그 뒤 req0 이 0 되면서 0, 0, 1 , 0
req1 이 1 이 되면서 0, 1, 1, 0
그 직후 0, 1, 0, 1
0, 0, 0, 1
1, 1, 0, 1
1, 1, 1, 0
0, 0, 1, 0
순으으로 나오게 된다.
처음에는 reset 이 0 으로 바뀌는걸 못봐서 한참 삽질했다.
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;
endelseif (enable ==1'b1) begin counter_out <= #1 counter_out +1;
endendendmodule
Nets - Present structural connections between components.
Registers - represent variables used to store data.
Every signal has a data type associated with it:
Explicitly declared with a declaration in your Verilog code.
Implicitly declared with no declaration when used to connect structural building blocks in your code. Implicit declaration is always a net type “wire” and is one bit wide.
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;
initialbegin $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;
endendmodule
Example - trireg
module test_trireg();
trireg a;
reg b, c;
assign a = (b) ? c :1'bz;
initialbegin $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;
endendmodule
Register Data Types
Registers store the last value assigned to them until another assignment statement changes their value. (새로운 할당 전까지 그 값이 변하지 않고 저장한다.)
Registers represent data storage constructs. (register는 data구성을 표현한다?)
You can create regs arrays called memories. (memories 라고도 불리는 regs array를 만들수도 있다.)
register data types are used as variables in procedural blocks. (register의 data type은 procedural block들 에서 변수로써 쓰인다.)
A register data type is required if a signal is assigned a value within a procedural block (procedural block에서 변수의 값을 할당하려면 register의 data type이 필요하다.)
Procedural blocks begin with keyword initial and always. (Procedural block 은 initial 과 always 키워드로 시작한다.)
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)
primitive udp_syntax (
a,
b,
c,
d
);
output a;
input b,c,d;
endprimitive
UDP ports rules
An UDP can contain only one output and up to 10 inputs.
Output port should be the first port followed by one or more input ports.
All UDP ports are scalar, i.e. Vector ports are not allowed.
UDPs can not have bidirectional ports.
The output terminal of a sequetial UDP requires an additional declaration as type reg.
It is illegal to declare a reg for the output terminal of a combinational UDP
Body
primitive udp_body (
a,
b,
c
);
ouput a;
input b, c;
// A = B | C;
table?1:1;
1?:1;
00:0;
endtableendprimitive
`include"udp_body.v"module udp_body_tb();
reg b,c;
wire a;
udp_body udp (a, b, c);
initialbegin $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;
endendmodule
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
$display("format_string", par_1, par_2, ...);
$strobe("format_string", par_1, par2, ...);
$monitor("format_string", par_1, par_2, ...);
$displayb (as above but defaults to binary..);
$strobeh (as above but defaults to hex..);
$monitoro (as above but defaults to octal..);
$time, $stime, $realtime : the current simulation time as a 64-bit integer, a 32-bit integer, and a real number
$reset, $stop, $finish : $reset resets the simulation back to time 0; $stop halts the simulator and puts it in interactive mode where the user can enter commands; $finish exits the simulator back to the operating system.
$scope, $showscope : $scope(hierarchy_name) sets the current hierarchical scope to hierarchy_name. $showscopes(n) lists all modules, tasks and block names in (and below, if n is set to 1) the current scope.
$random generates a random integer every tie it is called. If the sequence is to be repeatable, teh first time one invokes random giving it a numerical argument (a seed). Otherwise the seed is derived from the computer clock.
$dumpfile, $dumpvar, $dumpon, $dumpoff, $dumpall
$dumpfile("filename.vcd")
$dumpvar : dumps all variables in the design.
$dumpvar(1, top) : dumps all the varaibles in module top and below, but not modules instantiated in top.
$dumpvar(2, top) : dumps all the variables in module top and 1 level below.
$dumpvar(n, top) : dumps all the variables in module top and n-1 levels below.
$dumpvar(0, top) : dumps all the variables in module top and all level below.
$dumpon : initiates the dump.
$dumpoff : stop dumping.
$fopen, $fdisplay, $fstrobe, $fmonitor and $fwrite
$fopen opens an output file and gives the open file a handle for use by the other commands.
$fclose : closes the file and lests other programs access it.
$fdisplay and $fwrite write formatted data to a file whenever they are executed. They are the same except $fdisplay inserts a new line after every execution and $write does not.
$disrobe also writes to file when executed, but its waits until all other operations in the time step are complete before writing. Thus initial #1 a = 1; b= 0; $fstrobe(hand1, a,b); b=1; will write write 1 1 for a and b.
$fmonitor writes to a file whenever any of tis arguments changes.