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基础知识相关推荐

  1. Verilog基础知识总结02

    Verilog基础知识总结02 1.简述Verilog如何建模 数字电路有两种基本要素:线(器件管脚之间的物理连线:wire)和器件(模块:module). Verilog建模就是用HDL语言把数字电 ...

  2. Verilog基础知识(数值表示总结,signed,原码,反码,补码)

    以前虽然是用过verilog,但是只使用了其中最常见wire,reg类型数据,并且是无符号的,因为是及处理过程很多数据就是无符号的.但是想进一步拓展无符号数,或者其底层的补码形式存储与运算方式,就需要 ...

  3. Verilog基础知识3(门控时钟及FPGA时钟使能处理)

    需求说明:Verilog设计 内容       :第一部分  门控时钟                   第二部分  门控时钟和时钟使能的理解(附代码) 来自       :时间的诗 第一部分  门 ...

  4. Verilog基础知识(异步FIFO)

    本文主要内容来自Clifford E. Cummings的 Simulation and Synthesis Techniques for Asynchronous FIFO Design 这篇文章的 ...

  5. Verilog 基础知识

    Verilog 的逻辑值 逻辑 0:表示低电平,也就是对应我们电路的 GND: 逻辑 1:表示高电平,也就是对应我们电路的 VCC: 逻辑 X:表示未知,有可能是高电平,也有可能是低电平: 逻辑 Z: ...

  6. FPGA基础知识极简教程(9)七段数码管显示的Verilog简单设计

    博文目录 写在前面 正文 七段数码管原理 七段数码管译码表 单个七段数码管显示verilog设计 多个数码管动态扫描显示 参考资料 交个朋友 写在前面 作为FPGA的基础知识教程怎么能少得了这个简单的 ...

  7. Verilog HDL基础知识

    Verilog HDL基础知识 Verilog HDL的语言要素 空白符 注释符 标识符和转义标识符 关键字 数值 1. 整数及其表示 2. 实数及其表示 3. 字符串及其表示 数据类型 Verilo ...

  8. 数字电路基础知识——格雷码和二进制码的转换的算法和Verilog实现

    数字电路基础知识--格雷码和二进制码的转换的算法和Verilog实现 关于数字电路中的码制问题在这篇博客中已经做了详细分析, 数字电路基础知识--数字IC中的进制问题(原码,反码,补码以及各进制的转换 ...

  9. 数字电路基础知识——组合逻辑电路实现一些简单逻辑电路 (一)(用Verilog实现:绝对值函数运算(补码问题),取对数函数(移位寄存器),取整函数)

    数字电路基础知识--组合逻辑电路实现一些简单逻辑电路 (一)(用Verilog实现:绝对值函数运算(补码问题),取对数函数(移位寄存器),取整函数) 在数字逻辑设计中,本节介绍绝对值运算函数如何用Ve ...

最新文章

  1. 我猜你没听过UI自动化技术?
  2. CVPR 2020 论文大盘点-全景分割与视频目标分割篇
  3. Java RTTI与反射(参照Java编程思想与新浪博客)
  4. vector相关习题
  5. c盘哪些文件可以删除_Win7下C盘哪些文件可以删除?
  6. java.util.logging.Logger基础教程
  7. threadingdaemonmultiprocessing
  8. 计算机学业水平没过怎么办,高中学业水平考试两门没通过还能拿到高中毕业证吗...
  9. jquery 图片切换插件(初版)
  10. MFC对话框程序如何添加菜单
  11. java是用什么语言写的_java用什么开发出来的?
  12. elementUI el-upload使用方法、上传限制数量且超出不显示上传按钮、删除闪一下、多个upload并排显示
  13. 如何用python整理表格_Python 自动整理 Excel 表格
  14. Zeev Suraski、Andi Gutmans、Rasmus Lerdorf
  15. 遥控定时小夜灯芯片,充电遥控小夜灯PCBA控制板,遥控小台灯
  16. 1.4 爬虫-笔趣阁获取小说例子
  17. 什么是VMware VSP和VTSP
  18. C++——NOIP2016普及组 t4——魔法阵
  19. Solaris培训第二章:OpenBoot PROM(转)
  20. 数据湖之Hudi基础:核心原理

热门文章

  1. 【TypeScript】必学基础
  2. 局域网(LAN)端口与广域网(WAN/外网)端口映射——实现让局域网机器在外网做服务器...
  3. 批量爬取上交所上市公司报告
  4. 深度学习工作站攒机指南
  5. 前端 - 前端三剑客绘制一幅《圣诞节快乐》交互祝福效果
  6. CSP202109-4 收集卡牌
  7. 32位/64位系统,jdk32位,64位,32/64位jdk编译出来的class和eclipse 32位和64位
  8. js获取指定字符后面的字符
  9. 华为桌面云虚拟机如何安装Ubuntu 20.04.3-live-server
  10. 全国联动css,CSS3 齿轮啮合联动动画