###### 【该随笔部分内容转载自小梅哥】 #########
- 组合逻辑: 多路选择器、加法器、译码器、乘法器
- 时序逻辑: 计数器、分频器、定时器、移位寄存器
一、Verilog文件的基本结构
1、模块声明 模块名 端口列表
2、端口类型、位宽定义
3、功能描述
//模块描述方式一(先列出端口,再描述端口类型)
//此方式虽然行数多,但是方便后面例化端口,推荐使用
module name(
,
,
//最后一个不需要“,”
);
//端口类型描述
//功能描述
endmoule
//模块描述方式二(端口列表和端口类型一起描述)
module name(
//端口列表 + 类型描述
);
//功能描述
endmoule
二、数据类型
- 线与型wire(默认值z—高阻) 寄存器型reg
注:存储器型(memory)
memory型数据常用于寄存器文件、ROM和RAM建模等,是寄存器型的二维数组形式,它是将reg型变量进行地址扩展而得到
//一般格式:
reg[n-1 : 0] 存储器名[N-1 : 0];
//定义位宽为n,深度为N的寄存器组
- parameter型(常量参数)
三、数据表示
assign x = 4'b1001; //二进制
assign x = 4'd9; //十进制
assign x = 4'hc; //十六进制
四、运算
1、加(+)——加法器
减(-) ——减法器(逆运算)
乘(*) ——乘法器
除(/) ——除法器ip核(尽量不用)
2、 逻辑运算
逻辑与&&,或||,非!(只有一位)
按位与&、或|、非~、异或^、同或~^
五、组合逻辑电路功能的描述
设计方法: 分析真值表规律
两种描述方式:
-
- 方式1:用assign描述,用阻塞赋值=
-
- 方式2:用always@(*)描述,用非阻塞赋值<=
选择功能的三种描述方式:
-
- 方式1:三目运算符 ? : ;
-
- 方式2:if...else if.....else(分级)
-
- 方式3:switch...case....default...(并行)
例1.mux2二选一数据选择器
//方式1(先列出端口,后定义端口属性)
module mux2(
a,
b,
sel,
out
);
//端口属性定义(输入/输出,位宽)
input [7:0]a;
input [7:0]b;
input sel; //sel = 0,out输出a
output [7:0]out; //位宽8位
//功能描述
//阻塞赋值语句
assign out = (sel == 0)?a:b;
//assign out = (!sel)?a:b;
//assign out = sel?b:a;
endmodule
//方式2(在声明端口的同时定义属性)
module mux2(
//端口属性定义
input [7:0]a,
input [7:0]b,
input sel,
output [7:0]out //此处没有分号
);
//功能描述
//阻塞赋值语句
assign out = (sel == 0)?a:b;
endmodule
例2.三态门控制
//三态门控制
assign oe = sel;
assign io = oe?out[0]:1'bz; //z高阻态(输入)
例3.加法器
1、半加器halfadder
2、全加器adder
设计方式1:采用原理图方式,由两个半加器和一个或门组成
设计方式2:采用verilog直接描述(如下图)
六、时序逻辑电路设计
用always@(posedge clk)描述
时序逻辑电路的基础——计数器
例1.四位计数器(同步使能、异步复位)
module counter(clk,en,rst);
input clk; //时钟信号
input en; //使能信号
input rst; //清零信号
reg [3:0]cnt; //4位寄存器,用于计数
//同步清零和异步清零的问题
always@(posedge clk,negedge rst)
if(!rst)
cnt <= 4'd0;
else if(en)begin
cnt <= cnt + 1'b1;
else
cnt <= cnt;
end
endmodule
注:计数器只是基本电路,比如分频器、定时器、巴克码序列发生器在计数器基本电路上设计即可;
例2.基本分频操作——分频器(闪烁灯)
例3.基本移位操作——verilog位操作(流水灯)
//1.取某一位直接操作
wire [2:0]m;
assign m = out[5:3];
//2.循环移位(移位寄存器)
reg [7:0] shift_a;
always@(posedge clk)
shift_a <= {shifta[0],shift[7:1]};
reg [7:0] shift_a;
wire data;
always@(posedge clk)
shift_a <= {data,shift[7:1]};
reg [7:0] shift_a;
wire data;
always@(posedge clk)
shift_a <= {shift[7:1],data};
//3、拼接
wire [3:0]x;
wire [3:0]y;
wire [7:0]z;
wire [31:0]n;
assign z = {x,y};
assign n = {x,7{x}};