因为要用到串口方面的模块,对此一无所知,网上搜到一个最初级的入门demo,照着做了一下,对串口有了初步的认识,下面是实验内容。
首先我们要知道,nexys3上面是-用USB接口来实现异步串行通信协议,我们来看一下参考手册中的介绍:
连接接口跟FPGA的是一块FT232,而文字描述第一句话的意思就是这块FT232允许PC与开发板之间通过标准的Windows COM端口进行通信。原来如此,就是这么一块小小的芯片帮助我们完成了串行通信协议到USB协议之间的转换。这块芯片具体的工作原理我们暂且不去深究,对于我们这个开发来说,我们只需要搞清楚怎么使用它。那到底接下来怎么继续呢?似乎不太有头绪,那就先连接上电脑再说吧!将J13跟电脑的USB口连接上去,会发现这时电脑正在安装一个驱动,就像一般的U盘这些USB设备第一次连接电脑一样,打开设备管理器,可以看到多了一个COM4端口!
连接接口跟FPGA的是一块FT232,而文字描述第一句话的意思就是这块FT232允许PC与开发板之间通过标准的Windows COM端口进行通信。原来如此,就是这么一块小小的芯片帮助我们完成了串行通信协议到USB协议之间的转换。这块芯片具体的工作原理我们暂且不去深究,对于我们这个开发来说,我们只需要搞清楚怎么使用它。那到底接下来怎么继续呢?似乎不太有头绪,那就先连接上电脑再说吧!将J13跟电脑的USB口连接上去,会发现这时电脑正在安装一个驱动,就像一般的U盘这些USB设备第一次连接电脑一样
实际上我们操作的只是一个“伪”USB协议,我们真正需要完成的收发机遵循的协议应该是异步串行通信协议。这个协议对于大家来说应该是再熟悉不过了,在这里我就不多废话了。需要说明的是,我在这个DEMO里采用的数据帧格式是:8bits数据位,1bits停止位,无奇偶校验,波特率为9600。
首先我们要实现一个单纯的发送机,要求它能接收输入口上的7位ASCII编码,然后将它不停的发送出去。它可以由下面这个状态机完成:
状态1----空闲状态,等待并复位,当发送标志置位时转到状态2;
状态2----准备,并转到状态3;
状态3----一帧数据导入,将输入口的数据读入,并前后加上起始位和停止位,转入状态4;
状态4----数据发送,将一帧10bits的数据按9600波特率串行发送出去,当完成10bits数据发送后,回到状态1。
按照这个状态机,我设计出下面这个模块:
- `timescale 1ns / 1ps
- //
- // Company:
- // Engineer:
- //
- // Create Date: 23:24:03 11/11/2013
- // Design Name:
- // Module Name: USB_UART
- // Project Name:
- // Target Devices:
- // Tool versions:
- // Description:
- //
- // Dependencies:
- //
- // Revision:
- // Revision 0.01 - File Created
- // Additional Comments:
- //
- //
- module USB_UART(
- clk,
- data,
- send,
- tx,
- busy,
- led
- );
- input clk,send;
- input [7:0] data;
- output reg tx,busy;
- output [7:0] led;
- assign led = data;
- //状态机状态定义
- parameter Idel = 2'b00,//空闲状态
- Rdy = 2'b01,//数据准备完成
- LoadByte = 2'b10,//数据传入
- SendBit = 2'b11;//数据发送
- reg [13:0] BspClkReg;//波特率分频计数
- reg BspClk;//波特率时钟
- reg [9:0] tx_data;//发送的数据,加上起始位和停止位
- reg [3:0] tx_byte_count;//发送位数计数
- reg [1:0] state;//,next_state;//状态寄存器
- //波特率分频模块,100M/10416
- always@(posedge clk)
- begin
- BspClkReg <= BspClkReg + 1;
- if(BspClkReg == 5208)
- begin
- BspClkReg <= 0;
- BspClk <= ~BspClk;
- end
- end
- always@(posedge BspClk)
- begin
- case(state)
- Idel : begin
- tx <= 1;
- busy <= 0;
- tx_byte_count <= 0;
- if(~send) state <= Rdy;
- end
- Rdy : begin
- tx_byte_count <= 0;
- tx <= 1;
- busy <= 1;
- state <= LoadByte;
- end
- LoadByte : begin
- tx_data <= {1'b1,data,1'b0};
- tx <= 1;
- busy <= 1;
- state <= SendBit;
- end
- SendBit : begin
- tx <= tx_data[0];
- busy <= 1;
- tx_data <= tx_data >> 1;
- tx_byte_count <= tx_byte_count + 1;
- if(tx_byte_count == 9)
- state <= Idel;
- else
- state <= SendBit;
- end
- endcase
- end
- endmodule
写好约束文件,data对应拨码开关,led对应led灯,这里对网上这个代码有点疑问SEND 和 BUSY我也不太清楚 ,继续往下学习应该可以解决。
然后我将输入数据口接到板子上的8个拨码开关上,即当要发送字符“A”的时候,拨码开关拨为01000001(65),这个时候电脑上的超级终端能接收到板子上连续发来的字符“A”!(注意设置ASC码的属性)