记录一下看《设计与验证Verilog HDL》的知识学习,我属于突然开始学,且得边学边用,所以基础知识并不会太多,大部分项目还是得靠找别人的代码去修改,所以开始看这本书进行基础知识学习,看到这本书是看野火的教程中推荐的书籍,所以买来看看verilg的基础语法一类。
连续赋值语句
assign 是Verilog语言中的关键词之一,他是连续赋值语句,例如:
assign #3 result = (sel_n) ? B_in : A_in;
如果sel_in为真(1),则选B_in,反之则选A_in;最后九江选择的结果赋值给了result;
原语
原语是Xilinx针对其器件特征开发的一系列常用模块的名字,用户可以将其看成Xilinx公司为用户提供的库函数,类似于C++中的“cout”等关键字,是芯片中的基本元件,代表FPGA中实际拥有的硬件逻辑单元,如LUT,D触发器,RAM等,相当于软件中的机器语言。我用的是vivado,在该软件中调用原语的过程挺简单;(这部分在这本书里提到了,但好似没太讲,我也不太会用,在查了查);
也找了几个博客进行学习,我就不描述了,可以通过这个链接去看,不过这个是部分的:BUFG/BUFGCE/BUFH/BUFHCE/BUFH/BUFGHCE/BUFMR/BUFMRCE/BUFR/IBUF/IBUFDS-CSDN博客
这个是7系列FPGA中的几种主要时钟缓冲器原语。
也可以看看这个链接Xilinx原语的用法_xilinx原语的使用方法-CSDN博客
模块和端口
在一个项目中往往需要分不同部分去分别编程,一来好用,二来好看,不同部分就是不同的module,在module中有一些基本语法
reg(寄存器类型)、wire(线网类型)、parameter(部分定义,全局定义后面会说)、input(缺省定义为wire类型)、output(可为wire也可以reg类型)、inout(双向信号,类型是tri类型,表示有多个驱动源,无驱动时为三态)
Verilog里面也有一些编译指令,都是从C语言的预处理指令演变来的:
“`timescale”延时指令,一般放在整个代码的最顶部,形式可以是:“`timescale 1ns / 1ps” 意思是延时单位1ns,时间精度1ps,即0.001ns;
“`define”用于定义宏,这是一种全局变量,知道遇到“`undef”时会停止,parameter用法跟“`define”类似,但“`define”是全局的,parameter是局部的;
如果在代码内需要嵌入其他文件的内容时可用“`include”,典型案例时明德杨的千兆网案例,不过我没有移植成功,但也能看出来是什么样子的,如下图就是引用了其他文件内容;
其他指令用的也少,感兴趣可以百度一下(我也没太看)。
变量类型
verilog有两种变量类型:线网型:表示电路中的物理连线;
寄存器型:一个抽象的数据单元;
线网类型
wire、tri:都表示物理连线,后者主要用于多驱动源;
wor、trior:“线或”的功能;
还有其他的,我目前没咋见过,等见到需要到了在学习一下。
寄存器型
reg :最最最常见的寄存器型;
integer:整数类型,存储一个32位的32位证书;
time :时间类型,存储一个64位的时间值;
real、realtime:实数和实数时间寄存器;
看到一个用法是:reg [3:0] MEMABC [0:7] //定义一个储存器,地址是0~7位,每个存储单元都是4比特;
驱动和赋值
线网是驱动的,这个值不被储存,在仿真上不占内存;
寄存器是赋值的,且这个值是被保存的,直到下一次改变这个变量。
但不论是驱动还是赋值,在平时用的时候都是叫赋值,只有报错时候会说什么地方驱动不对,就例如前几天错的,用pll分频了一个时钟出来,但一直报错说一个引脚被多个驱动源驱动。所以虽然都叫赋值,但也得悄咪咪的分清。
在Verilog语言中他,有三种最基本的描述方式:
1、数据流形式:用assign连续赋值语句;
2、行为描述 :使用always赋值语句;
3、结构化描述:就是例化其他模块;
(写一半去弄了一下第三方编程软件和vivado关联,也没人告诉我要放一个文件下面啊,难搞,记得放同一个盘文件下面,编程软件放在环境变量的时候只需要填到文件夹就行)
行为描述
时序控制
三种方式进行时序控制:事件语句("@")、延时语句("#")、等待语句;
事件语句("@"):一般是在always后使用,如always@(posedge clk125m or posedge reset_p)
基于always语句的特点,always语句很快运行,当遇到@(posedge clk125m or posedge reset_p)时就会激活后续进程。这个例子属于带同步复位端的D触发器,这时候时当出现clk125m和reset_p的下降沿时才会触发always,
编程语句
分三大类:1、if-else语句;
2、case语句 ;
3、循环语句;
if-else语句:
always@(posedge clk125m or posedge reset_p)
begin
if(reset_p)
pkt_err_cnt <= 4'd0;
else if(rx_pkt_err && rx_pkt_done)
pkt_err_cnt <= pkt_err_cnt + 1'b1;
else
pkt_err_cnt <= pkt_err_cnt;
end
在使用这个语句的时候注意不要生成锁存器。因为锁存器会产生竞争冒险,反正是一个很不好的东西。
case语句:在case语句中需要些“default:”是描述虽有没有明确说明的其他可能情况。
always @(*)begin
case(addr)
0: sin_data = 8'h7F;
1: sin_data = 8'h85;
2: sin_data = 8'h8C;
3: sin_data = 8'h92;
4: sin_data = 8'h98;
5: sin_data = 8'h9E;
6: sin_data = 8'hA4;
default:;
endcase
end
循环语句:forever循环,还有其他的,就不一一列举了,这种循环一般是在仿真里编写的。
initial
begin
clk50m=0;
forever #10 clk50m=~clk50m;
end
RTL概念与RTL级建模
阻塞赋值和非阻塞赋值我相信都能大概分清就不写了,开始下一个话题;
寄存器和组合逻辑是数字逻辑电路的两大基本元素,寄存器一般和同步时序逻辑关联,特点就是仅当时钟的沿到达时才有可能发生输出的改变。
有时需要同时使用时钟上升沿和下降沿,虽然可以通过代码完成,但还是更推荐用pll倍频或分频。
串并转换建模
module para_serial(
clk, //50M系统时钟输入
rst_n, //系统复位
//系统输出
sda, //串行数据总线
en //数据转换标志信号
);
//-------------系统输入--------------
input clk; //50M系统时钟输入
input rst_n;//系统复位
//-------------系统输出--------------
output reg sda; //串行数据总线
output reg en; //数据转换标志信号
//------------寄存器定义-------------
reg [7:0]sda_buf; //并行数据寄存器
reg [3:0]counter; //移位计数器
//-----------并串转换逻辑------------
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
sda<=0; //串行数据总线赋初值
sda_buf<=8'b1001_1101; //并行数据寄存器赋初值
counter<=0; //移位计数器赋初值
en<=0; //数据转换标志信号赋初值
end
else
begin
if(counter<8)//控制移位次数
begin
en<=1; //转换使能打开
counter<=counter+1'b1;
//通过位拼接方式实现并串转换
sda_buf<={sda_buf[6:0],sda_buf[7]};
sda<=sda_buf[7]; //将sda_buf一位位的发送出去
end
else
begin
counter<=0;//移位结束,计数器清零
sda<=0;
en<=0; //转换完成
end
end
end
endmodule
这个代码是我在网上找的,串并转换然后发送出去的代码,注释都在。
同步复位和异步复位
复位电路很重要哈,能让整个电路进入初始状态或未知状态,理论上来说,任何一个寄存器、储存器和其他逻辑单元都需要复位电路,一般来说都是低电平有效,复位方式大致分为同步复位和异步复位。,各有优缺点。
同步复位
所谓同步复位是指当复位信号发生变化时,并不立即生效,只有当有效时钟沿采样到已变化的复位信号后,才对所有寄存器复位。同步复位的应用要点如下。指定同步复位时,always的敏感表中仅有时钟沿信号,仅仅当时钟沿采到同步复位的有效电平时,才会在时钟沿到达时刻进行复位操作。如果目标器件或可用库中的触发器本身包含同步复位端口,则在实现同步复位电路时可以直接调用同步复位端。然而很多目标器件(如PLD)和ASIC库的触发器本身并不包含同步复位端口,这样复位信号与输入信号组成某种组合逻辑(比如复位低电平有效,只需复位与输入信号两者相与即可),然后将其输入到寄存器的输入端。为了提高复位电路的优先级,一般在电路描述时使用带有优先级的if...else结构,复位电路在第一个if下描述,其他电路在 else或else...if分支中描述。
优点:利于仿真;利于分析;避免亚稳态;
缺点:很多器件没有同步复位;必须保持复位信号有效时间足够长,才能有效复位;
异步复位
异步复位就是指当复位信号有效沿到来时,无论是中是否有效,都立即对目标复位。
优点:大部分期间都有异步复位;大多数fpga都具有专用的全局异步复位;设计简单;
缺点:复位的作用和时钟没关系;如果复位逻辑出现问题,整体逻辑就乱了;
书中推荐的复位方式时,异步复位,同步释放;
先学到这,到点下班了,周末了,下周回来继续学。
标签:语句,同步,FPGA,复位,always,基础知识,学习,寄存器,赋值 From: https://blog.csdn.net/weixin_68654423/article/details/144128040