FPGA串口控制led

硬件介绍

硬件型号:Artix-7 MA703-35T

FPGA型号: Artix-7 XC7A35T FGG484

SPEED: -2

项目代码

已上传到gitlab:http://limfx.pro:23080/zhdyz/uart_led_cmd

功能描述

本模块在MA703-35T开发板上实现了串口通讯,命令解析及控制led的亮灭功能

可以通过USB线将开发板与上位机连接,然后通过串口调试助手进行命令收发,控制班上4个led灯的亮灭

基本命令

本模块规定设置了两种命令:GET 和 SET

GET

发送的第一个字节为00表示GET命令,GET命令为4个字节

  • 第一个字节代表命令类型

  • 第二个字节代表查询led的编号,范围为0003

  • 第三和第四个字节共同表示校验和,为前两个字节所加的和

例 查询编号为0的led灯的亮灭状态

00 00 00 00

例 查询编号为3的led灯的亮灭状态

00 03 00 03

SET

发送的第一个字节为01表示GET命令,SET命令为7个字节

  • 第一个字节代表命令类型

  • 第二个字节到第五个字节代表设置对应led灯的状态,00为熄灭,01为点亮

  • 第六和第七个字节共同表示校验和,为前五个字节所加的和

例 设置4个led灯全亮

01 01 01 01 01 00 05

例 设置中间两个led灯亮

01 00 01 01 00 00 03

模块实现

all_design

CLK_Wizard

这是一个IP核调用

功能是将输入的clk变成不同频率的clk输出

clk_wiz_50mTo100m clk_wiz
(
    .clk50m(clk),
    .clk100m(clk100mhz),
    .resetn(rstn),
    .locked(locked)
);

波特率时钟分频器

生成波特率为9600所需的时钟频率

baud_rate_gen clk100mTo9600(
    .clk(clk100mhz),          
    .rst(rstn),             
    .baud_x16_en(baud16x)  
);

UART_Receiver

串口接收模块

Receiver Recv(
    .baud16x(baud16x),
    .rstn(rstn),
    .recv(uart_rx),
    .rdata(RecvRdata),
    .recv_ready(RecvReady),
    .rdata_valid(RecvValid)
);

toFIFO

将串口接收到的数据进行检验,以及输出重要的控制信息

 Recv_To_FIFO ToFIFO(
    .rdata(RecvRdata),
    .rdata_valid(RecvValid),
    .baud16x(baud16x),
    .rstn(rstn),
    .FIFOWrEn(FIFOWren),
    .OneCMDEnd(OneCMDEnd) ,
    .newCMDTYPE(newcmdtype),
    .StartWriteFIFO(startwritefifo),
    .WriteFIFOData(writefifodata)
);  

FIFO

这是一个IP核调用

功能是缓存命令

FIFO_Gen FIFO (
  .clk(baud16x),               // input wire clk
  .rst(rstn),                  // input wire rst
  .din(writefifodata),         // input wire [7 : 0] din
  .wr_en(FIFOWren),            // input wire wr_en
  .rd_en(FIFOrden),            // input wire rd_en
  .dout(FIFODout),             // output wire [7 : 0] dout
  .full(),                     // output wire full
  .empty(),                    // output wire empty
  .data_count(FIFOdatacount),  // output wire [6 : 0] data_count
  .wr_rst_busy(),              // output wire wr_rst_busy
  .rd_rst_busy()               // output wire rd_rst_busy
);

LED_Control

根据toFIFO输出的控制信息和FIFO输出的命令,解析命令

如果是SET命令则控制led信号的输出

如果是GET命令则读取led信号并通过串口发送模块输出

led led_inst(
 .clk(clk100mhz),
 .rstn(rstn),
 .StartWriteFIFO(startwritefifo),
 .NewCMDTYPE(newcmdtype),
 .CMDByte(FIFODout),
 .FIFORdEn(FIFOrden),
 .Transdata(TransData),
 .transWren(transwren),
 .led(led)
);

UART_Transmitter

串口发送模块

Transmitter Trans(
    .DataIn(TransData),//并行数据输入
    .baud16x(baud16x),//baud16x=波特率×16
    .TxEn(transwren),//TxEn是并行数据装入使能信号
    .rstn(rstn),//rstn复位信号
    .DataOut(uart_tx),//串行数据输出
    .TxBusy()// 说明串口正忙的信号,检测其下降沿就可以判断是否可以装入新的数据
);

功能测试

经测试,GET/SET指令都能正常完成其功能

错误反思

实验过程中犯了许多错误,在此记录

错误1.

代码写好后,进行综合实现生成比特流上载,但板上测试无响应,故回到软件写testbench,进行仿真测试

一个个功能模块逐个测试后发现是FIFO的使用出现问题

其他模块都是的复位都使用低电平复位,而FIFO是使用高电平复位的,而我之前直接给FIFO输入rstn信号,故FIFO一直处于复位状态

将FIFO的复位信号取反即可

错误2

在进行仿真测试写testbench时,不小心把一个模块输入的变量名写错了(clk写成clk_100m)

然后这时候点仿真,不会出现报错,而是正常进入仿真,但是就是仿真信号与预期不一致

排查了很久,才发现原来是变量名错误,导致一个模块输入的信号一直为空

引以为戒,一定要仔细检查变量名是否正确,因为软件不会提示!


本文章使用limfx的vscode插件快速发布