verilog基础语法
算数运算电路
//反相器
//2022年10月16日
//反相器设计
'timescale 1ns/10ps
module inv(A,Y);
input A;
output Y;//定义端口的属性
assign output Y = ~A;//定义输入输出的关系
endmodule
//testbeach of inv----
module inv()
module inv_tb;
reg aa;//输入端要动
wire yy;
inv inv(.A(aa),.Y(yy));
//用aa动观察yy
initial begin //按照时间定义各个变量的值
aa <= 0;
#10 aa<= 1;
#10 aa<= 0;
#10 aa<= 1;
#10 $stop;//停止
end
endmodule
//与非门
‘timescale 1ns/10ps
module nand_gate(
A,
B,
Y);
input A;
input B;
output Y;
assign Y = ~(A&B);//组合逻辑,可以使用assign
endmodule
//-----testbench of nand_gate---
module nand_gate_tb;
//异名例化方法
reg aa,bb;
wire yy;
nand_gate nand_gate(.A(aa),.B(bb),.Y(yy));
//让aa,bb动
initial begin
aa<=0;bb<=0; //reg需要使用<=对应实际的电路
#10 aa<=0;bb<=1;
#10 aa<=1;bb<=0;
#10 aa<=1;bb<=1;
#10 $stop;
end
endmodule
//四位的与非门
‘timescale 1ns/10ps
module nand_gate_4bits(
A,
B,
Y);
input[3:0] A;
input[3:0] B;
output[3:0] Y;
assign Y = ~(A&B);//组合逻辑,可以使用assign
endmodule
//-----testbench of nand_gate---
module nand_gate_4bits_tb;
//异名例化方法
reg [3:0] aa,bb;
wire[3:0] yy;
nand_gate_4bits nand_gate_4bits(
.A(aa),
.B(bb),
.Y(yy));
//让aa,bb动
initial begin
aa<=4'b0000;bb<=4'b0000; //reg需要使用<=对应实际的电路
#10 aa<=4'b0010;bb<=4'b1111;
#10 aa<=4'b0000;bb<=4'b0110;
#10 aa<=4'b0000;bb<=4'b0000;
#10 $stop;
end
endmodule
小结
基本逻辑门代码结构。
简单testbeach编写
异名例化
$stop系统任务
verilog位操作逻辑符号
assign组合逻辑赋值语句
用initial组合逻辑赋值语句
用initial语句块写testbeach
设计不用的代码
- initial(设计不用,仿真时候使用)
- task/function(设计不用,仿真时很少用)
- for/while/repeat/forever(设计不用,仿真很少用)
- integer(设计不用)
- 模块内部不能有X态,Z态,内部不能有三态接口
- casex/casez(设计和仿真都不使用)
- force/wait/fork(设计不用,仿真很少用)
- #5(设计不用,仿真时使用)
设计使用的语法
- reg/wire parameter(由本模块产生且用always产生的信号,则reg类型,测试文件initial产生的信号(一般是对测模块的输入),用reg类型),其他都用wire.注:reg类型的信号,不一定产生寄存器!
parameter CNT_C_W = 12 //参数化将整个模块内的信号替换为12(要求参数名要大写区分其他普通信号)
- assign (建议改名使用) always
- 只允许使用if else和case两种条件语句
- 算数运算符(+ ,-, *, /, %)
- 赋值运算符(=,<=)(时序逻辑使用<=,组合逻辑使用=,其他情况不存在);
- 关系运算符(>,<,>=,<=)
- 逻辑运算符(&&,||,!)(为了避免歧义,运算符两边必须为1bit信号)
- 位运算符(~,|,^,&)
按位取反,或,异或,与
- 移位运算符(<<,>>)
<<右移 右移一位==除2 右移两位==除4 >>左移
- 拼接运算符({ })
c <= {{3{a[0]}},b[2],a[4] };
电路设计的结构
1、组合逻辑
always@(*)begin
语句
end
2、时序逻辑(相对于时钟)(时序逻辑使用<=
)
a、同步复位的时序电路
always@(posedge clk)begin
if(rst_n == 1'b0)begin
语句
else begin
语句
end
end
b、异步复位的时序电路
always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
语句
else begin
语句
end
end
电路设计的要点
一个always只产生一个信号
一个信号只能在一个always中产生
实战演练
module mul_module(
mul_result,
mul_a,
mul_b,
clk,
rst_n);
parameter A_W = 4;//参数化
parameter B_W = 3;
parameter C_W = A_W + B_W;//定义位宽 ,参数给别人看
input [A_W-1:0] mul_a;//声明输入,位宽为4
input [B_W-1:0] mul_b;//位宽为3
input clk;
input rst_n;
output [C_W-1:0] mul_result;//声明输出
reg [C_W-1:0] mul_result;//本模块产生,且由于always产生,定义为reg,注意位宽
reg [C_W-1:0] mul_result_tmp ;
//组合逻辑乘法器
always@(*)begin
mul_result_tmp = mul_a*mul_b;//组合逻辑“=”
end
//异步时序复位的D触发器
always@(posedge clk or negedge rst_n)begin
if(rst_n == 1'b0)begin
mul_result <=0;
end
else begin
mul_result <= mul_result_tmp ;
end
endmodule