Verilog设计入门
Posted 数学小学霸
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Verilog设计入门相关的知识,希望对你有一定的参考价值。
EDA(03)Verilog设计入门
2020-10-04
基础知识
常用
关键字
// 输入
input
// 输出
output
// 参数
parameter
// 赋值语句
assign
// 上升沿 与 下降沿
posedge negedge
常用运算符
// 逻辑操作
~ // 逻辑取反
| // 逻辑或
& // 逻辑与
^ // 逻辑异或
~^ // 逻辑同或
// 逻辑运算符
&&
||
!
// 关系运算
< <=
> >=
// 算术运算
+
-
*
/
%
// {}拼接运算
[7:0] a // a 为声明
a[6:3] // a 为调用
数值表示
长度'数制简写 数字
4'd8
4'b1011
12'ha2e
// 默认位宽 取决于本身的长度
2345
// 逻辑状态
0 1 x z
x 表示不确定
12'h13x
32'bz
z 表示高阻态
注意
-
assign
只能给wire 类型赋值 -
reg 类型只能在
always
赋值 -
变量缺省定义默认是
wire
类型 -
组合电路用
=
时序电路用<=
文件
后缀名是.v
常见电路
选择电路
2选1
module mux2_1_a(a, b, s, y);
input a, b, s;
output y;
assign y = (s ? a : b);
endmodule
module mux2_1_b(a, b, s, y);
input a, b, s;
output y;
wire c, d;
// 虽然位置有先后,但是同时运行的
assign c = a & (~s);
assign d = s & b;
assign y = c | d;
endmodule
4选1
module mux_4_1(y, a, b, c, d, s1, s0);
output out;
input a, b, c, d;
input s1, s0;
assign y = s1 ? (s0 ? d : c) : (s0 ? b : a);
endmodule
使用always
module mux_4_1(a, b, c, d, s1, s0, y);
input a, b, c, d, s1, s0;
output reg y;
always @ (a, b, c, d, s1, s0)
begin
// case 要在always 里面
case({s1, s0})
2'b00: y = a;
2'b01: y = b;
2'b10: y = c;
2'b11: y = d;
default: y = a;
endcase
end
endmodule
加法器
全加器
module full_add(a, b, c, so, co);
input a, b, c;
output so;
output co;
assign {co, so} = a + b + c;
endmodule
8位全加器
module adder_8bit(a, b, cin, cout, dout);
output [7:0] dout;
output cout;
input [7:0] a, b;
input cin;
// { } 是拼接操作符
assign {cout, dout} = a + b + cin;
endmodule
半加器
module h_adder(A, B, SO, CO);
input A, B;
output SO, CO;
assign SO = A ^ B;
assign CO = A & B;
endmodule
计数器
8位
module cnt_8bit(clk, nRST, cnt_out);
input clk, nRST;
output reg [7:0] cnt_out;
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
cnt_out <= 0;
else
cnt_out <= cnt_out + 1;
end
endmodule
0 - 199计数
module cnt_8bit(clk, nRST, cnt_out);
input clk, nRST;
output reg [7:0] cnt_out;
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
cnt_out <= 0;
else if (cnt_out < 8'd199)
cnt_out <= cnt_out + 1;
else
cnt_out <= 0;
end
endmodule
定时器
// clk = 1M Hz
// 1000000
// 999999
// 1s 产生 1 us高脉冲pulse
// 异步复位 低电平复位
module timer_pulse(clk, nRST, pulse);
input clk;
input nRST;
output reg pulse;
reg [19:0] cnt;
// 运行1 M 次才是 1 s
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
cnt <= 0;
else if (cnt < 999999)
cnt <= cnt + 1;
else
cnt <= 0;
end
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
pulse <= 0;
// 产生1 us = 10 e-6 脉冲
else if (cnt < 1)
pulse <= 1;
else
pulse <= 0;
end
endmodule
// clk = 1M Hz
// 1000000
// 999999
// 1s 产生 1 ms高脉冲pulse
// 异步复位 低电平复位
module timer_pulse(clk, nRST, pulse);
input clk;
input nRST;
output reg pulse;
reg [19:0] cnt;
// 运行1 M 次才是 1 s
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
cnt <= 0;
else if (cnt < 999999)
cnt <= cnt + 1;
else
cnt <= 0;
end
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
pulse <= 0;
// 产生1 ms = 10 e-3 脉冲
else if (cnt < 1000)
pulse <= 1;
else
pulse <= 0;
end
endmodule
寄存器
移位
module SHFT4(DIN, CLK, RST, DOUT);
input CLK, DIN, RST;
output DOUT;
reg [3:0] SHFT;
always @ (posedge CLK or posedge RST)
if (RST)
SHFT <= 0;
else
begin
SHFT[3] <= DIN;
SHFT[2:0] <= SHFT[3:1];
end
assign DOUT = SHFT[0];
endmodule
分频器
2 分频器
// 2 分频
// 50 % 占空比
module div_2(clk, div_2_out);
input clk;
output reg div_2_out;
reg cnt;
always @ (posedge clk)
begin
if (cnt == 1)
cnt <= 0;
else
cnt <= cnt + 1;
if (cnt == 1)
div_2_out <= 0;
else
div_2_out <= 1;
end
endmodule
4分频器
16分频器
module fenpin_16(clk, clk_out);
input clk;
output clk_out;
reg [3:0] cnt;
always @ (posedge clk)
begin
cnt <= cnt + 1;
end
assign clk_out = cnt[3];
endmodule
5 分频器
// 5 分频
// 3 / 5 占空比
// 带异步复位 低电平复位
module fenpin_53(clk, clk_out);
input clk;
output reg clk_out;
reg [3:0] cnt;
always @ (posedge clk)
begin
if (cnt == 4)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @ (posedge clk)
begin
if (cnt <= 2)
clk_out <= 1;
else
clk_out <= 0;
end
endmodule
LED灯
跑马灯
module paomadeng(clk, nRST, LED);
input clk;
input nRST;
output reg[7:0] LED;
// IN
reg [31:0] cnt;
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
cnt <= 0;
else if (cnt >= 499999)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
LED[7:0] <= 8'b10000000;
else if (cnt == 499999)
LED[7:0] <= {LED[0], LED[7:1]};
else
LED <= LED;
end
endmodule
回马灯
// 500ms 定时器 cnt
// 每3500 ms 翻转一次
// 500 ms 改变一次LED状态
// state 0 右移
// state 1 左移
module huimadeng(clk, nRST, LED);
input clk;
input nRST;
output reg [7:0] LED;
// IN
reg [31:0] cnt;
reg state;
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
cnt <= 0;
else if (cnt == 499999)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
LED <= 4'b10000000;
else if (cnt == 1)
begin
if (state == 0)
LED <= {LED[0], LED[7:1]};
else
LED <= {LED[6:0], LED[7]}};
end
else
LED <= LED;
end
always @ (posedge clk or negedge nRST)
begin
if (!nRST)
state <= 0;
else if (LED == 8'b00000001)
state <= 1;
else if (LED = 8'b10000000)
state <= 0;
else
state <= state;
end
endmodule
交通灯
时序逻辑电路
触发器
// 同步复位
module DFF1(clk, D, Q);
output reg Q;
input clk, D;
always @ (posedge CLK)
Q <= D;
endmodule
// 异步复位
module DFF2(CLK, Q, D, RST, EN);
input CLK, D, RST;
output reg Q;
always @ (posedge CLK or negedge RST)
begin
if (!RST)
Q <= 0;
else if (EN)
Q <= D;
end
endmodule
阻塞和非阻塞
// in = 1 2 3 4 5 6 7 ...
// 阻塞
always @ (*)
begin
a = in;
b = a;
c = b;
end
// 跟C 语言一样, 是有顺序的
// 1 1 1
// 2 2 2
// 3 3 3
// 4 4 4
// ...
// 非阻塞
always @ (posedge clk)
begin
a <= in;
b <= a;
c <= b;
end
// 同时执行的
// 1 0 0
// 2 1 0
// 3 2 1
// 4 3 2
基本时序
以上是关于Verilog设计入门的主要内容,如果未能解决你的问题,请参考以下文章