Verilog小总结
Verilog小总结
基础
assign
assign作为一个组合逻辑常用的语句,可认为是将电线连接起来,当然它能做的不仅仅是将一个输入直接输出,它能把输入信号进行逻辑运算后再输出。当assign左右两边位宽不相等时,将自动进行零扩展或截断以匹配左边的位宽。
eg:
module top_module (
input a,
input b,
input c,
input d,
output out,
output out_n );
wire w1, w2; // Declare two wires (named w1 and w2)
assign w1 = a&b; // First AND gate
assign w2 = c&d; // Second AND gate
assign out = w1|w2; // OR gate: Feeds both 'out' and the NOT gate
assign out_n = ~out; // NOT gate
endmodule
Vectors
声明向量
type [upper:lower] vector_name;
type
指定向量的数据类型,通常是wire
或reg
。如果要声明输入或输出端口,则该类型还可以另外包括端口类型(例如,input
或output
)
wire [7:0] w; // 8-bit wire
reg [4:1] x; // 4-bit reg
output reg [0:0] y; // 1-bit reg that is also an output port (this is still a vector)
input wire [3:-2] z; // 6-bit wire input (negative ranges are allowed)
output [3:0] a; // 4-bit output wire. Type is 'wire' unless specified otherwise.
wire [0:7] b; // 8-bit wire where b[0] is the most-significant bit.
部分选择
使用向量名称访问整个向量,但是当assign左右两边位宽不相等时,将自动进行零扩展或截断以匹配左边的位宽。
使用vector_name[up:low]
的形式获取部分向量,注意方向应与定义的一致,如定义了一个a[3:0]
,那么不能反向获取a[0:3]
。
矢量运算
- 位运算
符号 | 功能 |
---|---|
~ |
按位取反 |
& |
按位与 |
| |
按位或 |
^ |
按位异或 |
^~ |
按位同或 |
注意:除了~
外均为双目运算符;若进行双目运算时左右两个操作数位数不一样,位数少的将在相应的高位用0扩展。
- 逻辑运算
逻辑运算会将整个向量视为布尔值(真=非零,假=零),并且产生1位输出,如有input [2:0] a
和input [2:0] b
那么他们的逻辑或运算即为assign out = a || b;
,a和b均视为一个布尔值。
- 缩减运算
对一个向量的每一位进行位操作,如有a[2:0]
,那么b=&a
相当于b=(a[0]&a[1])&a[2]
矢量串联
串联运算符{a,b,c}
用来将小向量串联起来创建一个更大的向量。串联中不允许使用不定尺寸的常量。如{1,2,3}
是非法的,因为Verilog不知道他们的位宽。
还可以用{n{vec}}
的形式来复制向量,如{6{a}}
和{a,a,a,a,a,a}
是一样的,同时注意两组大括号都是必须的,即{1'b1,6{1'b0}}
是非法的,因为其中的6{1'b0}
少了一组大括号,正确的写法是{1'b1,{6{1'b0}}}
。这其实比较好理解,串联运算符{a,b,c}
中的abc均为一个向量,{n{vec}}
也代表了一个向量,因此{a,b,{n{c}}}
也是一个向量
模块
mod_name instance_name (signal_name1,signal_name2,signal_name3);//by position
mod_name instance_name (.port_name1(signal_name1),.port_name2(signal_name2),.port_name3(signal_name3));//by name
可以理解为一个函数,注意括号内的是外部连接到模块的信号。
always块
组合逻辑
使用always @(*)
可以类似于assign
的效果,当右方有变量发生改变时,左边输出随之立即改变。assign out1 = a & b | c ^ d;
和always @(*) out2 = a & b | c ^ d;
是一样的
时序逻辑
- 同步与异步复位
//同步复位
always @(posedge clk) begin
if(reset == 1) begin
//reset
end
end
//异步复位
always @(posedge clk,posedge areset) begin
if(areset == 1) begin
//reset
end
end
- 阻塞赋值非阻塞赋值
一般来说,我们在组合逻辑的always块中使用阻塞赋值(x = y;
);在时序逻辑的always块中使用非阻塞赋值(x <= y;
)
case
always @(*) begin //这是一个组合逻辑
case (in)
1'b1: begin
out = 1'b1;
end
1'b0: out = 1'b0;
default: out = 1'bx;
endcase //一定记得写endcase
end
注意一定要写endcase。
另外还有case的好兄弟casez,他可以匹配形如4'bzzz1
的向量,z表示无关位。
eg:优先编码器
module top_module (
input [7:0] in,
output reg [2:0] pos );
always @(*) begin
casez (in)
8'bzzzzzzz1 : pos = 0;
8'bzzzzzz1z : pos = 1;
8'bzzzzz1zz : pos = 2;
8'bzzzz1zzz : pos = 3;
8'bzzz1zzzz : pos = 4;
8'bzz1zzzzz : pos = 5;
8'bz1zzzzzz : pos = 6;
8'b1zzzzzzz : pos = 7;
default: pos =0;
endcase
end
endmodule
for
组合for循环
与C语言的用法类似。
eg:人口计数器
module top_module (
input [254:0] in,
output reg [7:0] out
);
always @(*) begin //组合逻辑always块
out = 0; //一定要初始化为0
for (int i=0;i<255;i++)
out = out + in[i];
end
endmodule
生成for循环
当对矢量中多个位进行重复操作时,或进行多个模块的实例化引用的重复操作时,可使用生成块简化程序。写法如下
genvar i;//只能用genvar作为循环变量
generate
for (i=1;i<99;i=i+1) begin: add_loop//这个名字是必须的
mod_name instance_name(......);//括号里写由i推出的信号
end
endgenerate
eg:Bcdadd100
module top_module(
input [399:0] a, b,
input cin,
output cout,
output [399:0] sum );
genvar i;
wire [99:0]cout1;
bcd_fadd mod1(a[3:0],b[3:0],cin,cout1[0],sum[3:0]);
generate
for (i=1;i<99;i=i+1) begin: addloop
bcd_fadd mod2(a[(4*i+3):(4*i)],b[(4*i+3):(4*i)],cout1[i-1],cout1[i],sum[(4*i+3):(4*i)]);
end
endgenerate
bcd_fadd mod3(a[399:396],b[399:396],cout1[98],cout,sum[399:396]);
endmodule
状态机写法
Moore型
三段式写法:使用一个state用于存当前状态,使用一个next_state用于存下一状态。第一段用于写状态转换逻辑,第二段用于状态转移,第三段用于输出。
reg state, next_state;
//第一段:
always @(*) begin //一个组合逻辑always块,用于写状态转换逻辑,当in改变时,next_state将立即改变。
case(state)
A: next_state = f(in)//关于in的函数
B: next_state = f(in)
...
endcase
end
//第二段(异步):
always @(posedge clk, posedge areset) begin
if(areset == 1) begin
state <= 0;//reset
end
else state <= next_state;
end
//第二段(同步):
always @(posedge clk) begin
if(reset == 1) begin
state <= 0;//reset
end
else state <= next_state;
end
//第三段(assign法)
assign out = (state == ...);//判断state
//第三段(组合逻辑always块法)
always@(*) begin
case (state)
A: {out3,out2,out1} = 3'b111;
B: {out3,out2,out1} = 3'b110;//对每一种状态输出
...
endcase
end
Mealy型
仅仅第三段发生了改变,可使用{state,in}
来做输出判断。
//第三段(assign法)
assign out = f(state,in);//关于state和in的函数
//第三段(组合逻辑always块法)
always@(*) begin
case ({state,in})
4'b0000: {out3,out2,out1} = 3'b111;
4'b0001: {out3,out2,out1} = 3'b110;//对每一种state与in做输出
...
end
(希望明天P1能过呜呜呜
Verilog小总结的更多相关文章
- Windows上使用iverilog+gtkwave仿真
主要参考了: https://www.cnblogs.com/lsgxeva/p/8280662.html 谢谢! ------------------------------------------ ...
- verilog学习笔记(1)_两个小module
第一个小module-ex_module module ex_module( input wire sclk,//声明模块的时候input变量一定是wire变量 input wire rst_n,// ...
- Verilog中关于wire使用的一些小知识
1.Verilog中如果wire连接到常量,而常量没有说明他的位宽,那么将会默认为32位 如: input [:] x ; wire [:] a; assign a = + x; 上述代码在综合的时候 ...
- verilog 实用的小技巧
(之后还会持续的更新) 移位操作的实现: verilog有一种非常简单的移位操作实例如下: reg [3:0] source; reg out; {out,source[3:0]}={source[3 ...
- verilog学习笔记(3)_task/case小例子及其tb
module ex_case `timescale lns/1ns module ex_case( input wire rst_n, input wire sclk, output reg [7:0 ...
- verilog学习笔记(2)_一个小module及其tb
module-ex_cnt module ex_cnt( input wire sclk, input wire rst_n, output wire[9:0] cnt ); reg [9:0] cn ...
- Verilog HDL小练习
5s内15Hz4个LED闪烁,再两秒熄灭,循环往复. 引入en,可以使得4个LED灯全亮,以及恢复周期变化. module led(clk_27MHZ, en, led1, led2, led3, l ...
- verilog $fopen 函数的小缺陷
system task $fopen 的argument 为1.文件名字(可以包含具体的文件路径但是注意用)2.打开方式比如"r"."w"."a&qu ...
- system verilog中的类型转换(type casting)、位宽转换(size casting)和符号转换(sign casting)
类型转换 verilog中,任何类型的任何数值都用来给任何类型赋值.verilog使用赋值语句自动将一种类型的数值转换为另一种类型. 例如,当一个wire类型赋值给一个reg类型的变量时,wire类型 ...
随机推荐
- 嵌入式arm-linux mips-linux 交叉编译GDB,结合vscode图形化调试使用,coredump定位段错误
第一部分:使用GDB GDB源码下载路径:http://ftp.gnu.org/gnu/gdb/ 遇到的主要难点: 选择合适的GDB源码版本 我的mips-linux交叉编译器不支持C++11特性,所 ...
- Focal loss论文解析
Focal loss是目标检测领域的一篇十分经典的论文,它通过改造损失函数提升了一阶段目标检测的性能,背后关于类别不平衡的学习的思想值得我们深入地去探索和学习.正负样本失衡不仅仅在目标检测算法中会出现 ...
- C/C++ 条件编译
条件编译就是指有条件的编译,即根据条件去编译代码,在编译阶段时就对代码做出取舍,有的编译,有的不编译,这样比写成一个个判断函数更有效率,比如工程代码大部分的地方都类似,只有个别语句因为使用的硬件版本不 ...
- Java之ConcurrentHashMap源码解析
ConcurrentHashMap源码解析 目录 ConcurrentHashMap源码解析 jdk8之前的实现原理 jdk8的实现原理 变量解释 初始化 初始化table put操作 hash算法 ...
- 详解gitignore的使用方法,让你尽情使用git add .
大家好,欢迎来到周一git专题. 今天和大家聊聊gitignore的作用,其实如果你英文还可以的话,你应该已经基本上猜到它的作用了.ignore在英文当中的意思是忽视.忽略,gitignore自然就是 ...
- 多测师讲解selenium—自动化测试课堂面试题总结—高级讲师肖sir
1.你有做过自动化?你用什么语言? python2.自动化中如何使用语言打开一个网址?浏览器,浏览器对应驱动,导入库,类,get,url3.在一个浏览器中打开多个窗口?open_windows dri ...
- Markdown语法及使用方法完整手册
欢迎使用 Markdown在线编辑器 MdEditor Markdown是一种轻量级的「标记语言」 Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容 ...
- 为什么说switch比if快
C++的switch语法 在C++中,switch只接受整型常量作为分支的值: switch (expr) { case integral-constant : \\... break; case i ...
- 【树形结构】51nod 1766 树上的最远点对
题目内容 \(n\)个点被\(n−1\)条边连接成了一颗树,边有权值\(w_i\).有\(q\)个询问,给出\([a,b]\)和\([c,d]\)两个区间,表示点的标号请你求出两个区间内各选一点之间的 ...
- 【树形DP】CF 1293E Xenon's Attack on the Gangs
题目大意 vjudge链接 给n个结点,n-1条无向边.即一棵树. 我们需要给这n-1条边赋上0~ n-2不重复的值. mex(u,v)表示从结点u到结点v经过的边权值中没有出现的最小非负整数. 计算 ...