软件版本:Anlogic -TD5.6.1-64bit 操作系统:WIN10 64bit 硬件平台:适用安路(Anlogic)FPGA 1概述UART串口通信是应用非常广泛的一种串行异步通信方式,常用的异步串口包括RS232\RS482\RS485。 RS232的逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V,下图是老式的DB9串口线。 标准的DB9接口定义如下:
实际上一般RS232只使用到TXD RXD两个信号。 RS485/422采用差分信号负逻辑,逻辑"1"以两线间的电压差为-(2~6)V表示;逻辑"0"以两线间的电压差为+(2~6)V表示,由于采用差分方式可以具有更高的速度和更强的抗干扰能力,具有更远的传输距离。由于RS485/RS422更多出现在工业场合,因此一般采用接线端子方式接线 老式DB9串口基本上已经消失了,但是UART串口更加广泛的实用,比如我们常见的USB串口,就是通过一颗芯片实现了通过USB接口芯片,实现了以TTL电平方式的UART串口通信。数据通过USB接口进行传输,通过UART串口芯片完成USB协议到UART串口协议的相互转换。
在完成本实验前,请确保已经完成前面的实验,包括已经掌握以下能力: 1:完成了TD软件安装 2:完成了modelsim安装以及TD库的编译 3:掌握了TD仿真环境的设置 4:掌握了modesim通过do文件启动仿真
实验目的: 1:实现UART串口发送控制器的设计 2:实现主程序中调用串口发送控制器发送字符"HELLO FPGA" 3:实用modelsim完成仿真验证 4:编译并且固化程序到FPGA验证 2UART发送驱动设计
1:系统框图如下图所示,米联客设计的UART发送控制器包含3个主要模块:波特率发生器,发送使能模块,移位模块,其中移位模块中包含了移位计数器和移位控制器。 2:UART发送时序下图中,UART串口通信数据格式包括1bit起始位、8bits数据位、1bit停止位,不包含奇偶校验位。 在开始编写串口发送驱动前,我们需要了解下以下概念: 波特率:UART采用异步通信方式,数据首发双方只有在同一波特率才才能正常通信。波特率代表了UART完成1个时间单位数据位或者控制位的时间。通常,我们需要对系统时钟进行分频来产生正确的波特率,所以计算分频系统尤为重要,比如系统时钟是25000000HZ,波特率是115200,那么分频系数为=25000000/115200-1
起始位:UART数据总线由高电平变低电平并且持续1个波特率时间代表数据的起始
数据位:每个数据位占用1个波特率时间,本文实验发送1BYTE字节需要占用8个波特率时间。
停止位:如果没有奇偶校验位,数据位结束后,保持1/1.5/2个波特率的高电平代表了停止位。
奇偶校验:用于校对数据,对于UART通信,可以根据实际情况选择是否需要支持奇偶校验 3:驱动接口时序图米联客设计了一种通用简洁的驱动接口,包含以下信号: xxx_wreq:数据发送请求 xxx_wdata:需要发送的数据 xxx_wbusy:数据发送忙状态指示 这里xxx代表了uart 4:驱动源码代码如下: module uiuart_tx# ( parameter integer BAUD_DIV = 10416 ) ( input clk_i, input uart_rstn_i, input uart_wreq_i, input [7:0] uart_wdata_i, output uart_wbusy_o, output uart_tx_o );
localparam UART_LEN = 4'd10; wire bps_en ; reg uart_wreq_r = 1'b0; reg bps_start_en = 1'b0; reg [13:0] baud_div = 14'd0; reg [9 :0] uart_wdata_r = 10'h3ff; reg [3 :0] tx_cnt = 4'd0;
assign uart_tx_o = uart_wdata_r[0];
assign uart_wbusy_o = bps_start_en;
// uart tx Baud rate divider assign bps_en = (baud_div == BAUD_DIV);
always@(posedge clk_i )begin if((uart_rstn_i== 1'b0) || (uart_wreq_i==1'b1&uart_wreq_r==1'b0))begin baud_div <= 14'd0; end else begin if(bps_start_en && baud_div < BAUD_DIV) baud_div <= baud_div + 1'b1; else baud_div <= 14'd0; end end
always@(posedge clk_i)begin uart_wreq_r <= uart_wreq_i; end
//UART transmit enable ,Support gapless continuous enable always@(posedge clk_i)begin if(uart_rstn_i == 1'b0) bps_start_en <= 1'b0; else if(uart_wreq_i==1'b1&uart_wreq_r==1'b0) bps_start_en <= 1'b1; else if(tx_cnt == UART_LEN) bps_start_en <= 1'b0; else bps_start_en <= bps_start_en; end
//UART transmitter BIT counter always@(posedge clk_i)begin if(((uart_rstn_i== 1'b0) || (uart_wreq_i==1'b1&uart_wreq_r==1'b0))||(tx_cnt ==10)) tx_cnt <=4'd0; else if(bps_en && (tx_cnt < UART_LEN)) tx_cnt <= tx_cnt + 1'b1; end
//uart send controller shift control always@(posedge clk_i)begin if((uart_wreq_i==1'b1&uart_wreq_r==1'b0)) uart_wdata_r <= {1'b1,uart_wdata_i[7:0],1'b0}; else if(bps_en && (tx_cnt < (UART_LEN - 1'b1)))//shift 9 bits uart_wdata_r <= {uart_wdata_r[0],uart_wdata_r[9:1]}; else uart_wdata_r <= uart_wdata_r;
end
endmodule |
3UART用户数据发送模块1:发送流程图用户发送模块负责把数据听过UART驱动模块发送出去。用户发送模块 2:用户数据发送源码`timescale 1ns / 1ps module uart_top ( input sysclk_i, output uart_tx_o );
wire uart_rstn_i; wire uart_wbusy; reg t1s_dly_en; reg[1:0] S_UART_TX; reg[3:0] tx_index; reg uart_wreq; reg[7:0] uart_wdata; reg[7:0] uart_tx_buf[0:11];
reg [15:0]rst_cnt = 16'd0; reg [24:0]delay_cnt = 25'd0;
assign uart_rstn_i = rst_cnt[15];
//Power-on Reset Delay always @(posedge sysclk_i)begin rst_cnt <= (rst_cnt[15] == 1'b0) ? (rst_cnt + 1'b1) : rst_cnt ; end
//frame interval delay always @(posedge sysclk_i)begin if(t1s_dly_en == 1'b0) delay_cnt <= 25'd0; else delay_cnt <= delay_cnt + 1'b1; end
always @(posedge sysclk_i)begin if(uart_rstn_i==1'b0)begin uart_tx_buf[0] <=8'h48;//h uart_tx_buf[1] <=8'h45;//e uart_tx_buf[2] <=8'h4c;//l uart_tx_buf[3] <=8'h4c;//l uart_tx_buf[4] <=8'h4f;//o uart_tx_buf[5] <=8'h20;//space uart_tx_buf[6] <=8'h46;//f uart_tx_buf[7] <=8'h50;//p uart_tx_buf[8] <=8'h47;//g uart_tx_buf[9] <=8'h41;//a uart_tx_buf[10] <=8'h0d;//Enter uart_tx_buf[11] <=8'h0a;//newline
uart_wdata <= 8'd0; uart_wreq <= 1'b0; S_UART_TX <= 2'd0; t1s_dly_en <= 1'b0; tx_index <= 4'd0; end else begin case(S_UART_TX) 0:begin if(!uart_wbusy)begin//When the bus is not busy, request to send uart_wdata <= uart_tx_buf[tx_index]; uart_wreq <= 1'b1; end else begin uart_wreq <= 1'b0; S_UART_TX <= 2'd1; end end 1:begin//wait for the bus to be free S_UART_TX <= (uart_wbusy == 1'b0) ? 2'd2: S_UART_TX; end 2:begin//update index if(tx_index < 11)begin tx_index <= tx_index + 1'b1; S_UART_TX <= 2'd0; end else begin tx_index <= 4'd0; t1s_dly_en <= 1'b1; S_UART_TX <= 2'd3; end end 3:begin//A frame of data is sent and waits for a delay if(delay_cnt[24] == 1'b1)begin S_UART_TX <= 2'd0; t1s_dly_en <= 1'b0; end else S_UART_TX <= S_UART_TX; end endcase end
end
//uart send controller uiuart_tx# ( .BAUD_DIV(25000000/115200 -1) ) uart_tx_u ( .clk_i(sysclk_i), .uart_rstn_i(uart_rstn_i), .uart_wreq_i(uart_wreq), .uart_wdata_i(uart_wdata), .uart_wbusy_o(uart_wbusy), .uart_tx_o(uart_tx_o) );
endmodule |
4FPGA工程fpga工程的创建过程不再重复,如有不清楚的请看前面实验,这里以型号为EG4D20EG176的FPGA作为演示demo 米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹 01_rtl:放用户编写的rtl代码 02_sim:仿真文件或者工程 03_ip:放使用到的ip文件 04_pin:放fpga的pin脚约束文件或者时序约束文件 05_boot:放编译好的bit或者bin文件(一般为空) 06_doc:放本一些相关文档(一般为空) 3Modelsim仿真1:准备工作再次提醒,在进行modelsim仿真前,请提前完成,如果有不清楚的,以下3步请看前面课程内容: 1:完成了modelsim安装以及TD库的编译 2:掌握了TD仿真环境的设置 3:掌握了modesim通过do文件启动仿真
对于向执行什么级别的仿真,就执行对应的HDL2Bit Flow 当 HDL2Bit Flow 运行至 Read Design 这一步时,可执行 Behavioral Simulation; 当 HDL2Bit Flow 运行至 Optimize RTL 这一步时,可执行 Post-RTL Simulation; 当 HDL2Bit Flow 运行至 Optimize Gate 这一步时,可执行 Post-Gate Simulation; 当 HDL2Bit Flow 运行至 Optimize Routing 这一步时,可执行 Post-Route Simulation。 以执行Behavioral Simulation仿真来说,只要执行Read Design 这一步,如下图 右击FPGA Flow中 Read Design,Rerun 2:产生do文件在tool菜单中选择simulation 我们这里也是选择已经编写好的仿真测试文件 仿真测试文件源码如下: `timescale 1ns / 1ns
module uart_top_TB;
reg sysclk_i; wire uart_tx_o;
uart_top u_uart_top ( .sysclk_i (sysclk_i), .uart_tx_o (uart_tx_o) );
initial begin sysclk_i = 0; #100; end
always #20 sysclk_i = ~sysclk_i;
endmodule |
可以看到产生的do文件中,自动添加了仿真文件、库的路径 3:启动modelsim仿真输入do fpga_prj_behavioral_sim.do 启动后,右击需要观察的信号,添加到波形窗口 设置restart 设置运行100ms(如果运行时间太长可以修改小一些) 4下载演示下载程序前,先确保FPGA工程已经编译。 1:硬件连接请确保下载器和开发板已经正确连接,并且开发板已经上电(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)
2:程序下载单击下载按钮 可以看到已经识别到芯片,但是请注意,实际芯片是EG4D20EG176,而识别出来的变成了EAGLE_S20_EG176,但是这个不影响我们下载,所以继续。 选择bit文件 选中后单击Run 下载成功 2:运行结果附录:常见问题1联系方式
米联客社区FPGA/SOC QQ群: 群1:516869816 群2:543731097 群3:86730608 群4:34215299
技术微信:18951232035 技术电话:18951232035
官方微信公众号(新微信公众号): 2售后1、7天无理由退货(人为原因除外) 2、质保期限:本司产品自快递签收之日起,提供一年质保服务(主芯片,比如FPGA 或者CPU等除外)。 3、维修换货,需提供淘宝订单编号或合同编号,联系销售/技术支持安排退回事宜。 4、以下情形不属于质保范畴。 A:由于用户使用不当造成板子的损坏:比如电压过高造成的开发板短路,自行焊接造成的焊盘脱落、铜线起皮 等 B:用户日常维护不当造成板子的损坏:比如放置不当导致线路板腐蚀、基板出现裂纹等 5、质保范畴外(上方第4条)及质保期限以外的产品,本司提供有偿维修服务。维修仅收取器件材料成本,往返运 费全部由客户承担。 3销售
销售电话:18921033576
公司地址:常州溧阳总部:常州溧阳市中关村吴潭渡路雅创高科智造谷10-1幢楼 南京研发基地:南京市栖霞区仙林大道181号5幢1820室 4在线视频5软件下载6经验分享7官方博文
|