时间:2025年1月7日11:08:49


0.FPGA简介

芯片的简称叫:IC

芯片分类:

1、ASIC(专用集成电路):是一种在设计时就考虑了设计用途的IC。

2、FPGA(现场可编程门阵列):是一种可以进行重新编程设计的IC

FPGA可以通过重新编程来修改芯片内部逻辑连接和配置让这个芯片实现你自己想要的功能。

什么是ICT?

计算机半导体通信大类

  • IT
  • IC
  • CT

wire | n.金属线

FPGA的开发:verilog HDL语言

数字信号处理领域:(模拟信号转化为数字信号)软件无线电技术

FPGA生产厂商

1、Xilinx(赛灵思):是全球领先的可编程逻辑完整解决方案的供应商,也是全球PGA市场份额最大的公司,目前被AMD收购。市场占比最高。提供的主要开发平台:Vivado

2、Altera(阿尔特拉),业界与Xilinx齐名的FPGA供应商,2015年被Intel收购。市场占比排第二。提供的主要开发平台:QuartusII。

3、Lattice(莱迪思),以其低功耗产品著称,Lattice公司是目前唯一一家在中国有研发部的外国FPGA厂商,也为国产FPGA厂商培养了很多业内优秀的管理人员和技术人,当年国内企业欲收购Lattice,而被美国以违反国家安全的名义否决了收购计划,使国产FPGA商业化还要走更长的路。

4、京微齐力、国微电子、711所、复旦微电子、华微电子、紫光同创等

1.创建新项目

1
2
3
4
5
项目存放的绝对路径

填写与.qbf相同的名字

与第二行保持一致

器材设备

1
2
选择自己使用的设备
本例为:EP4CE6F17C8

EP4CE6F17C8

EP:表示该芯片属于 Cyclone IV FPGA 系列。EP 是 Cyclone FPGA 的前缀。

4:表示这是 Cyclone IV 系列中的一个器件。Cyclone IV 是英特尔较低功耗、低成本的 FPGA 系列。

CE:指的是该 FPGA 采用的是 Cyclone IV E 系列。Cyclone IV E 是 Cyclone IV 系列中的一个子系列,优化了性能和容量。

6:表示该 FPGA 的逻辑单元(LE,Logic Element)数量。数字 6 通常代表这个 FPGA 的资源规模是 6K 逻辑单元。

F:表示该 FPGA 使用的是 Fine-pitch Ball Grid Array (FBGA) 封装。F 是指 FBGA 类型封装,用于更小尺寸和更高密度的应用。

17:代表该芯片的 I/O 引脚数。数字 17 表示该 FPGA 有 17x17 的引脚阵列(共 289 引脚),具体的引脚配置会影响外部连接能力。

C8:表示该 FPGA 的 温度范围和速度等级。C8 通常代表该 FPGA 在 商业温度范围(0°C 到 85°C) 和中等速度等级下工作。

2.not_gate[非门]

设计输入输出

创建工程

tools>Netlist views>RTL view

波形图的文件:tb.v

not_gate.v

1
2
3
4
5
6
7
8
9
10
module not_gate(               //模块 模块名
input wire A , //括号中逗号作为结尾

output wire Y //括号中的最后一行不用逗号
);

//组合逻辑:输出随输入改变立刻改变,RTL视图综合出来是一根导线
assign Y = ~A ; //assign用于赋值

endmodule // 结束模块

image-20250106161416230

顶层

image-20250106173159787

仿真测试:

tb_not_gate.v

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
`timescale 1ns/1ps //时间单位,1纳秒、1皮秒,后续若不写默认是纳秒为单位

/*
module tb_not_gate();
wire A ;

wire Y ;
*/

module tb_not_gate();
reg A ;

wire Y ;

/*
被赋值的参数遇到ini或者alw要改为寄存器reg型
*/

initial begin
A=0;
end

always #10 A = {$random}%2 ; //添加大括号去掉负数 .对2取余,数字范围是0~1,对16取余就是0~15

//打点 例化名 传参
not_gate not_gate_inst(
. A(A) ,//括号中的参数来自于当前模块

. Y(Y) //括号中的最后一行不用逗号
);


endmodule

选择tb文件

image-20250106173339172

image-20250106173959213

3.key_led

一个按键点亮一个灯

绑定管脚、点亮灯(需要确定是高电平还是低电平点亮)

首先看原理图分析驱动方式
image-20250107092502464

led灯为0亮,1灭

按键的原理图

image-20250107092813118

key_led.v

1
2
3
4
5
6
7
8
9
10
module key_led(
input wire key0,

output wire led0
);

//led和key都是低电平有效
assign led0=key0 ;

endmodule

image-20250107095409219

根据原理图绑定管脚

image-20250107100834630

看原理图,key绑定按键,led绑定灯

  • led原理图

image-20250107100453278

  • key原理图

image-20250107101457215

绑定完成后再编译一次

随后进行如下设置:

选择.sof文件

image-20250107095835762

等连接设备以后,点击Hardware Setup...

点击star进行烧录

仿真测试

tb.v

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
`timescale 1ns/1ps //时间单位,1纳秒、1皮秒,后续若不写默认是纳秒为单位


module tb();
reg key0;

wire led0;

/*
被赋值的参数遇到ini或者alw要改为寄存器reg型
*/

initial begin

key0=0; //给予低电平

end

always #10 key0 = {$random}%2 ; //添加大括号去掉负数 .对2取余,数字范围是0~1,对16取余就是0~15

//打点 例化名 传参
key_led key_led_inst(
. key0(key0) ,//括号中的参数来自于当前模块

. led0(led0) //括号中的最后一行不用逗号
);


endmodule

仿真结果正确

image-20250107103229325

4.调制解调

毛刺:干扰信号:竞争冒险

解决竞争冒险

1,时间顺序读取(去掉)

2,填充(找到上一时刻。保持上一时刻的状态,保持的时长为毛刺长度)

3,时间的来源:( 晶振-> 频率- > 周期-> <傅里叶变换> 时间)

10下降沿,01上升沿

D触发器(晶振的最小时间单元)D_FLIP_FLOP

  • 具有记忆性
  • 具有两个稳定状态
  • 信息存储单元

边沿触发的标志

  • 上升沿触发:向右的三角形,在上升沿之间进行采样,看是高电平还是低电平
  • 下降沿触发:在下降沿之间进行采样,看是高电平还是低电平

组合逻辑:即时触发

时序逻辑:时序触发

创建d触发器

频率50mhz ,周期是20纳秒

时序的实现

状态机

序列检测:

设置一个计数器,如果遇到序列第一个,此计数器加1,再检测下一个,如果仍然满足序列的第二个,则继续加一,若不是序列的第二个则减去一(有的不是,需要具体分析状态机),直到计数器达到序列自身长度

如何寻找10010这一行,例如:接收到10010时才给出一个周期的高电平

1
2
3
Moore状态机:输出只取决于当前状态,与输入状态无关,有S4

Mealy状态机:输出不仅取决于当前状态,还和输入有关

重复检测

image-20250108142712411

1
2
3
4
5
6
7
如果data==1
state <=S0
否则
state <=S


if (state == s4)

state2.v

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
module state2(
input wire clk,
input wire rdt_n,
input wire state_out,
input reg find

);
parameter IDLE =6'000_001 ; //二进制编码,独热码
parameter s0 =6'000_010 ; //二进制编码,独热码
parameter s1 =6'000_100 ; //二进制编码,独热码
parameter s2 =6'001_000 ; //二进制编码,独热码
parameter s3 =6'010_000 ; //二进制编码,独热码
parameter s4 =6'100_001 ; //二进制编码,独热码

reg [5:0] state; //状态寄存器

//二段式状态机:第一段描述状态转移,第二段描述状态输出
always @ (posedge clk , negedge rst_n)
if(~rst_n)
state <= IDLE ;
else case (state)
IDLE : if(data==1)
state <= s0 ;
else
state <= IDLE ;
s0 : if(data==0)
state <= s1 ;
else
state <= s0 ;
s1 : if(data==0)
state <= s2 ;
else
state <= s0 ;
s2 : if(data==1)
state <= s3 ;
else
state <= IDLE ;
s3 : if(data==0)
state <= s4 ;
else
state <= s0 ;

s4 : if(data==0)
state <= s2 ; //重复检测100
else
state <= s0 ;

default : state <= state;
endcase

always @ (posedge clk , negedge rst_n)//状态输出
if(~rst_n)
find <= 0 ;
else if (state == s4)
find <= 1 ;
else
find <= 0 ;

endmodule

UART总线

三大低速总线(UART、 SPI、 IIC)

RXD:接收数据

TXD:发送数据

串口的协议之一:RS232

串口的帧结构(一个最基本的 RS232 帧结构)

8位宽数据,每一位都是1bit

img

1bit持续的时间为波特率(baud),常用4800、9600

比特率:1秒钟发送了多少个bit

比特率=波特率 * 单个调制状态对应的二进制位数,如果使用的是 9600 的波特率,其串口的比特率为:

1
9600Bps *1bit= 9600bps。

bps = bit/s

由计算得串口发送或者接收 1bit 数据的时间为一个波特,即 1/9600 秒,如果用
50MHz(周期为 20ns)的系统时钟来计数,需要计数的个数为 cnt = (1s * 10^9)ns /
9600bit)ns / 20ns ≈ 5208 个系统时钟周期,即每个 bit 数据之间的间隔要在 50MHz 的时钟频率下计数 5208 次(13位宽)。
$$
2^{13}
$$

位拼接

组合逻辑中的毛刺叫:竞争冒险

时序逻辑中的毛刺叫:亚稳态

bit_cnt ==8 && bit_flag==1的时候,work_en 拉低

image-20250109155739685

uart_rx.v

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
module uart_rx 
#(
parameter CNT_MAX = 50_000_000/9600
)
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire rx ,

output reg [7:0] po_data ,
output reg po_flag
);

reg rx_reg1 ;
reg rx_reg2 ;
reg rx_reg3 ;
reg start_nedge ;
reg bit_flag ; //5208/2-1最稳定,取走
reg [3:0] bit_cnt ; //记录8个bit数据
reg work_en ;
reg [12:0] baud_cnt ;
reg [7:0] rx_data ; //拼接
reg rx_flag ; //出稳定数据

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n) //~sys_rst_n sys_rst_n==0
begin
rx_reg1 <= 1'b1; // 并行赋值
rx_reg2 <= 1'b1;
rx_reg3 <= 1'b1;
end
else
begin
rx_reg1 <= rx; //原本的信号给下一个寄存器
rx_reg2 <= rx_reg1;
rx_reg3 <= rx_reg2;
end
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
start_nedge <= 1'b0; //下降沿开始信号
else if ((~rx_reg2) && (rx_reg3))
start_nedge <= 1'b1;
else
start_nedge <= 1'b0;
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
bit_flag <= 1'b0;
else if(baud_cnt == CNT_MAX/2 - 1) //CNT_MAX >> 1
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
bit_cnt <= 4'b0; //bit计数器清零
else if(bit_cnt == 4'd8 && bit_flag == 1'b1) //bit计数器计数到8,并且bit_flag为1时,bit计数器清零
bit_cnt <= 4'b0;
else if(bit_flag)
bit_cnt <= bit_cnt + 1'b1;
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n) //sys_rst_n==0 时
work_en <= 1'b0;
else if(start_nedge)
work_en <= 1'b1;
else if(bit_cnt == 4'd8 && bit_flag == 1'b1) //bit计数器为8,且bit_flag为1时
work_en <= 1'b0; //工作使能为0
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
baud_cnt <= 13'b0; //波特计数器清零
else if((baud_cnt == CNT_MAX - 1) || work_en == 1'b0) //work_en为0时,波特计数器清零,或者波特计数器达到最大值时,波特计数器清零
baud_cnt <= 13'b0;
else if(work_en == 1'b1)
baud_cnt <= baud_cnt + 1'b1;//波特计数器加1
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rx_data <= 8'b0;
else if(bit_cnt >= 4'b1 && bit_cnt <= 4'd8 && bit_flag == 1'b1)
rx_data <= {rx_reg3,rx_data[7:1]};
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
rx_flag <= 1'b0;
else if(bit_cnt == 4'd8 && bit_flag)
rx_flag <= 1'b1;
else
rx_flag <= 1'b0;
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
po_data <= 8'b0;
else if(rx_flag == 1'b1)
po_data <= rx_data;
end

always @ (posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
po_flag <= 1'b0;
else
po_flag <= rx_flag;
end


endmodule

得出的电路图如下:

image-20250109161004346

end

位宽以该数的二进制位数为准

串口的数据接收和发送

tx:主机发送

rx:经过判断语句,若符合条件则返回一个信息

串口调试助手中显示的tx,rx都是在主机这一侧的,

”32位宽的16进制数44556677“ 的写法

1
32'h44556677

不描述状态转移,使用拼接方式

模块名:led

状态机的第十三种写法:拼接

default

case既有选择也有begin的用法

状态机类型:摩尔型(有s4)、米粒型

三位宽格雷码的全部表示内容

串行并行转换