Verilog基础知识
I/O端口类型:
input wire型
output wire/reg型
verilog可综合语句 assign,always,其中initial 语句不建议用在可综合语句中。
关于时标:
`timescale 时间单位/时间精度
`timescale 1ns/1ps
#3 延时3ns,精度为1ps,递增时,可以递增0.1ns
如果 `timescale 1ns/1ns,精度为1ns,递增时只能按照1ns开始递增
变量类型:wire ,reg
wire 线型
reg 寄存器
在Verilog中,寄存器要用reg来声明,但是reg声明的变量不一定都是寄存器,有可能是锁存器,或者查找表。
查找表:可以理解为数电中的真值表
对于线型,用assign进行赋值即可。
对于寄存器,包含数据输入D端,时钟输入clk端,使能信号en(可无),数据输出Q端。其中,clk是指同步脉冲,一般是指外部晶振提供的方波时钟,占空比50%,即高低电平各占一个时钟周期的50%,1表示高电平,0表示低电平,高到低为下降沿,低到高为上升沿,一般都为上升沿有效时,触发寄存器(也可以下降沿触发,但是reg型必须在always块内进行编程);当时钟clk上升沿触发D端将数据传输至Q端,如果寄存器没有到达下一个沿,继续保持当前数据;当下一个沿到来时,再由D端传输新的数据至Q端。(不含使能情况,若含有使能,则需要在时钟有效后,使能有效,才进行数据的传输)
FPGA一般接收的是方波时钟,而非正弦波时钟。
RTL电路基本结构:组合逻辑 + 时序逻辑
RTL级描述的就是寄存器级的输出传输
阻塞赋值 = :属于立即发生
组合逻辑用,输出受限于输入信号最长延时路径,
非阻塞赋值 <=:时钟沿触发
时序逻辑用,输出受限于时钟沿的到来
在使用always时触发列表由posedge或negedge触发,使用非阻塞赋值
在使用assign时,用阻塞赋值
生成锁存器一般是电平触发 always @(*)
生成寄存器的一般是沿触发 always @(posedge clk)
在代码中进行数值定义时,如果不声明前面的位宽则默认为32bit,写代码时需要写明位宽和进制;如果数据表述为32位宽,但实际数值不足32位宽,则高位补0。
例如: 255 默认32bit
// reg [7:0] cnt = 8'd255;
// reg [3:0] cnt = 255; cnt 实际上等于 4'd15, 4hf,4'b1111
// reg [3:0] cnt = 81; cnt 实际上等于 4'b0001
//0~255 随机数生成方式 {$random}%256
// %表示求模运算,返回值是除以256后的余数
//always #10 a = {$random}%256;
赋值语句:
assign c1 = a & b; //c1 wire
always @(posedge clk) begin
c2 <= a & b; //c2 reg
end
//敏感列表不全会生成latch,所以建议直接使用 * 代替所有敏感变量
always @(*)begin
c3 <= a & b; // c3 reg
end
时钟频率计算:
时钟周期 20ns = 50 Mhz = 1 / 20
时钟周期 10ns = 100 Mhz = 1/10
F = 1/T
1s=10^3 ms=10^6 us=10^9 ns
1GHz=1000MHz,1MHz=1000kHz,1kHz=1000Hz
1s=1000ms,1 ms=1000μs,1μs=1000ns
时钟频率 |
时钟周期 |
1Hz |
1s |
1KHz |
1ms |
1MHz |
1μs |
1GHz |
1ns |
定义接口时,output reg c2=1'b0, 可给寄存器赋初始值;但是线网不可进行赋初始值。
运算符:
% 求模运算
假设得到0~9之间的随机数:a = {$random}%10;
判断 a 是否在 10 ~ 20 之间写法:
错误写法:if(10<a<20)
正确写法:if(10 < a && a < 20)
逻辑运算符(&&、||、!):结果为 1 或者 0
按位运算符(&、|、~):每一位都进行运算
条件运算符((x)?x:x)
移位运算发:
>>右移; 高位补0
<<左移;低位补0
位拼接运算符:{}; 例如:d <= {a,b,c};
位拼接实现循环左移:po_a <= {po_a[6:0],po_a[7]};
位拼接实现循环右移:po_a <= {po_a[0],po_a[7:1]};
移位运算应用于并串转换,SPI接口协议将协议以方波的形式传递出去(实际数据8bit,但SPI输出的数据是在一根线上,所以可以用移位寄存器将输入的8bit并行数据以串行方式以1bit输出方式串行输出)
条件判断语句:if…else case…endcase
PS:
在编写always块时,if else 叠加不易过多,不然可能造成线路的延时过多。因为,每一个 if else 语句都会生成一个选择器,而每两级选择器之间会存在线路延时,当 if else 过多时,选择器链路总延时就会很长,从而影响电路时序,当时序出问题时,就算是功能仿真正确,下板后电路也是不正确的。
另外:在使用 if else 时需要注意优先级造成的影响。
使用case…endcase语句可生成多路选择器,无延时,并行判断,勿漏default(组合逻辑中),不然会生成 latch:
对于:
else if(cnt == 4'd15)
cnt <= 4'd0;
如果cnt最大值是cnt位宽所能容纳的最大值时,计数到最大值后自动清零;
反之,如果位宽所能容纳的最大值不是cnt的最大值时,就需要加限制条件。
时钟分频:(在FPGA中,如果不调用PLL,则无法进行倍频)
在FPGA开发板上面只有一个晶振,即只有一种频率的时钟,如果需要用到不同频率的时钟,就需要在这个固定的时钟频率条件下进行分频或者倍频;
得到比固定的时钟频率更慢的时钟,进行分频操作;
得到比固定时钟频率更快的时钟,进行倍频操作;
时钟分频例子:呼吸灯
要求:从亮到灭的时间为 2s,从灭到亮的时间为 2 秒,完成呼吸的过程一共需要 4 秒时间。
解析:2s/1000份 = 2000000ms = 2000us,将2000us再分1000份=2us,
50Mhz=20ns,2us/20ns = 100,最小计数为100,计数1000次,得到一个2/1000 s,
计满1000个2/1000 s 即为2s,每2/1000 s 为1个PWM周期。
波形图:
RTL code:
module breathing_led(input wire clk,rst,output reg led);reg [6:0] clk50m_cnt;reg [9:0] clk50m_cnt_1000;reg [9:0] pwn_cnt_1000;reg pwn_flag;always @(posedge clk)beginif(rst)clk50m_cnt <= 7'd0;else if(clk50m_cnt == 7'd99)clk50m_cnt <= 7'd0;else clk50m_cnt <= clk50m_cnt + 1'b1;endalways @(posedge clk)beginif(rst)clk50m_cnt_1000 <= 10'd0;else if(clk50m_cnt == 7'd99 && clk50m_cnt_1000 == 10'd999)clk50m_cnt_1000 <= 10'd0;else if(clk50m_cnt == 7'd99)clk50m_cnt_1000 <= clk50m_cnt_1000 + 1'b1;endalways @(posedge clk)beginif(rst)pwn_cnt_1000 <= 10'd0;else if(clk50m_cnt == 7'd99 && clk50m_cnt_1000 == 10'd999 && pwn_cnt_1000 == 10'd999)pwn_cnt_1000 <= 10'd0;else if(clk50m_cnt == 7'd99 && clk50m_cnt_1000 == 10'd999)pwn_cnt_1000 <= pwn_cnt_1000 + 1'b1;endalways @(posedge clk)beginif(rst)pwn_flag <= 1'b0;else if(clk50m_cnt == 8'd99 && clk50m_cnt_1000 == 10'd999 && pwn_cnt_1000 == 10'd999)pwn_flag <= ~pwn_flag;endassign led = (pwn_flag==1'b1)?((clk50m_cnt_1000 < pwn_cnt_1000)?1'b1:1'b0):((clk50m_cnt_1000 < pwn_cnt_1000)?1'b0:1'b1);endmodule
TB:
`timescale 1ns/1ns
module tb_breathing_led;reg clk,rst;wire led;initial beginclk=0;rst=1;#100rst=0;endalways #10 clk = ~clk;breathing_led inst_breathing_led (.clk(clk), .rst(rst), .led(led));endmodule
Top-down设计
Top-down 设计即自顶向下的设计
在模块例化时:
如果模块内部接口是输入,连接的接口类型可以是 wire/reg;
如果模块内部接口是输出,连接的接口类型可以是 wire;
有限状态机
一段式指的是在一个 always块内使用时序逻辑既描述状态的转移,同时也描述数据的输出;
二段式指一个always 块使用时序逻辑描述状态转移,另外一个 always 块使用时序逻辑描述数据输出;
三段式指使用三个 always 块,一个 always 模块采用时序逻辑描述状态转移,一个 always 块采用组合逻辑判断状态转移条件,描述状态转移规律,另一个 always 块描述状态输出(可以用组合电路输出,也可以时序电路输出)。
//状态机模板
module 模块名(
端口 1,
端口 2,
...
端口 N,
);/时序逻辑描述的状态转移always@(posedge clk or negedge rst_n)状态转移;//时序逻辑描述的数据输出always@(posedge clk or negedge rst_n)数据输出;endmodule
对于modelsim自动化仿真脚本的建立:
run.tcl#退出仿真
quit -sim
#清除临时保存的仿真文件
.main clear #建立库
vlib work
#编译 .v
vlog ./tb_test.v
#编译所有 .v 到work库中
vlog ./../src/*.v
#启动仿真,-voptargs+=acc(等于手动点simulation),选择work库中的tb顶层文件,进行仿真
vsim -voptargs+=acc work.tb_test #添加wave
add wave /tb_test/test_init/*
#执行1us
run 1us
状态机例子:
一个自动售货机中的商品 2.5 元一件,每次投币既能投入 1 元, 也能投入 0.5 元,当投入 3 元时,找零0.5元,使用状态机描述。
RTL codemodele fsm(input wire clk,input wire rst,input wire pi_money,output reg po_money,output reg po_water);reg [4:0] state;parameter idle = 5'b00001;parameter half = 5'b00010;parameter one = 5'b00100;parameter one_half = 5'b01000;parameter two = 5'b10000;always @(posedge clk)beginif(rst==1'b1)beginstate <= idle;endelse begincase(state)idle : if(pi_money == 1'b1) state <= one;else if(pi_money == 1'b0) state <= half;half : if(pi_money == 1'b1) state <=one_half;else if(pi_money == 1'b0) state <= one;one : if(pi_money == 1'b1) state <= two;else if(pi_money == 1'b0) state <= one_half;one_half: if(pi_money == 1'b1) state <= idle;else if(pi_money == 1'b0) state <= two;two : if(pi_money == 1'b1) state <= idle;else if(pi_money == 1'b0) state <= idle;default : state <= idle;endcaseendendalways @(posedge clk)beginif(rst==1'b1)beginpo_water <= 1'b0;po_money <= 1'b0;endelse if(state == one_half && pi_money == 1'b1) || (state == two && pi_money == 1'b0)beginpo_water <= 1'b1;po_money <= 1'b0;endelse if (state == two && pi_money == 1'b1) beginpo_water <= 1'b1;po_money <= 1'b1;endendendmodule
tb:
`timescale 1ns/1ns
module tb_fsm;reg clk,rst,pi_money;wire po_money,po_water;initial beginrst = 1;clk = 0;pi_money = 0;#100rst = 0;endalways #10 clk = ~clk;always #20 pi_money = {$random};fsm fsm_inst(.clk(clk),.rst(rst),.pi_money(pi_money),.po_money(po_money),.po_water(po_water));endmodule
run.tcl:quit -sim
.main clear vlib work
vlog ./tb_fsm.v
vlog ./../src/*.v
vsim -voptargs+=acc work.tb_fsm #定义结构体进行匹配
virtual type{{5'b00001 idle}{5'b00010 half}{5'b00100 one}{5'b01000 one_half}{5'b10000 two}
}abc;#创建新信号,(abc)强制转换
virt function{(abc)/tb_test/test_init/state}new_state
add wave /tb_fsm/fsm_init/*
run 1us
Verilog基础知识相关推荐
- Verilog基础知识总结02
Verilog基础知识总结02 1.简述Verilog如何建模 数字电路有两种基本要素:线(器件管脚之间的物理连线:wire)和器件(模块:module). Verilog建模就是用HDL语言把数字电 ...
- Verilog基础知识(数值表示总结,signed,原码,反码,补码)
以前虽然是用过verilog,但是只使用了其中最常见wire,reg类型数据,并且是无符号的,因为是及处理过程很多数据就是无符号的.但是想进一步拓展无符号数,或者其底层的补码形式存储与运算方式,就需要 ...
- Verilog基础知识3(门控时钟及FPGA时钟使能处理)
需求说明:Verilog设计 内容 :第一部分 门控时钟 第二部分 门控时钟和时钟使能的理解(附代码) 来自 :时间的诗 第一部分 门 ...
- Verilog基础知识(异步FIFO)
本文主要内容来自Clifford E. Cummings的 Simulation and Synthesis Techniques for Asynchronous FIFO Design 这篇文章的 ...
- Verilog 基础知识
Verilog 的逻辑值 逻辑 0:表示低电平,也就是对应我们电路的 GND: 逻辑 1:表示高电平,也就是对应我们电路的 VCC: 逻辑 X:表示未知,有可能是高电平,也有可能是低电平: 逻辑 Z: ...
- FPGA基础知识极简教程(9)七段数码管显示的Verilog简单设计
博文目录 写在前面 正文 七段数码管原理 七段数码管译码表 单个七段数码管显示verilog设计 多个数码管动态扫描显示 参考资料 交个朋友 写在前面 作为FPGA的基础知识教程怎么能少得了这个简单的 ...
- Verilog HDL基础知识
Verilog HDL基础知识 Verilog HDL的语言要素 空白符 注释符 标识符和转义标识符 关键字 数值 1. 整数及其表示 2. 实数及其表示 3. 字符串及其表示 数据类型 Verilo ...
- 数字电路基础知识——格雷码和二进制码的转换的算法和Verilog实现
数字电路基础知识--格雷码和二进制码的转换的算法和Verilog实现 关于数字电路中的码制问题在这篇博客中已经做了详细分析, 数字电路基础知识--数字IC中的进制问题(原码,反码,补码以及各进制的转换 ...
- 数字电路基础知识——组合逻辑电路实现一些简单逻辑电路 (一)(用Verilog实现:绝对值函数运算(补码问题),取对数函数(移位寄存器),取整函数)
数字电路基础知识--组合逻辑电路实现一些简单逻辑电路 (一)(用Verilog实现:绝对值函数运算(补码问题),取对数函数(移位寄存器),取整函数) 在数字逻辑设计中,本节介绍绝对值运算函数如何用Ve ...
最新文章
- 我猜你没听过UI自动化技术?
- CVPR 2020 论文大盘点-全景分割与视频目标分割篇
- Java RTTI与反射(参照Java编程思想与新浪博客)
- vector相关习题
- c盘哪些文件可以删除_Win7下C盘哪些文件可以删除?
- java.util.logging.Logger基础教程
- threadingdaemonmultiprocessing
- 计算机学业水平没过怎么办,高中学业水平考试两门没通过还能拿到高中毕业证吗...
- jquery 图片切换插件(初版)
- MFC对话框程序如何添加菜单
- java是用什么语言写的_java用什么开发出来的?
- elementUI el-upload使用方法、上传限制数量且超出不显示上传按钮、删除闪一下、多个upload并排显示
- 如何用python整理表格_Python 自动整理 Excel 表格
- Zeev Suraski、Andi Gutmans、Rasmus Lerdorf
- 遥控定时小夜灯芯片,充电遥控小夜灯PCBA控制板,遥控小台灯
- 1.4 爬虫-笔趣阁获取小说例子
- 什么是VMware VSP和VTSP
- C++——NOIP2016普及组 t4——魔法阵
- Solaris培训第二章:OpenBoot PROM(转)
- 数据湖之Hudi基础:核心原理
热门文章
- 【TypeScript】必学基础
- 局域网(LAN)端口与广域网(WAN/外网)端口映射——实现让局域网机器在外网做服务器...
- 批量爬取上交所上市公司报告
- 深度学习工作站攒机指南
- 前端 - 前端三剑客绘制一幅《圣诞节快乐》交互祝福效果
- CSP202109-4 收集卡牌
- 32位/64位系统,jdk32位,64位,32/64位jdk编译出来的class和eclipse 32位和64位
- js获取指定字符后面的字符
- 华为桌面云虚拟机如何安装Ubuntu 20.04.3-live-server
- 全国联动css,CSS3 齿轮啮合联动动画