FPGA学习(基于小梅哥Xilinx FPGA)学习笔记

文章目录

相关资源网站(小梅哥FPGA)

https://www.corecourse.cn/forum.php?mod=viewthread\&tid=27978

https://www.corecourse.cn/forum.php?mod=viewthread\&tid=28730

本篇文章使用的开发板为:
小梅哥 Xilinx FPGA
型号:XC7A35T
芯片型号:XC7A35TFGG484-2

以下所有文章内容,均来自小梅哥FPGA教学视频,这个文章只是针对每个教学视频的个人理解总结。

一、整个工程的流程

写一套硬件描述语言,能够在指定的硬件平台上实现相应的功能

  1. 设计定义(让LED一秒闪烁一次)
  2. 设计输入(编写逻辑(使用Verilog代码描述逻辑),画逻辑图,使用IP盒(即提供的成品功能器件))
  3. 综合工具(由专业的EDA软件进行,Quartus、Vivado、ISE),对所写的逻辑内容进行分析,并得到逻辑门级别的电路内容。(如if else就是一个二选一多路器)
  4. 功能仿真(使用专门的仿真工具进行仿真,验证设计的逻辑功能能够实现。对于数字电路来说 ,仿真时基本接近于真实情况的,是可信的)
  5. 布局布线(走线带来延迟,延迟越长,主频越低)(在指定器件上将设计的逻辑电路实现)
  6. 分析性能(1、时序仿真(非常耗费时间),仿真软件进行观察;2、静态时序分析(平时用这个))
  7. 下载到目标板运行,查看运行结果。(板级调试)(使用ILA(嵌入式逻辑分析仪)(Vivado))
  8. 让设计的逻辑在目标板上正常工作(功能正常,性能稳定)

总结

  1. 设计定义
  2. 设计输入
  3. 分析综合(EDA、Vivado、Quartus)
  4. 功能仿真(Modelsim)
  5. 布局布线(Vivado、Quartus)
  6. 分析性能(时序仿真Modelsim、静态时序分析Vivado、Quartus)
  7. 板级调试
  8. OK
    2024.12.22

二、基于Vivado的FPGA开发流程实践(二选一多路器)

打开Vivado并创建工程mux2后,Vivado界面上左边流程

即该软件就是按照开发流程进行运行的

什么是二选一多路器

当SEL=1时,out=a

当SEL=0时,out=b

用verilog语言,Vivado软件进行该电路实现

下图要注意符号的运用

1、设计输入:Design Sources中的代码

用到的语法(Verilog语言)

  1. 定义模块
c 复制代码
module xxx(
......
)
endmodule
//定义一个模块
  1. 定义输入输出
c 复制代码
input a;
output out;
  1. 赋值语句
c 复制代码
assign out = (sel==1)?a:b;
//在sel=1的情况下,将a的值赋予out,否则将b的值赋予out
assign out = ~a;
//将a取反的值赋予out

2、分析和综合:分析设计输入中是否有错误

分析综合运行后,看message,其中没有报错那么这一步就完成了,接下来就进行仿真验证

3、功能仿真,Simulation Sources中的仿真实现代码(Test_Bench)

在仿真平台中,通过代码编写,搭建一个仿真平台,取验证之前编写的module是否OK

我们个人一般用不到ps级别的延时,ns够用

c 复制代码
#1 //延时1ns
#2 //延时2ns
#1.001 //延时1.001ns,这是在配置为1ns/1ps情况下是可以实现的

写一个可以测试之前定义的module mux2的功能的仿真代码

c 复制代码
reg s_a; //定义测试平台的输入信号,可接0和1逻辑输入
c 复制代码
.a(s_a); //.代表测试端子,a代表module中a端口,(s_a)代表测试平台的reg端口
//这句话的意思是,将测试平台的(s_a)端子与module的a端子通过.来相接
c 复制代码
wire out; //定义平台的输出信号,可根据分析输入信号和module来确认这个输出信号
c 复制代码
initial begin
......
end
//测试平台的操作

跑仿真后出现这个界面,这个就是仿真的时序图,

第一次跑不全,再跑一次

此时可以看着时序图对out的信号进行对比,看是否是我们需求的信号输出结果。

仿真这一步挺重要的,建议需要掌握

4、布局布线


点击红框中的符号可以看到目前的编译状态

5、时序仿真


时序仿真电路中可以看到真实的电路中的信号延迟情况,

out都滞后于输入信号的变化,根据时序仿真,可以看出延迟情况,来判断 这个延迟我们能否接受

6、板级调试

(1)IO引脚分配






根据上图进行引脚分配

分配完成后,在引脚分配界面进行ctrl+s进行保存,保存名称和项目名称可以一样(不强求,也可以不一样)

(2)程序下载

点击后就可以进行创建,

创建完成后可以进行程序下载


这样就下载完成了,之后就可以进行板级调试。

2021.12.22

三、3-8译码器的实现

什么是3-8译码器

1、设计输入

3-8译码器

创建module,创建3-8译码器的端口

端口创建完成后,定义端口的输入输出状态

输入输出状态定义完成后,进行端口之间的逻辑编写

用到的语法

  1. always

  2. 位拼接

    d是一个4位数据,通过assign将 a, 1bit常量值为0,b , c这四个数拼在一块赋值给d

  3. 描述多位格式的常用限定符号

    这两个表达方式是一样的

c 复制代码
b  二进制        3'b101         8'b0000_1010
o  八进制
d  十进制        3'd5           8'd10
h  十六进制                     8'ha
  1. case() endcase
    case括号中,为满足操作的条件
    在满足条件下进行操作,如:\
c 复制代码
3'b000 : out = 8'b0000_0001; 

具体解释为拼接后的{a,b,c}在满足3位bit值是000的情况下,将8bit的0000_0001赋值给out

整个3-8译码器代码为下

2、分析综合

分析综合的作用,检查设计输入的语法有无问题

分析之后查看reports,有错误则报红

3、仿真

创建一个测试平台,命名规则一般为(文件名_tb),tb代表test bench

测试平台的代码具体的流程为

  1. 定义测试平台的时间尺度
  2. 定义一个测试平台
  3. 定义测试平台的端口,标注好reg型(输入)和wire型(输出)
  4. 将模块放置到测试平台上
  5. 将模块中的端口与测试平台的端口互相连接
  6. 定义测试平台的测试动作(给各信号端口激励信号并延时)
  7. end

    所有代码完成后,进行仿真

    仿真第一次跑会根据仿真设置中的默认跑1000ns来跑,所以第一次的仿真都是1000ns的时间段中的动作
    这里我们可以不用管,直接再次跑,在动作结尾加上 $stop; 即可跑到这里自动停止

4、时序仿真

跳过,这个项目中只进行了模拟仿真,并没有进行时仿真

原因是项目比较简单,无进行必要。但也可以进行。这个步骤有无都无所谓

5、IO引脚分配

打开综合类工程

必须打开后才能看到IO planning这个选项

IO设置中首先将I/O Std电压设定为3.3(LVCMOS33),只针对于目前手中的这个开发板进行的设定

其次根据引脚对应表,将拨码开关引脚进行设定

LED灯对应的引脚(高电平点亮)

根据表进行设定

设定完成后进行ctrl+s保存

6、生成代码,板级调试

因为之前没有进行布局布线,即

在生成BitStream时候会进行检查,没布局布线的话这一步会自动进行,所以这一步在之前省略了

点击之后,等待完成。

下一步连接硬件板卡进行程序下载

之后进行板级调试就OK

三个拨码开关,设定为a,b,c
8个LED灯代表out 0-7
拨码开关不同状态代表不同输出,led显示表示输出

课后题,写4-16译码器代码

1、module设计输入


代码完成后进行分析综合,即检查下代码有无错误

2、功能仿真


代码完成后进行分析综合,即检查下代码有无错误

3、布局布线

4、 时序仿真

5、IO引脚分配

6、生成代码,板级调试

2024.12.23

四、时序逻辑计数器设计

什么是D触发器

CK上升沿的时候,将D端口的信号输出给Q端口

即D触发器有存储特性,只在CK端口上升沿变化,其余时间一概不管,即Q端口可以存储D的电平状态

什么是计数器

counter = counter+1

目标,设计1s频率闪烁的LED灯(亮灭各500ms)

目前板子的时钟是50MHz,那么执行每步操作时候为20ns

则500ms需要计数500ms/20ns=25000000

用Verilog代码实现led闪烁

1、设计输入:module编写

  1. 确认module端口,需要有时钟信号Clk,复位信号Reset_n(低电平复位),Led控制信号
  2. 确认信号的类型
    时钟信号为输入 input
    复位信号为输入 input
    led信号为输出 output
    counter信号为内部计数,多位D触发器,具体多少位,通过以下计算

    即需要25位D触发器,设定为reg类型的counter:reg [24:0]counter;
    即最终的端口定义是这样的

    通过这个定义可以看出,内部端口也是需要进行定义的,而且内部端口不再试input和output类型的端口了,这里则使用的试reg寄存器类型来表示。
    同时对需要进行复杂操作的端口也要进行reg的定义,如之后的代码需要让Led端口自行取反,即Led=!Led;
  3. 端口的逻辑操作,两种写法:1:综合在一块写;2:分开写
    综合在一块写(不推荐)

    分开写(推荐,构成的电路会更简便)

即最终的module代码:

这个图试后续运行后发现代码无法实现功能反回来查找问题,各种语句使用的都是"<=",否则会有问题。
<= :非阻塞赋值
= : 阻塞赋值

c 复制代码
阻塞赋值  =
阻塞赋值是顺序执行的。在一个begin - end块中,多条阻塞赋值语句按照顺序依次执行,下一条语句会等待当前阻塞赋值语句执行完成后才开始执行。例如:
always @(posedge clk) begin
    a = b;
    c = a;
end
当clk上升沿到来时,先执行a = b,将b的值赋给a,然后执行c = a,此时a已经更新为b的值,所以c得到的是更新后的a(也就是b的值)。

应用场景:
常用于组合逻辑电路建模,特别是在需要按照特定顺序进行计算的组合逻辑中。例如,在实现一个简单的算术逻辑单元(ALU)的组合逻辑部分时,按照运算优先级进行计算就可以使用阻塞赋值。
还用于initial块中初始化变量,因为initial块主要是顺序执行的初始化代码,例如:
initial begin
    reg_a = 0;
    reg_b = 1;
end

对仿真的影响:
在仿真过程中,由于阻塞赋值是顺序执行的,所以赋值语句的执行顺序会直接影响变量的值和仿真结果。如果赋值顺序不当,可能会导致不符合预期的结果。
例如,如果在组合逻辑中有相互依赖的阻塞赋值,可能会出现竞争冒险(race condition)现象,导致输出出现毛刺(glitch)。
c 复制代码
非阻塞赋值  <=
非阻塞赋值是并发执行的。在一个always块中,所有非阻塞赋值语句在同一时刻开始计算表达式的值,但赋值操作会在当前时间步(time step)结束时同时更新目标变量。例如:
always @(posedge clk) begin
    a <= b;
    c <= a;
end
当clk上升沿到来时,a <= b和c <= a这两个赋值语句会同时开始计算右侧表达式的值。此时计算c <= a时,a的值是更新前的值,等到这个always块执行结束后,a和c才会同时更新。所以c得到的是a的旧值。

应用场景:
主要用于对时序逻辑电路进行建模,特别是在多个寄存器之间需要传递数据,并且这些寄存器的更新应该在时钟沿触发后同时进行的情况。例如,在一个简单的移位寄存器设计中:
always @(posedge clk) begin
    reg1 <= in_data;
    reg2 <= reg1;
    reg3 <= reg2;
end

对仿真的影响:
非阻塞赋值在仿真时会在每个时间步结束时更新所有被赋值的变量,这样可以更好地模拟实际硬件中的寄存器等时序元件的行为。
有助于避免在时序逻辑建模中因为赋值顺序不当而产生的错误,但如果在组合逻辑中错误地使用非阻塞赋值,也可能会导致意想不到的结果,因为组合逻辑通常期望是立即更新输出的。

使用 = ,直接结果是后续仿真的时候高电平只持续了1个周期,即20ns就又变为低电平

使用<=,则可以实现500.00002ms一反转

为什么是500.000002ms,因为计数是从0开始,计数到25000000时候多计数了一个周期,即20ns,这里需要把计数改为24999999就OK

用到的语法

c 复制代码
 always@(posedge Clk or negedge Reset_n)//当时钟(Clk)的上升沿或者复位(Reset_n)的下降沿时候,这个代码块工作,其他时候不工作。
c 复制代码
counter <= 0;//counter清零,<=是非阻塞赋值的意思
c 复制代码
counter=counter + 1'd1;//counter自加1

2、分析综合

3、仿真模拟

最终在module为以下情况下,进行仿真

得出下图:即高低电平切换时间为500ms

4、 IO设定

按键

LED灯

时钟引脚为Y18

5、生成程序、板级调试

2024.12.23

相关推荐
Erik_LinX7 分钟前
day1-->day7| 机器学习(吴恩达)学习笔记
笔记·学习·机器学习
魔理沙偷走了BUG9 分钟前
【Linux笔记】Day5
linux·笔记
索然无味io22 分钟前
组件框架漏洞
前端·笔记·学习·安全·web安全·网络安全·前端框架
珊瑚里的鱼37 分钟前
【单链表算法实战】解锁数据结构核心谜题——环形链表
数据结构·学习·程序人生·算法·leetcode·链表·visual studio
林涧泣38 分钟前
图的矩阵表示
学习·线性代数·矩阵
chimchim661 小时前
【starrocks学习】之catalog
学习
Jackilina_Stone2 小时前
【论文阅读笔记】“万字”关于深度学习的图像和视频阴影检测、去除和生成的综述笔记 | 2024.9.3
论文阅读·人工智能·笔记·深度学习·ai
梦云澜2 小时前
论文阅读(二):理解概率图模型的两个要点:关于推理和学习的知识
论文阅读·深度学习·学习
Ronin-Lotus2 小时前
上位机知识篇---CMake
c语言·c++·笔记·学习·跨平台·编译·cmake
lxl13072 小时前
学习数据结构(2)空间复杂度+顺序表
数据结构·学习