FPGA基础入门【11】开发板USB-UART串口通信配置

上一篇教程介绍了NEXYS4 开发板中DDR2的使用方式,这一篇介绍不可或缺的网络接口RJ45在FPGA开发板中的使用

FPGA基础入门【11】开发板USB-UART串口通信配置

  • 开发板串口芯片
  • 逻辑设计
    • 源代码
  • 模拟仿真
    • Testbench
    • 仿真脚本
      • 仿真结果
  • 编译测试
    • 结果观察
  • 总结

开发板串口芯片

NEXYS 4开发板自带一根USB mini-B线,在板子上的接口上写着PROG_UART,就是程序烧写和UART串口通信通用接口复用的。

用来实现串口通信的芯片名称是FTDI(Future Technology Devices International) FT2232HQ,它的文档链接在此:datasheet

NEXYS 4文档中写着,为了实现和FPGA的串口通信,还需要下载一个VCP(Virtual Com Port)驱动。各种不同的平台需要的软件可以从这个网站找到,我下载的是Windows x64:www.ftdichip.com。记得要点击右边的setup executable来下载安装,而不是点击版本号(为什么一定要做这么麻烦):懒人链接

但是我用Putty可以直接收发数据,并没有多大问题,可以跳过VCP驱动这一步直接开始

在开发板中FTDI和FPGA的连接如下:
FPGA基础入门【11】开发板USB-UART串口通信配置_第1张图片
TXD和RXD分别是串行收发信号,RTS是Require ToSend,CTS是Clear ToSend,作为连接时候的握手信号。从这里发现,这个接口没用提供任何控制配置接口,只有数据接口。它意味着初始配置由其他结构控制,我们只能使用它。因此这次我们不具体研究FTDI芯片的细节。

串口的时序如下
FPGA基础入门【11】开发板USB-UART串口通信配置_第2张图片
图中用的波特率是9600,但我们用的是115200bps。发送以10位为一个单位,第一位拉低表示开始,接着八位从数据的低位开始直到最高位,最后把电平拉高表示结束。至于CTS和RTS,它们是低电平有效,平时是高电平,在有数据从PC发给FPGA时,就会把RTS拉低,这时需要把CTS拉低做回应。

逻辑设计

这篇教程的计划是,看到RTS拉低,就相应的把CTS拉低做回应,然后循环传回提前指定好的数据。

源代码

module uart(
    input       clk,
    input       rst,
    output reg  led,
    
    // UART port
    input       RXD,
    output reg  TXD,
    output reg  CTS,
    input       RTS
);

接口定义,LED接在RTS上,看是否有信号从PC传来

(* dont_touch = "true" *)reg  RXD_d;
(* dont_touch = "true" *)reg  RTS_d;
reg [15:0] tx_count;
reg [39:0] tx_shift;

always @(posedge clk or posedge rst) begin
	if(rst) begin
		RXD_d <= 1'b0;
		RTS_d <= 1'b0;
	end
	else begin
		RXD_d <= RXD;
		RTS_d <= RTS;
	end
end

把RXD和RTS接到的数据保存下来,到chipscope中观察

always @(posedge clk or posedge rst) begin
    if(rst) begin
        TXD <= 1'b1;
		tx_shift <= {10'b0011000101, 10'b0101010101, 10'b0110000101, 10'b0110100101};
    end
    else begin
		if(tx_count < 16'd867) begin
			tx_count <= tx_count + 16'd1;
		end
		else begin
			tx_count <= 16'd0;
		end
		
		if(tx_count == 16'd0) begin
			TXD <= tx_shift[39];
			tx_shift <= {tx_shift[38:0], tx_shift[39]};
		end
    end
	
	if(rst) begin
		CTS <= 1'b1;
	end
	else begin
		CTS <= 1'b0;
	end
end

保持CTS低电位,持续循环输出提前设置好的数据。具体数据内容可以参考UTF-8表格,注意把码反过来。比如说字母F的UTF-8码是0x46=8’b01000110,那么反过来再加上头尾就变成了10’b0011000101

always @(posedge clk or posedge rst) begin
    if(rst) begin
        led <= 1'b0;
    end
    else begin
        led <= RTS;
    end
end

endmodule

模拟仿真

Testbench

Testbench如下:

`timescale 1ns/1ns

module tb_uart;

reg  clock;
reg  reset;
wire led;

reg  RXD;
wire TXD;
wire CTS;
reg  RTS;

定义资源

initial begin
    clock = 1'b0;
    reset = 1'b0;
    RXD = 1'b1;
    RTS = 1'b1;
    // Reset for 1us
    #100 
    reset = 1'b1;
    #1000
    reset = 1'b0;
    #10000
    RTS = 1'b0;
    repeat(10) begin
        #867;
        RXD = ~RXD;
    end
end

// Generate 100MHz clock signal
always #5 clock <= ~clock;

初始化信号,生成时钟,并且在最开始给予一个字符

uart uart(
    .clk (clock),
    .rst (reset),
    .led (led),
    
    // UART port
    .RXD (RXD),
    .TXD (TXD),
    .CTS (CTS),
    .RTS (RTS)
);

endmodule

仿真脚本

再写一个仿真脚本sim.do:

vlib work
vlog ../src/uart.v ./tb_uart.v
vsim work.tb_uart -voptargs=+acc +notimingchecks
log -depth 7 /tb_uart/*
#do wave.do
run 1ms

仿真结果

打开ModelSim,将路径切换到仿真文件夹后,调用脚本do sim.do,加入相应信号,结果如下:
waveform
可以看出TXD和CTS在输出期望中的信号

编译测试

新建一个叫uart的project,初始配置可以参考之前的教程。添加代码文件uart.v

下一步加入约束constraint文件uart.xdc,同样这是用标准模板取自己需要部分修改出来的(NEXYS 4 DDR Master XDC):

## This file is a general .xdc for the Nexys4 DDR Rev. C
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used ports (in each line, after get_ports) according to the top level signal names in the project

## Clock signal
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]


##Switches

set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports rst]


## LEDs

set_property -dict {PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports led]

##USB-RS232 Interface

set_property -dict {PACKAGE_PIN C4 IOSTANDARD LVCMOS33} [get_ports RXD]
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports TXD]
set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33} [get_ports CTS]
set_property -dict {PACKAGE_PIN E5 IOSTANDARD LVCMOS33} [get_ports RTS]

到这里可以点击 Run Synthesis做综合,几秒钟完成后用Set Up Debug配置ChipScope:
FPGA基础入门【11】开发板USB-UART串口通信配置_第3张图片
设置观察长度为8192,因为串口的频率是115200Hz,和时钟频率比起来很低,需要多观察一段时间。下面就可以Run Implementation和Generate Bitstream生成配置文件了。

和前面的教程一样,USB线连接NEXYS4板子,开启Hardware Manager,然后auto连接上板子,Program Device烧写进程序,注意Debug probes file有对应的ltx文件。

结果观察

现在我们要配置PC端的串口通信软件,就像前面说的,我推荐使用Putty,简单好用,其他很多地方可以用,下载链接就不附了,可以自己找。配置如下:
putty 1
这里具体用哪个串口COM是可以在设备管理器device manager里看到的,如果找不到,你可以拔一下开发板的USB,看一下哪个消失了,我这里是COM4。
putty 2
还有一个需要配置的要到左侧Connection -> Serial里,按照图中来配置。到这里就可以开启了。emmmmmmm:
FPGA基础入门【11】开发板USB-UART串口通信配置_第4张图片
再来配置ChipScope的配置,trigger配置成RTS,这个信号平时是高电平,拉低代表着收到有效信号。开启捕捉后,可以重开一次putty,因为刚刚连接的时候会给一个有效信号,在ChipScope中看到的信号是这样的:
FPGA基础入门【11】开发板USB-UART串口通信配置_第5张图片

总结

这一篇教程相对短一些,因为串口是作为低速低复杂度的点对点传输,主要存在的意义就是方便传输低速信号,将来做一些需要传回复杂字符数据的时候就可以调用相应代码。

下一篇介绍如何使用开发板上的USB接口,接收键盘和鼠标的信号

你可能感兴趣的:(FPGA)