文章目录
- 前言
- 一、树莓派简介
- 二、整体实现步骤
- 三、树莓派设置
- 四、树莓派串口代码
- 五、Verilog代码
- 5.1 串口接收模块
- 5.2 流水灯模块
- 六、quartus引脚绑定
- 七、 运行效果
- 总结
- 参考
前言
本次实验的目的是通过树莓派和FPGA之间的串口通信,控制FPGA开发板上的小灯。实验将展示如何使用树莓派发送特定的字符信号,通过串口传输至FPGA,并在FPGA上实现逻辑解析,以点亮指定的小灯。这不仅验证了树莓派与FPGA之间的通信能力,也展示了数字逻辑设计在实际应用中的灵活性。
实验器材:
DE2-115开发板
树莓派
一、树莓派简介
树莓派是什么?
树莓派(Raspberry Pi)是尺寸仅有信用卡大小的一个小型电脑,您可以将树莓派连接电视、显示器、键盘鼠标等设备使用。
树莓派能替代日常桌面计算机的多种用途,包括文字处理、电子表格、媒体中心甚至是游戏。并且树莓派还可以播放高至 4K 的高清视频。
我们希望将树莓派推广给全世界的青少年电脑爱好者,用于培养计算机程序设计的兴趣和能力。
树莓派各版本发布时间和差异对照:
二、整体实现步骤
-
1.使用一个FPGA开发板和一个串口通信模块(如UART)来进行通信。确保开发板上有足够的GPIO引脚可用于连接流水灯。
-
2.在FPGA开发环境中创建一个新项目,并为其添加一个顶层模块。这个顶层模块将负责接收串口数据,并控制流水灯的状态。
-
3.在顶层模块中添加一个串口接收器模块,用于接收来自串口通信模块的数据。您可以使用FPGA开发环境提供的现成模块,或者自己编写一个。
-
4.在顶层模块中添加一个计数器,用于控制流水灯的状态。每当接收到串口数据时,计数器会更新,并根据其值来控制流水灯的亮灭。
-
5.添加一个输出模块,将计数器的值连接到流水灯所需的GPIO引脚上。确保配置正确的约束文件,以确保引脚映射正确。
-
6.编译和烧录FPGA,并将串口通信模块连接到计算机上。您可以使用串口终端程序来发送数据给FPGA。
-
7.当串口接收器接收到数据时,计数器将更新,并相应地控制流水灯的状态。
三、树莓派设置
1、首先确认波特率设置正确,是否为115200。(当然,其他波特率也可以的,不过代码得改一下
2、向microSD卡中烧录树莓派官方的镜像后,先不要急着把它插入树莓派中。
3、在电脑上打开microSD卡,按如下方式修改config.txt和cmdline.txt这两个文件,在config.txt文件中附加
dtoverlay=pi3-miniuart-bt
在电脑里直接打开比在树莓派里打开要好操作,不用获取权限
然后把cmdline.txt中的内容换成
dwc_otg.lpm_enable=0 console=tty1 console=serial0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
修改完成之后,我们打开树莓派
进入到树莓派的命令行当中进行如下操作
在命令行中输入如下命令
sudo chmod 777 /dev/ttyAMA0
这里要先获取权限,否则后面代码会报错
四、树莓派串口代码
fpgaUart.c
#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>
int main()
{
int fd =serialOpen("/dev/ttyAMA0",115200); //打开串口
if(fd == -1){ //如果打开串口失败则退出程序
printf("serialOpen failed!\n");
return 0;
}
printf("serialOpen success!\n");
while(1){
serialPrintf(fd,"A");
delay(2000);
serialPrintf(fd,"B");
delay(2000);
}
return 0;
}
编译命令
gcc -o fpgaUart fpgaUart.c -lwiringPi
五、Verilog代码
5.1 串口接收模块
uart_rx.v
module uart_rx (
input clk ,
input rst_n ,
input din , //pc端发送给FPGA的数据
output reg [7:0] dout , //发送给tx 让他串行的传出去
output reg dout_vld //当这一次8bit接收完成 再传给tx
);
parameter BAUD = 434 ; //使用波特率115200 发送1bit所需要的时钟周期
reg [8:0] cnt_bsp ;
wire add_cnt_bsp ;
wire end_cnt_bsp ;
reg [3:0] cnt_bit ; //计数当前到了哪一bit了 计数9bit 起始位加上数据
wire add_cnt_bit ;
wire end_cnt_bit ;
reg din_r0 ; //同步到时钟上升沿
reg din_r1 ; //打拍 延时一个时钟周期
wire nedge ; //下降沿
reg flag ; //计数器计数的标志 下降沿到来之后开始计数 传输数据完成了就停止计数
reg [8:0] data ; //寄存数据
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bsp <= 9'b0;
end
else if(add_cnt_bsp)begin
if(end_cnt_bsp)begin
cnt_bsp <= 9'b0;
end
else begin
cnt_bsp <= cnt_bsp + 1'b1;
end
end
else begin
cnt_bsp <= cnt_bsp;
end
end
assign add_cnt_bsp = flag;
assign end_cnt_bsp = add_cnt_bsp && cnt_bsp == BAUD - 1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bit <= 4'b0;
end
else if(add_cnt_bit)begin
if(end_cnt_bit)begin
cnt_bit <= 4'b0;
end
else begin
cnt_bit <= cnt_bit + 1'b1;
end
end
else begin
cnt_bit <= cnt_bit;
end
end
assign add_cnt_bit = end_cnt_bsp;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 8; //起始位加上8bit数据位
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
din_r0 <= 1'b1;
din_r1 <= 1'b1;
end
else begin
din_r0 <= din;
din_r1 <= din_r0;
end
end
assign nedge = ~din_r0 & din_r1;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
flag <= 1'b0;
end
else if(nedge)begin
flag <= 1'b1;
end
else if(end_cnt_bit)begin
flag <= 1'b0;
end
else begin
flag <= flag;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
data <= 9'b0;
end
else if(cnt_bsp == (BAUD >> 1) && flag)begin
data[cnt_bit] <= din; //串并转换 LSB
end
else begin
data <= data;
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
dout <= 8'b0;
dout_vld <= 1'b0;
end
else if(end_cnt_bit)begin
dout <= data[8:1]; //第0位是起始位 舍弃掉
dout_vld <= 1'b1;
end
else begin
dout <= dout;
dout_vld <= 1'b0;
end
end
endmodule
5.2 流水灯模块
led.v
module led (
input clk,
input rst_n,
input tx,
output reg[7:0] led
);
wire [7:0] dout;
wire dout_vld;
uart_rx uart_rx_inst (
.clk (clk),
.rst_n (rst_n),
.din (tx),
.dout(dout),
.dout_vld (dout_vld)
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
led <= 8'b0;
end
else begin
case (dout)
8'h41 : led <= 8'b0000_0001;
8'h42 : led <= 8'b0000_0010;
default: led <= led;
endcase
end
end
endmodule
六、quartus引脚绑定
可以选择其它灯,看数据手册
七、 运行效果
总结
实验概述
在本次实验中,我们成功地通过树莓派与FPGA之间的串行通讯,实现了对FPGA开发板上LED灯的控制。该实验展示了树莓派作为控制端与FPGA结合的潜力,以及数字逻辑设计在工程实践中的应用价值。
技术实现
- 串口通讯:实验利用树莓派的串行通讯接口与FPGA进行数据传输,这是实现远程控制的核心环节。
- 信号解码:FPGA上的逻辑电路能够准确地解析来自树莓派的信号,确保了控制指令的准确执行。
- 硬件配置:实验中对树莓派与FPGA之间的物理连接进行了严格的检查,确保了串口线路和电源供应的稳定性。
问题与解决策略 - 通讯稳定性问题:面对串口通讯过程中出现的不稳定现象,我们通过调整通讯波特率和仔细检查串口线路来确保通讯的可靠性。
逻辑设计缺陷:在FPGA的逻辑设计阶段,我们遇到了信号解析的误差,通过细致的复查和调试,最终修正了逻辑电路。
实验反思
本次实验不仅加深了我们对树莓派和FPGA硬件特性的理解,还提升了我们在通信技术和数字逻辑设计方面的实践技能。在解决实验中遇到的挑战时,我们的问题分析与解决能力得到了显著提升,同时对微控制器编程和系统集成有了更深入的认识。
通过这次学习经历,我们认识到了理论与实践相结合的重要性,并体会到了在解决复杂工程问题时,耐心和细致的必要性。
参考
树莓派对FPGA板子上的流水灯程序的控制
树莓派点亮FPGA小灯
【树莓派初始化】教你从0开始搭建树莓派的使用环境