FPGA模拟串口自收发-Verilog

合集下载

基于verilog的很基础的RS232串口收发代码

基于verilog的很基础的RS232串口收发代码

基于verilog的很基础的RS232串口收发代码写代码,记笔记,防忘记,须牢记。

写串口的Verilog代码关键是要搞明白RS232串口的通信协议,它并不像单片机,直接读写SBUF就可实现串口的收发功能,收发整个字节。

而FPGA要一位一位的收发,因此必须了解RS232的数据格式。

起始位:RS232约定一位起始位“0”。

停止位:约定停止位为“1”。

可选一位或两位停止位。

奇偶校验位:可选。

通过串口发送数据时,要严格遵守RS232的数据格式,先发送起始位,然后是数据,最后是停止位(无奇偶校验的情况)。

通过串口接收数据时,若接收端无数据输入,会一直处于高电平,若开始接收数据,会首先收到来自串口的起始位“0”,然后是要接收的数据,最后为停止位(无奇偶校验的情况)。

所以对于接收模块,可如此设计,FPGA一直检测接收端是否有下降沿到来,直到检测到下降沿,才开始接收数据。

波特率设置的重要性不言而喻,毋庸赘述。

此设计为最基础的串口收发代码,控制逻辑简单,适合编写第一次编写串口代码的朋友。

此设计收发的数据格式为1位起始位,1位停止位,无奇偶校验位,8位数据位。

波特率为19200,代码中可随意更改。

具体Verilog代码如下:顶层模块`timescale 1ns / 1ps/////////////////////////////////////////////////////////////////// /////////////// Company : 杭州电子科技大学// Engineer : 晓晓川// Create Date : 2012.08.26// Design Name : serial_test// Module Name : serial_test// Project Name: serial_test// Target Device: CycloneII EP2C5T144C8// Tool versions: Quartus II 11.0// Revision : V1.0// Description : 一个极为简单的串口收发工程,适于串口收发的入门。

基于FPGA Verilog RS232串口回环测试例程,附源程序仿真源码及测试图片

基于FPGA Verilog RS232串口回环测试例程,附源程序仿真源码及测试图片

FPGA Verilog RS232串口回环测试基于FPGA Verilog RS232串口回环测试例程,支持多byte数据传输,附源程序仿真源码及测试图片。

测试基于SSCOM/友善之臂上位机软件测试,测试结果如下图一图二所示。

图一SSCOM图二图三连续发送仿真截图图四连续接收仿真截图后附verilog源程序代码及testbech仿真例程,注释欠。

重点:多byte回环测试要点,上位机串口多位数据连续发送停止位和起始位之间无间隔,回环程序在接收和发送都需要具备在停止位后能立马跳转到下一个起始位的能力。

重点关注cnt_bit的处理方式。

附录1 顶层例化uart_txd uart_txd(.clk_50m(sys_clk_50m),.reset_n(sys_rst_n),.tx_data(rx_data),.baud_set(3'd4),.send_en(rx_done),.send_done(),.send_busy(send_busy),.uart_tx(uart_tx));uart_rxd uart_rxd(.clk_50m(sys_clk_50m),.reset_n(sys_rst_n),.rx_data(rx_data),.baud_set(3'd4),.rx_done(rx_done),.rx_busy(rx_busy),.uart_rx(uart_rx));附录2 串口发送源程序`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 09:45:23// Design Name:// Module Name: uart_txd// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies:// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_txd(clk_50m,reset_n,tx_data,baud_set,send_en,send_done,send_busy,uart_tx);input clk_50m;input reset_n;input[7:0] tx_data;input[2:0] baud_set;input send_en;output reg send_done;output reg send_busy;output reg uart_tx;reg[12:0] cnt;reg[12:0] baud_rate_cnt_max;reg[3:0] cnt_bit;reg[7:0] tx_data_r;localparam baud_rate_9600 =13'd5207;localparam baud_rate_19200 =13'd2603;localparam baud_rate_38400 =13'd1301;localparam baud_rate_57600 =13'd867;localparam baud_rate_115200 =13'd433;always@(posedge clk_50m or negedge reset_n)if(!reset_n)baud_rate_cnt_max <= baud_rate_115200;elsecase(baud_set)3'd0:baud_rate_cnt_max = baud_rate_9600;3'd1:baud_rate_cnt_max = baud_rate_19200;3'd2:baud_rate_cnt_max = baud_rate_38400;3'd3:baud_rate_cnt_max = baud_rate_57600;3'd4:baud_rate_cnt_max = baud_rate_115200;default:baud_rate_cnt_max = baud_rate_115200;endcasealways@(posedge clk_50m or negedge reset_n)if(!reset_n)tx_data_r <=8'd0;else if(send_en)tx_data_r <= tx_data;elsetx_data_r <= tx_data_r;always@(posedge clk_50m or negedge reset_n)if(!reset_n)send_busy <=1'b0;else if(send_en)send_busy <=1'b1;else if(cnt == baud_rate_cnt_max)beginif(cnt_bit ==4'd10)send_busy <=1'b0;elsesend_busy <= send_busy;endelsesend_busy <= send_busy;always@(posedge clk_50m or negedge reset_n)if(!reset_n)send_done <=1'b0;else if(cnt == baud_rate_cnt_max)beginif(cnt_bit ==4'd10)send_done <=1'b1;elsesend_done <=1'b0;endelsesend_done <=1'b0;always@(posedge clk_50m or negedge reset_n)if(!reset_n)cnt <=13'd0;else if(send_busy)beginif(cnt == baud_rate_cnt_max)cnt <=13'd0;elsecnt <= cnt +1'b1;endelsecnt <= cnt;/****************************************always@(posedge clk_50m or negedge reset_n)if(!reset_n)cnt_bit <= 4'd0;else if(send_en) //send_en needs to be 1 clock high pulse cnt_bit <= 4'd1;else if(cnt == baud_rate_cnt_max)beginif(cnt_bit == 4'd10)cnt_bit <= 4'd0;elsecnt_bit <= cnt_bit + 1'b1;endelsecnt_bit <= cnt_bit;******************************************/always@(posedge clk_50m or negedge reset_n)if(!reset_n)cnt_bit <=4'd0;else if(send_busy &&(cnt_bit ==4'd11))cnt_bit <=4'd1;else if(cnt ==1)cnt_bit <= cnt_bit +1'b1;elsecnt_bit <= cnt_bit;always@(posedge clk_50m or negedge reset_n)if(!reset_n)beginuart_tx <=1'b1;endelsecase(cnt_bit)4'd0:;4'd1: uart_tx <=1'b0;//start4'd2: uart_tx <= tx_data_r[0];//bit 04'd3: uart_tx <= tx_data_r[1];4'd4: uart_tx <= tx_data_r[2];4'd5: uart_tx <= tx_data_r[3];4'd6: uart_tx <= tx_data_r[4];4'd7: uart_tx <= tx_data_r[5];4'd8: uart_tx <= tx_data_r[6];4'd9: uart_tx <= tx_data_r[7];//bit 84'd10: uart_tx <=1'b1;//stopdefault:;endcaseendmodule附录3 串口发送testbench`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 11:38:04// Design Name:// Module Name: uart_txd_tb// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_txd_tb();reg clk_50m;reg reset_n;reg[7:0] tx_data;reg[2:0] baud_set;reg send_en;wire send_done;wire send_busy;wire uart_tx;parameter CLK_PERIOD =20;initial clk_50m =0;always#(CLK_PERIOD /2) clk_50m =~clk_50m;initial begintx_data =8'h55;baud_set =4;reset_n =0;send_en =0;#(CLK_PERIOD *100);reset_n =1;# CLK_PERIOD;send_en =1;#(CLK_PERIOD );send_en =0;#(CLK_PERIOD *4340);send_en =1;#(CLK_PERIOD );send_en =0;#(CLK_PERIOD *4340);#(CLK_PERIOD *100);$stop;enduart_txd uart_txd(.clk_50m(clk_50m),.reset_n(reset_n),.tx_data(tx_data),.baud_set(baud_set),.send_en(send_en),.send_done(send_done),.send_busy(send_busy),.uart_tx(uart_tx));endmodule附录4 串口接收源程序`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 15:30:30// Design Name:// Module Name: uart_rxd// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_rxd(clk_50m,reset_n,rx_data,baud_set,rx_done,rx_busy,uart_rx);input clk_50m;input reset_n;output reg[7:0] rx_data;input[2:0] baud_set;output reg rx_done;output reg rx_busy;input uart_rx;reg[12:0] cnt;reg[12:0] baud_rate_cnt_max;reg[3:0] cnt_bit;reg uart_rx_r1;reg uart_rx_r2;wire nedge;localparam baud_rate_9600 =13'd5207;localparam baud_rate_19200 =13'd2603;localparam baud_rate_38400 =13'd1301;localparam baud_rate_57600 =13'd867;localparam baud_rate_115200 =13'd433;always@(posedge clk_50m or negedge reset_n)if(!reset_n)baud_rate_cnt_max <= baud_rate_115200;elsecase(baud_set)3'd0:baud_rate_cnt_max = baud_rate_9600;3'd1:baud_rate_cnt_max = baud_rate_19200;3'd2:baud_rate_cnt_max = baud_rate_38400;3'd3:baud_rate_cnt_max = baud_rate_57600;3'd4:baud_rate_cnt_max = baud_rate_115200;default:baud_rate_cnt_max = baud_rate_115200;endcasealways@(posedge clk_50m or negedge reset_n)if(!reset_n)beginuart_rx_r1 <=8'd0;uart_rx_r2 <=8'd0;endelse beginuart_rx_r1 <= uart_rx;uart_rx_r2 <= uart_rx_r1;endassign nedge = uart_rx_r2 &(!uart_rx_r1);always@(posedge clk_50m or negedge reset_n) if(!reset_n)rx_busy <=1'b0;else if(nedge)rx_busy <=1'b1;else if(cnt == baud_rate_cnt_max)begin if(cnt_bit ==4'd10)rx_busy <=1'b0;elserx_busy <= rx_busy;endelserx_busy <= rx_busy;always@(posedge clk_50m or negedge reset_n) if(!reset_n)rx_done <=1'b0;else if(cnt == baud_rate_cnt_max)begin if(cnt_bit ==4'd10)rx_done <=1'b1;elserx_done <=1'b0;endelserx_done <=1'b0;always@(posedge clk_50m or negedge reset_n) if(!reset_n)cnt <=13'd0;else if(rx_busy)beginif(cnt == baud_rate_cnt_max)cnt <=13'd0;elsecnt <= cnt +1'b1;endelsecnt <= cnt;always@(posedge clk_50m or negedge reset_n) if(!reset_n)cnt_bit <=4'd1;else if(cnt == baud_rate_cnt_max )begin if(cnt_bit ==4'd10)cnt_bit <=4'd1;elsecnt_bit <= cnt_bit +1'b1;endelsecnt_bit <= cnt_bit;always@(posedge clk_50m or negedge reset_n)if(!reset_n)beginrx_data <=8'd0;endelse if(cnt == baud_rate_cnt_max /2)case(cnt_bit)4'd1:;//start4'd2: rx_data[0]<= uart_rx_r2;//bit 04'd3: rx_data[1]<= uart_rx_r2;4'd4: rx_data[2]<= uart_rx_r2;4'd5: rx_data[3]<= uart_rx_r2;4'd6: rx_data[4]<= uart_rx_r2;4'd7: rx_data[5]<= uart_rx_r2;4'd8: rx_data[6]<= uart_rx_r2;4'd9: rx_data[7]<= uart_rx_r2;//bit 74'd10:;//stopdefault:;endcaseelserx_data <= rx_data;endmodule附录5串口接收testbench`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 19:44:29// Design Name:// Module Name: uart_rxd_tb// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_rxd_tb();reg clk_50m;reg reset_n;wire[7:0] rx_data;wire rx_done;wire rx_busy;reg uart_rx;parameter CLK_PERIOD =20;initial clk_50m =0;always#(CLK_PERIOD /2) clk_50m =~clk_50m;initial beginreset_n =0;uart_rx =1;//idle#(CLK_PERIOD *100);reset_n =1;# CLK_PERIOD;uart_rx =0;//start#(CLK_PERIOD *434);uart_rx =1;//bit0#(CLK_PERIOD *434);uart_rx =0;//bit1#(CLK_PERIOD *434);uart_rx =1;//bit2#(CLK_PERIOD *434);uart_rx =0;//bit3#(CLK_PERIOD *434);uart_rx =1;//bit4#(CLK_PERIOD *434);uart_rx =0;//bit5#(CLK_PERIOD *434);uart_rx =1;//bit6#(CLK_PERIOD *434);uart_rx =0;//bit7#(CLK_PERIOD *434);uart_rx =1;//stop#(CLK_PERIOD *434);uart_rx =1;//idle#(CLK_PERIOD *434);#(CLK_PERIOD *434);#(CLK_PERIOD *434);uart_rx =0;//start #(CLK_PERIOD *434);uart_rx =0;//bit0#(CLK_PERIOD *434);uart_rx =1;//bit1#(CLK_PERIOD *434);uart_rx =0;//bit2#(CLK_PERIOD *434);uart_rx =1;//bit3#(CLK_PERIOD *434);uart_rx =0;//bit4#(CLK_PERIOD *434);uart_rx =1;//bit5#(CLK_PERIOD *434);uart_rx =0;//bit6#(CLK_PERIOD *434);uart_rx =1;//bit7#(CLK_PERIOD *434);uart_rx =1;//stop#(CLK_PERIOD *434);uart_rx =1;//idle#(CLK_PERIOD *434);#(CLK_PERIOD *434);#(CLK_PERIOD *434);$stop;enduart_rxd uart_rxd(.clk_50m(clk_50m),.reset_n(reset_n),.rx_data(rx_data),.baud_set(3'd4),.rx_done(rx_done),.rx_busy(rx_busy),.uart_rx(uart_rx));endmodule。

正点原子fpga串口多字节-概述说明以及解释

正点原子fpga串口多字节-概述说明以及解释

正点原子fpga串口多字节-概述说明以及解释1. 引言1.1 概述概述正点原子FPGA(现场可编程门阵列)串口多字节是一种用于串口通信的技术,借助正点原子FPGA芯片的特性,实现了在传输数据时可以同时发送多个字节的功能。

传统的串口通信只能逐个字节地发送和接收数据,效率较低。

而正点原子FPGA串口多字节技术的出现,极大地提高了串口通信的速度与效率。

本文将介绍正点原子FPGA串口多字节技术的基本原理、实现方法以及其在实际应用中的优点和应用场景。

通过深入分析和论述,读者将能够更好地理解正点原子FPGA串口多字节技术的工作原理和优势,为其在实际项目中的应用提供指导和参考。

在接下来的章节中,我们将会详细讨论正点原子FPGA串口多字节技术的具体内容。

首先,在第一个要点中,我们将介绍其基本概念和原理,并阐述其如何在FPGA芯片中实现。

其次,在第二个要点中,我们将深入探讨正点原子FPGA串口多字节技术在实际应用中的优势和应用场景,包括其在数据传输、通信系统和嵌入式系统中的应用。

通过本文的阐述,我们希望读者能够全面了解正点原子FPGA串口多字节技术,并能够在实际项目中运用此技术,提高串口通信的效率和性能。

在结论部分,我们将对正点原子FPGA串口多字节技术进行总结,并展望其在未来的发展前景。

1.2 文章结构文章结构部分的内容:本文共分为三个部分,分别是引言、正文和结论。

引言部分主要对本文进行概述,介绍文章的目的和结构。

第一个要点是正文的第一个部分,将详细介绍正点原子FPGA串口多字节的原理和应用。

我们将从FPGA的基本概念出发,通过对正点原子FPGA的介绍和分析,深入探讨其串口多字节的实现原理和相关技术。

第二个要点是正文的第二个部分,将进一步展开对正点原子FPGA串口多字节的设计和实现进行详细阐述。

我们将从硬件设计和软件编程两个方面入手,介绍如何在FPGA上进行串口多字节的设计和开发,并给出相应的实例和实验结果。

结论部分将对本文的内容进行总结,并展望正点原子FPGA串口多字节在未来的应用前景。

基于FPGA的串口通信设计与实现

基于FPGA的串口通信设计与实现

置和输人数据计算出响应
的奇偶校验位,它是通过
纯组合逻辑来实现的。
2.6总线选择模块
总线选择模块用于
选择奇偶校验器的输入是
数据发送总线还是数据接
收总线。
2.7计数器模块
计数器模块的功能
是记录串行数据发送或者
接收的数日,在计数到某
数值时通知UART内核模
块。 3 UART程序设计 UART完整的工作流程可以分为接收过程
关键词:FPGA:UART:RS232
引言 串行接口的应用非常广泛,为实现串口通 信功能一般使用专用串行接口芯片,但是这种 接口芯片存在体积较大、接口复杂以及成本较 高的缺点,使得硬件设计更加复杂,并且结构与 功能相对固定,无法根据设计的需要对其逻辑 控制进行灵活的修改。介绍了一种采用FPGA 实现串口通信的方法。 1串口通信协议 对一个设备的处理器来说,要接收和发送 串行通信的数据,需要一个器件将串行的数据 转换为并行的数据以便于处理器进行处理,这 种器件就是UART(Universal Asynchronous Re— ceiver/Transmitter)通用异步收发器。作为接iSl的 一部分,UART提供以下功能: 1.1将由计算机内部传送过来的并行数据 转换为输出的串行数据流; 1.2将计算机外部来的串行数据转换为字 节,供计算机内部使用并行数据的器件使用; 1.3在输出的串行数据流中加入奇偶校验 位,并对从外部接收的数据流进行奇偶校验: 1.4在输出数据流中加入启停标记,并从 接收数据流中删除启停标记。 2 UART模块设计 UART主要由UART内核、信号检测器、移 位寄存器、波特率发生器、计数器、总线选择器 和奇偶校验器7个模块组成。(见图1) 2.1 UART内核模块 UART内核模块是整个设计的核心。在数 据接收时,UART内核模块负责控制波特率发 生器和移位寄存器同步的接收并且保存 RS一232接收端口上的串行数据。在数据发送 时,UART内核模块首先产生完整的发送序列, 之后控制移位寄存器将序列加载到移位寄存器 的内部寄存器里,最后再控制波特率发生器驱 动移位寄存器将数据串行输出。 2_2信号检测模块 信号检测器用于对RS一232的输入信号进 行实时检测,一旦发现新的数据则立即通知 UART内核。需要注意的是,这里所说的 RS一232输入输出信号都指经过电平转换后的 逻辑信号,而不是RS一232总线上的电平信号。 2_3移位寄存器模块 移位寄存器的作用是存储输入或者输出 的数据。 2.4波特率发生器模块 由于RS一232传输必定是工作在某种波特 率下,比如9600,为了便于和RS一232总线进行 同步,需要产生符合RS一232传输波特率的时 钟。 2.5奇偶校验器模块 奇偶校验器的功能是根据奇偶校验的设

Verilog实现串口接收多帧数据

Verilog实现串口接收多帧数据

Verilog实现串口接收多帧数据`timescale 1ns / 1ps/////////////////////////////////////////////////////////////////// ///////////////// Company:// Engineer://// Create Date: 19:50:45 04/19/2015// Design Name:// Module Name: Serial_Decoder// Project Name:// Target Devices:// Tool versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments:///////////////////////////////////////////////////////////////////// ///////////////module Serial_Decoder(input wire clk_seri, //串口时钟,用于从串口发送命令给FPGA input wire rst,input wire RxD,output reg[1:0] modu_sel, //BPSK,QPSK,8PSK选择output reg[13:0] ser_asf, //由串口发过来的asfoutput reg[31:0] ser_ftw, //由串口发过来的ftwoutput reg cmd_done, //上位机给FPGA发送指令结束output reg[31:0] dina, //ROM存储器,用于存储外部PN码output reg wea,output reg[1:0] addra);reg cmd_rdy;//指令接收完成reg [3:0] instr_code;//用于分辨命令,是asf还是ftw还是外部PN码reg [31:0] cmd_data; //接收从上层发过来的命令wire RxD_data_ready;wire [7:0] RxD_data;reg [1:0] instr_cnt;reg data_rec_valid;reg data_rec_busy;reg [1:0] data_cnt;//instancereceiver i_receiver(.clk(clk_seri),.RxD(RxD),.RxD_data_ready(RxD_data_ready),.RxD_data_error(),.RxD_data(RxD_data));//*********上位机发命令给FPGA************//always @ (posedge clk_seri)beginif(rst)begininstr_cnt <= 0;endelse if(RxD_data_ready && !data_rec_busy) case(instr_cnt)2'd0:if(RxD_data == 8'h55)begininstr_cnt <= 2'd1;data_rec_valid <= 0;endelsebegininstr_cnt <= 2'd0;data_rec_valid <= 0;end2'd1:if(RxD_data == 8'h55)begininstr_cnt <= 2'd2;data_rec_valid <= 0;endelsebegininstr_cnt <= 2'd0;data_rec_valid <= 0;end2'd2:if(RxD_data == 8'h55)begininstr_cnt <= 2'd3;endelsebegininstr_cnt <= 2'd0;data_rec_valid <= 0;end2'd3:if(RxD_data == 8'h55)begininstr_cnt <= 2'd3;data_rec_valid <= 0;endelsebegininstr_cnt <= 2'd0;data_rec_valid <= 1;instr_code <= RxD_data[3:0]; //用来分辨各命令enddefault:begininstr_cnt <= 2'd0;data_rec_valid <= 0;endendcaseelsedata_rec_valid <= 0;endalways @ (posedge clk_seri)beginif(rst)begindata_cnt <= 2'd0;data_rec_busy <= 0;cmd_rdy <= 0;endelse if(data_rec_valid)begindata_cnt <= 0;data_rec_busy <= 1;cmd_rdy <= 0;endelse if(RxD_data_ready && data_rec_busy) case(data_cnt)2'd0:begindata_cnt <= 2'd1;data_rec_busy <= 1;cmd_rdy <= 0;cmd_data[31:24]<= RxD_data;end2'd1:begindata_cnt <= 2'd2;data_rec_busy <= 1;cmd_rdy <= 0;cmd_data[23:16]<= RxD_data;end2'd2:begindata_cnt <= 2'd3;data_rec_busy <= 1;cmd_rdy <= 0;cmd_data[15:8] <= RxD_data; end2'd3:begindata_cnt <= 2'd0;data_rec_busy <= 0;cmd_rdy <= 1; //命令接收完毕cmd_data[7:0] <= RxD_data; enddefault:begindata_cnt <= 2'd0;data_rec_busy <= 0;cmd_rdy <= 0;endendcaseelsecmd_rdy <= 0;end//*********分辨命令*********// always @ (posedge clk_seri) beginif(rst)begincmd_done <= 0;modu_sel <= 0;ser_asf <= 0;ser_ftw <= 0;endelse if(cmd_rdy)begincase(instr_code)4'h6:beginser_ftw <= cmd_data;cmd_done <= 0;end4'h7:beginmodu_sel <= cmd_data[25:24];cmd_done <= 0;end4'h8:beginser_asf <= cmd_data[13:0];cmd_done <= 0;end4'hF:cmd_done <= 1; //上位机命令发送结束default:; endcaseendelsebeginser_ftw <= ser_ftw;ser_asf <= ser_asf;modu_sel<= modu_sel;cmd_done<= cmd_done;endendalways @ (posedge clk_seri)beginif(rst)begindina <= 0;wea <= 1;addra <= 0;endelse if(cmd_rdy)begincase(instr_code)//********A--D是外部PN码,将其存入ROM中********// 4'hA:begindina <= cmd_data;wea <= 1;addra <= 2'd0;end4'hB:begindina <= cmd_data;wea <= 1;addra <= 2'd1;end4'hC:begindina <= cmd_data;wea <= 1;addra <= 2'd2; end4'hD:begindina <= cmd_data; addra <= 2'd3; wea <= 0;enddefault:; endcaseendelsebegindina <= dina; addra <= addra; wea <= wea;endend endmodule。

fpga vio 用法

fpga vio 用法

fpga vio 用法FPGA VIO(Virtual Input/Output)是一种在FPGA(Field Programmable Gate Array)中用于仿真和验证的功能模块。

它可以模拟输入和输出信号,以便在硬件设计的早期阶段进行验证和调试。

下面我将从不同角度来介绍FPGA VIO的用法。

首先,FPGA VIO可以用于仿真验证。

在FPGA设计的早期阶段,我们需要验证设计的正确性,包括输入输出信号的正确连接和逻辑功能的正确实现。

使用FPGA VIO,我们可以在仿真环境中生成虚拟的输入信号,并监视输出信号,从而验证设计的功能和正确性。

其次,FPGA VIO也可以用于硬件调试。

当FPGA设计被加载到实际的硬件平台上时,我们可能需要对输入输出信号进行调试。

通过使用FPGA VIO,我们可以通过调整输入信号的值,监视输出信号的变化,来定位和解决硬件设计中的问题。

此外,FPGA VIO还可以用于快速原型验证。

在设计复杂的数字电路时,我们可能需要快速验证设计的功能。

使用FPGA VIO,我们可以快速生成各种输入信号,验证设计的功能,加速设计验证的过程。

另外,FPGA VIO还可以用于接口协议验证。

在许多应用中,FPGA需要与其他设备进行通信,比如I2C、SPI、UART等。

使用FPGA VIO,我们可以模拟这些通信协议的输入输出信号,验证FPGA 设计与其他设备的接口协议是否正确。

总的来说,FPGA VIO是一种非常有用的工具,可以在FPGA设计的各个阶段用于仿真验证、硬件调试、快速原型验证和接口协议验证。

它为FPGA设计提供了灵活、高效的验证手段,有助于提高设计的可靠性和稳定性。

基于FPGA的高速串行数据收发接口设计

基于FPGA的高速串行数据收发接口设计

基于FPGA的高速串行数据收发接口设计随着信息技术的不断发展,高速串行数据收发接口已经成为许多应用领域中的关键技术。

而基于FPGA的高速串行数据收发接口设计,可以充分发挥FPGA的并行计算和可编程性优势,实现高速数据传输和处理。

本文将介绍基于FPGA的高速串行数据收发接口的设计原理、关键技术和应用。

一、设计原理在高速串行数据收发接口中,主要涉及到以下几个方面的技术:物理接口、时钟同步、帧同步、数据编码和解码、差分信号传输等。

1.物理接口物理接口是指FPGA与外部设备之间进行数据传输的接口。

常见的物理接口包括LVDS、USB、PCIe等。

在设计中,需要选择合适的物理接口,并实现与FPGA之间的连接。

2.时钟同步时钟同步是指接收端与发送端的时钟信号保持同步,以确保数据的准确传输。

常见的时钟同步技术包括PLL锁相环、FIFO缓存等。

在设计中,需要使用适当的时钟同步技术,保证数据的稳定传输。

3.帧同步帧同步是指接收端能够正确识别数据帧的起始和结束标志,以及数据帧中的各个字段。

在设计中,通过使用标志位或者特定的编码格式,可以实现帧同步,保证数据的正确接收和解析。

4.数据编码和解码数据编码和解码是指将要传输的数据进行编码,以提高传输速率和抗干扰能力。

常见的数据编码和解码算法包括差分编码、曼彻斯特编码、8b/10b编码等。

在设计中,需要根据具体的应用需求,选择合适的数据编码和解码算法。

5.差分信号传输差分信号传输是指将发送端的信号分为正负两路进行传输,以提高传输速率和抗干扰能力。

差分信号传输可以有效抑制共模干扰和噪声,提高信号的可靠传输。

二、关键技术在基于FPGA的高速串行数据收发接口设计中,需要关注以下几个关键技术。

1.时钟和数据恢复由于传输中的时钟和数据可能存在相位偏移和抖动等问题,因此需要使用时钟和数据恢复技术来保持时钟的稳定,并将数据恢复到正确的状态。

2.信号完整性由于传输线上会存在反射、串扰等问题,需要采取合适的电路设计和布线策略,以提高信号的抗干扰能力和抗噪声能力,保证数据的可靠传输。

FPGA笔记之verilog语言(基础语法篇)

FPGA笔记之verilog语言(基础语法篇)

FPGA笔记之verilog语言(基础语法篇)笔记之verilog语言(基础语法篇)写在前面:verilogHDL语言是面对硬件的语言,换句话说,就是用语言的形式来描述硬件线路。

因此与等软件语言不同,假如想要在实际的中实现,那么在举行verilog语言编写时,就需要提前有个硬件电路的构思和主意,同时,在编写verilog语言时,应当采纳可综合的语句和结构。

1. verilog 的基础结构1.1 verilog设计的基本单元——module在数字电路中,我们经常把一些复杂的电路或者具有特定功能的电路封装起来作为一个模块用法。

以后在运用这种模块化的封装时,我们只需要知道:1.模块的输入是什么;2.模块的输出是什么;3.什么样的输入对应什么样的输出。

而中间输入是经过什么样的电路转化为输出就不是我们在用法时需要特殊重视的问题。

当无数个这样的模块互相组合,就能构成一个系统,解决一些复杂的问题。

verilog语言的基础结构就是基于这种思想。

verilog中最基本的模块是module,就可以看做是一个封装好的模块,我们用verilog来写无数个基本模块,然后再用verilog描述多个模块之间的接线方式等,将多个模块组合得到一个系统。

那么一个module应当具有哪些要素呢?首先对于一个module,我们应当设计好其各个I/O,以及每个I/O的性质,用于与模块外部的信号相联系,让用法者知道如何连线。

第二,作为开发者,我们需要自己设计模块内部的线路来实现所需要的功能。

因此需要对模块内部浮现的变量举行声明,同时通过语句、代码块等实现模块的功能。

综上所述,我们把一个module分成以下五个部分:模块名端口定义I/O解释第1页共9页。

Verilog双向口的使用和仿真

Verilog双向口的使用和仿真

Verilog in out 双向口使用和仿真2007-12-01 11:11芯片外部引脚很多都使用in out类型的,为的是节省管腿。

一般信号线用做总线等双向数据传输的时候就要用到INOUT类型了。

就是一个端口同时做输入和输出。

inout 在具体实现上一般用三态门来实现。

三态门的第三个状态就是高阻'Z' 0当in out端口不输出时,将三态门置高阻。

这样信号就不会因为两端同时输出而出错了,更详细的内容可以搜索一下三态门tri-state 的资料.1使用in out类型数据,可以用如下写法:inout data」no ut;in put data_i n;reg data_reg;//data_i nout 的映象寄存器reg lin k_data;assign data_inout=link_data?data_reg:1 ' bz;//link_data 控制三态门//对于data_reg,可以通过组合逻辑或者时序逻辑根据data_in对其赋值.通过控制link_data 的高低电平,从而设置data」nout是输出数据还是处于高阻态,如果处于高阻态,则此时当作输入端口使用.link_data 可以通过相关电路来控制.2编写测试模块时,对于in out类型的端口,需要定义成wire类型变量,而其它输入端口都定义成reg类型,这两者是有区别的.当上面例子中的data」nout用作输入时,需要赋值给data」nout,其余情况可以断开.此时可以用assign 语句实现:assign data_inout=link?data_in_t:1 ' bz; 其中的link ,data_in_t 是reg类型变量,在测试模块中赋值.另外,可以设置一个输出端口观察data_inout用作输出的情况:Wire data_out;Assign data_out_t=(!link)?data_inout:1 ' bz;else , in RTLinout use in top module(PAD)dont use ino ut(tri) in sub module也就是说,在内部模块最好不要出现inout,如果确实需要,那么用两个port 实现,到顶层的时候再用三态实现。

FPGA和单片机串行通信接口的实现

FPGA和单片机串行通信接口的实现

FPGA和单片机串行通信接口的实现FPGA(Field-Programmable Gate Array)和单片机(Microcontroller)是两种常用的数字电子设备,它们在串行通信接口方面有不同的实现方式。

首先,我们需要了解串行通信是一种将数据以位的形式逐个传输的通信方式。

常见的串行通信协议包括UART(Universal Asynchronous Receiver/Transmitter)、SPI(Serial Peripheral Interface)和I2C (Inter-Integrated Circuit)等。

对于FPGA和单片机之间的串行通信,我们可以基于以下几种方式进行实现:1. UART:UART是一种常见的串行通信协议,可以实现全双工的通信。

在FPGA和单片机之间建立UART通信,需要在FPGA中实现UART模块,并将其与单片机的UART接口连接。

在FPGA中,我们可以使用硬件语言(如Verilog或VHDL)来实现UART模块,该模块负责将FPGA内部的数据通过UART协议进行封装和解封装。

单片机与FPGA之间通过TX(发送)和RX (接收)引脚建立连接。

单片机可以通过串口发送数据给FPGA,FPGA接收到数据后进行处理,然后再通过串口将处理后的数据发送给单片机。

2.SPI:SPI是一种用于片上外设之间通信的串行通信协议,常用于FPGA与外部设备(例如传感器、显示器等)之间的通信。

在FPGA和单片机之间建立SPI通信,需要在FPGA中实现SPI控制器,并将其与单片机的SPI接口连接。

FPGA通过把数据写入SPI发送缓冲区或从SPI接收缓冲区读取数据来实现与单片机的通信。

单片机通过控制SPI接口的时钟、数据和使能信号来与FPGA进行数据传输。

3.I2C:I2C是一种双线制串行总线,常用于连接多个设备的系统,例如FPGA、单片机和其他外部设备之间的通信。

在FPGA和单片机之间建立I2C通信,需要在FPGA中实现I2C控制器,并将其与单片机的I2C接口连接。

基于fpga的串口通信

基于fpga的串口通信

基于FPGA的串口通信设计学号:姓名:班级:指导教师:电子与控制工程学院一、串行通信系统1.1概述在计算机系统和微机网络的快速发展领域里串行通信在数据通信及控制系统中得到广泛的应用。

UART 即Universal AsynchronousReceiver Transmitter 通用异步收发器 协议是数据通信及控制系统中广泛使用的一种全双工串行数据传输协议 在实际工业生产中有时并不使用UART的全部功能。

只需将其核心功能集成即可。

波特率发生器、接收器和发送器是UART的三个核心功能模块 利用Verilog-HDL语言对这三个功能模块进行描述并加以整合UART是广泛使用的串行数据传输协议。

UART允许在串行链路上进行全双工的通信。

串行外设用到RS232-C异步串行接口 一般采用专用的集成电路即UART实现。

如8250、8251、NS16450等芯片都是常见的UART器件 这类芯片已经相当复杂有的含有许多辅助的模块 如FIFO有时我们不需要使用完整UART的功能和这些辅助功能。

或者设计上用到了FPGA/CPLD器件那么我们就可以将所需要的UART功能集成到FPGA内部。

使用VHDL或Veriolog -HDL将UART的核心功能集成从而使整个设计更加紧凑、稳定且可靠。

本文应用EDA技术 基于FPGA/CPLD器件设计与实现UART。

通信指人与人或人与自然之间通过某种行为或媒介进行的信息交流与传递从广义上指需要信息的双方或多方在不违背各自意愿的情况下无论采用何种方法使用何种媒质 将信息从某方准确安全传送到另方。

通信在不同的环境下有不同的解释在出现电波传递通信后通信(Communication)被单一解释为信息的传递是指由一地向另一地进行信息的传输与交换其目的是传输消息。

然而通信是在人类实践过程中随着社会生产力的发展对传递消息的要求不断提升使得人类文明不断进步。

在各种各样的通信方式中利用“电”来传递消息的通信方法称为电信(Telecommunication) 这种通信具有迅速、准确、可靠等特点且几乎不受时间、地点、空间、距离的限制 因而得到了飞速发展和广泛应用。

FPGA模拟串口自收发-Verilog

FPGA模拟串口自收发-Verilog

实现功能,FPGA 里实现从PC 串口接收数据,接着把接收到的数据发回去。

波特率可选 9600bps,可调1bit 起始位,8bit 数据,1bit 停止位,无校验位。

参考《VHDL 硬件描述语言与和数字逻辑电路设计》模块介绍如下一、串口数据接收模块: 特别注意一个数据位占 4个clk_bps_4时钟周期。

串口数据接收控制当数据接收端rxd 出现起始位低电平,启动接收控制计数器rx_cnt,置位为 8' b0111_00(28),即 rx_cnt[5:2]== 4 ' b0111(7),rx_cnt[1:0]== 2'b00(0); —个计数周期开始,伴随clk_bps_4, rx_cnt 加1 (每一个数据位加 4) 串口接收数据移位控制(关键采样点的选取)每当rx_cnt[1:0] == 2'b01, 为了保证在 rxd 一位数据靠近中间位置采样;每 4个 clk_bps_4, rx_cnt[5:2] 力口 1 当 rx_cnt[5:2] == 8,9,10….15,完成 8 位的数据采样,串并变换置位标志位rxdF 数据接收标志rxd 出现起始位低电平,rxdF 置1 ,表示数据接收开始;当rx_cnt 计数到rxdflk reserr<scido hichF1 fr冲'豔K/ tt/ L J弃L--XrdbLLLCLK RESETI rrpset|EMPTY8'b1111_11( 63), 数据接收完成,rxdF 置0置位标志位rdFULL; 5,完成一位起始位,8 位的数据位发送,随后txd 置1(停止位),完成并串转换置位标志位txdF ,tdEMPTY st_n(rst_n),.clk_bps_4(clk_bps_4),.wr(wr),.tdEMPTY(tdEMPTY),.DATA(DATA),.txd(txd));st_n(rst_n),.clk_bps_4(clk_bps_4),.rd(rd),.rdFULL(rdFULL),.do_latch(do_latch),.rxd(rxd));/* 针对9600bps ,生成的时钟信号,用于接收数据采样与数据发送*/ Baudrate baud(.clk(clk),.rst_n(rst_n), .clk_bps_4(clk_bps_4));Endmodule串口数据接收模块:module Uart_RX(rst_n, clk_bps_4, rd, rdFULL, do_latch, rxd);input rst_n; // 低电平复位input clk_bps_4; //4 倍于波特率时钟信号即一个数据位占4 个时钟周期input rd;// 接收使能, 低电平有效output reg[7:0] do_latch;// 接收数据锁存output reg rdFULL;// 接收锁存器满标志input rxd;// 串口引脚输入reg[7:0] data_r = 8'bx; // 接收数据寄存器reg[5:0] rx_cnt;reg rxdF;// 数据接收标志,RX模块内部信号/* 当数据接收端rxd 出现起始位低电平,启动接收控制计数器rx_cnt, 置位为b0111_00(28),8'即rx_cnt[5:2]== 4 'b0111(7),rx_cnt[1:0] == 2'b00(0);一个计数周期开始,伴随clk_bps_4, rx_cnt 加1(每一个数据位加4) */ always@(posedgeclk_bps_4 or negedge rst_n)beginif(!rst_n)begin rx_cnt <= 0; endelse if(rx_cnt <= 27 && rxd == 0)begin rx_cnt <= 28; endelse if(rx_cnt <= 27 && rxd == 1)// 串口无数据时,rx_cnt 保持0 begin rx_cnt <= 0;endelsebegin rx_cnt <= rx_cnt + 1;endend/* 空闲时rdFULL 置0,当数据接收完成,数据锁存到do_latch,同时rdFULL置1,向上层模块表示数据以准备0K可以来读取;rd 置0, 表示上层模块开始读取数据,rdFULL 置0,表示数据已读走*/ always@(posedgeclk_bps_4 or negedge rst_n)// 置位标志位rdFULL beginif(!rst_n)begin rdFULL <= 0; endelse if(rd == 0)begin rdFULL <= 0; endelse if(rxdF == 1 && rx_cnt == 63)begindo_latch <= data_r;// 数据锁存rdFULL <= 1;// 锁存器数据准备0Kendend/*rxd 出现起始位低电平, rxdF 置1 ,表示数据接收开始;当rx_cnt计数到8' b1111_11(63),数据接收完成,rxdF置0* always@(posedge clk_bps_4 or negedge rst_n)// 置位标志位rxdFendcaseend endmodule串口数据发送模块:module Uart_TX(rst_n, clk_bps_4,wr,tdEMPTY, DATA, txd); input rst_n; // 低电平复位 input clk_bps_4; //4 倍于波特率时钟信号 input [7:0]DATA;beginif(!rst_n)begin rxdF <= 0; endelse if(rxd == 0)// 拉低表示有数据来begin rxdF <= 1;endelse if(rxdF == 1 && rx_cnt == 63)begin rxdF <= 0;endend/* 每当 rx_cnt[1:0] == 2'b01, 每 4 个 clk_bps_4, rx_cnt[5:2] 串并变换 */ always@(posedge clk_bps_4)// beginif( rx_cnt[1:0] == 2'b01 )case(rx_cnt[5:2]) //4'd7:rxd==0; 起始位 4'd8:data_r[0] <= rxd;// 4'd9:data_r[1] <= rxd;// 4'd10:data_r[2] <= rxd;// 4'd11:data_r[3] <= rxd;// 4'd12:data_r[4] <= rxd;// 4'd13:data_r[5] <= rxd;// 4'd14:data_r[6] <= rxd;// 4'd15:data_r[7] <= rxd;//为了保证在 力口 1 当rx_cnt[5:2]数据接收rxd 一位数据靠近中间位置采样 ; ==8,9,10…15,完成8位的数据采样,低第 1 位 第 2 位 第 3 位 第 4 位 第5位 第 6 位 第 7 位 高第 8 位input wr;// 发送使能信号output reg tdEMPTY;// 发送寄存器空标志对外输出output txd;// 串口引脚输出reg txdF;// 发送完成标志模块内部信号reg txd_r; // 发送寄存器reg[7:0] din_latch;// 发送数据锁存reg[5:0] tx_cnt;// 发送计数器/* 空闲时wr 置1,数据发送时wr 产生低电平脉冲,wr 上升沿将数据锁存到din_latch;*/ always@(posedge wr)begin//din_latch <= 8'hAB; din_latch <= DATA;end/*wr 由0 跳变为1 后,启动发送控制计数器tx_cnt, 置位为8'b0111_00(28), 即tx_cnt[5:2]== 4 'b0111(7), tx_cnt[1:0] == 2'b00(0);一个计数周期开始,伴随clk_bps_4, tx_cnt 加1(每一个数据位加4) */always@(posedge clk_bps_4 or negedge rst_n) beginif(!rst_n)begin tx_cnt <= 0; endelse if(tx_cnt <= 27)beginif(tdEMPTY == 0 && wr == 1)begin tx_cnt <= 28;endelse begin tx_cnt <= 0; endendelsebegin tx_cnt <= tx_cnt + 1;endend/*当写数据到发送寄存器din_latch 时,txdF , tdEMPTY置0;当tx_cnt 计数到8' b1111_11(63),数据发送完成,txdF , tdEMPTY置1; */ always@(posedge clk_bps_4 or negedge rst_n)beginif(!rst_n)begintxdF <= 1;tdEMPTY <= 1;endelse if(wr == 0)begintxdF <= 0;tdEMPTY <= 0;endelse if(txdF == 0 && tx_cnt == 63)begintxdF <= 1; tdEMPTY <= 1;endend/* 每4 个clk_bps_4, tx_cnt[5:2] 力口1 当tx_cnt[5:2] ==7,8,9,10 …15,完成一位起始位,8位的数据位发送,随后txd 置1(停止位) ,完成并串转换*/ always@(posedge clk_bps_4 or negedge rst_n)if(!rst_n)begintxd_r <= 1;endelsebegincase(tx_cnt[5:2])4'd7:txd_r <= 1'b0; // 起始位04'd8:txd_r <= din_latch[0]; // 低第1 位4'd9:txd_r <= din_latch[1]; // 第2位4'd10:txd_r <= din_latch[2];// 第3位4'd11:txd_r <= din_latch[3];// 第4位4'd12:txd_r <= din_latch[4];// 第5位4'd13:txd_r <= din_latch[5];// 第6位4'd14:txd_r <= din_latch[6];// 第7位4'd15:txd_r <= din_latch[7];// 高第 8 位 default:txd_r <= 1; endcase endassign txd = txd_r; endmodule波特率发生模块:/* 针对 9600bps ,生成 4 倍于波特率的时钟信号,用于采样 */ module Baudrate(clk, rst_n,clk_bps_4); input clk; // 时钟周期 50MHzinput rst_n; // 低电平复位reg clk_bps_4;always@(posedge clk or negedge rst_n) beginif(!rst_n) begin clk_bps_4 <= 0; bps_cnt <= 0;end elsebeginif(bps_cnt == N/2 - 1)begin clk_bps_4 <= ~clk_bps_4; bps_cnt <= 0;end elsebegin bps_cnt <= bps_cnt + 1;end endend endmoduleoutput clk_bps_4; //时钟信号 9600*4 reg [12:0] bps_cnt; // parameter N=1302;//波特率产生时计数 分频系数 9600bpsModelsim 仿真波形图:rxd 端输入数据 01010101 , txd 发送01010101 'i LUU'JUITJ J..ULU If.'UU- J LLbllJUJ Jlf_ L L_LLUUJllUL.LLUlllniL j.jiirjuJJUJuuLuirjiiiiiiiniLL'UU'.J J ipunnLiii 2 LJ^,ULX5tl hrjuEJumninnrLuiJiJui JirjinmfjujnLWTnimfnr TTTD 】门丁q■■nr '1 tfejarli danaj U.-UmJlfiLLfUlTJUlJ ja —i 暫主诞OfnEMJini'jinjrL'ULrjiLri I 咼岂巫:HS3E 1SS«二.■UITJXJ ifL :ui^.:jioiwwirjinr. i连接PC 串口助手。

串口通讯设计之Verilog实现

串口通讯设计之Verilog实现

串口通讯设计之V e r i l o g实现FPGA串口模块是将由RS-485发送过来的数据进行处理,提取出8位有效数据,并按异步串口通讯的格式要求输出到MAX3223的12脚;FPGA选用Xilinx公司的SpartanII系列xc2s50;此部分为该设计的主体;如上所述,输入数据的传输速率为700k波特率;为了使FPGA能够正确地对输入数据进行采样,提高分辨率能力和抗干扰能力,采样时钟必须选用比波特率更高的时钟,理论上至少是波特率时钟的2倍;1 串口通信基本特点随着多微机系统的应用和微机网络的发展,通信功能越来越显得重要;串行通信是在一根传输线上一位一位地传送信息.这根线既作数据线又作联络线;串行通信作为一种主要的通信方式,由于所用的传输线少,并且可以借助现存的电话网进行信息传送,因此特别适合于远距离传送;在串行传输中,通信双方都按通信协议进行,所谓通信协议是指通信双方的一种约定;约定对数据格式、同步方式、传送速度、传送步骤、纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守;异步起止式的祯信息格式为:每祯信息由四部分组成:位起始位;~8位数据位;传送顺序是低位在前,高位在后.依次传送;c.一位校验位,也可以没有;d.最后是1位或是2位停止位;FPGAField Pmgrammable Gate Array现场可编程门阵列在数字电路的设计中已经被广泛使用;这种设计方式可以将以前需要多块集成芯片的电路设计到一块大模块可编程逻辑器件中,大大减少了电路板的尺寸,增强了系统的可靠性和设计的灵活性;本文详细介绍了已在实际项目中应用的基于FPGA的串口通讯设计;本设计分为硬件电路设计和软件设计两部分,最后用仿真验证了程序设计的正确性;2 系统的硬件设计本方案的异步串行通信的硬件接口电路图如图1所示,主要由四部分组成:RS-485数据发送模块、FPGA 串口模块、MAX3223和DB9;各部分功能简述如下:RS-485数据发送模块是将前续电路的数据发送到FPGA,供本电路处理,亦即本电路的输入;RS485是符合RS-485和RS-4225串口标准的低功耗半双工收发器件,有和5V两种,在本设计中选用了的器件SP3485;在本设计中;485的7脚和8脚与前端信号相连接,用于接收输入的数据;数据格式是这样的:一帧数据有25位,报头是16个高电平和1个低电平,接下来是8位有效的数据;传输速率为700k波特率;2脚是使能端,与FPGA的I/O 口相连,由FPGA提供逻辑控制信号;1脚和4脚也与FPGA相连,由FPGA对输入数据进行处理;FPGA串口模块是将由RS-485发送过来的数据进行处理,提取出8位有效数据,并按异步串口通讯的格式要求输出到MAX3223的12脚;FPGA选用Xilinx公司的Spartan II系列xc2s50;此部分为该设计的主体;如上所述,输入数据的传输速率为700k波特率;为了使FPGA能够正确地对输入数据进行采样,提高分辨率能力和抗干扰能力,采样时钟必须选用比波特率更高的时钟,理论上至少是波特率时钟的2倍;在本设计中选用4倍于波特率的时钟,利用这种4倍于波特率的接收时钟对串行数据流进行检测和定位采样,接收器能在一个位周期内采样4次;如果没有这种倍频关系,定位采样频率和传送波特率相同,则在一个位周期中,只能采样一次,分辨率会差;比如,为了检测起始位下降沿的出现,在起始位的前夕采样一次之后,下次采样要到起始位结束前夕才进行;而假若在这个周期期间,因某种原因恰恰使接收时钟往后偏移了一点点,就会错过起始位;造成整个后面位的检测和识别错误;针对本设计,FPGA的软件共分了三个模块:1.时钟分频模块;模块的功能是用来产生所需要的数据采集时钟和数据传输时钟;系统主频是40M的;数据采集时钟是2.8M的,发送时钟是;2. 提取数据模块;由RS485发送过来的数据共有25位,其中只有8位是有效数据;为了发送这8位有效数据;必须先将其提取出来;提取的办法是这样的:通过连续检测到的16个高电平和一个低电平;判断8位有效数据的到来;然后按照串行数据传输的格式,在加上起始位和停止位后,将其存储于输出缓冲寄存器中;在这里,我们的串行数据输出格式是这样规定的,一位起始位,八位数据位,一位停止位,无校验位;3.串行数据输出模块;这一模块相对比较简单,波特率选为,模块的功能是在移位输出脉冲的作用下,将输出缓冲寄存器中的数据移位输出;MAX3223是实现电平转换的芯片;由于RS-232c是用正负电压来表示逻辑状态;与TTL以高低电平表示逻辑状态的规定不同;因此,为了能够同计算机接口或终端的TTL器件连接,必须在RS-232与TTL电路之间进行电平和逻辑关系的变换;实现这种变换的方法可用分立元件,也可用集成电路芯片; MAXIM公司的MAX3223是为满足RS-232c 的标准而设计的具有功耗低、波特率高、价格低等优点,外接电容仅为或1uF,为双组RS232收发器;由MAX3223的12脚输入的数据,经过电平转换后由8脚输出,再经过DB9的TxD端输出,由PC机接收并做后续处理;3 系统软件设计FPGA模块是本设计的主体,使用Verilog硬件描述语言进行编写,本段代码共有两个子模块,分别实现提取八位数据和串行数据发送的功能;下面是verilog源代码module SIMOdin,clk,rst,dout_ser;input din; 4倍于波特率的时钟reg txclk; //发送数据时钟;发数据取的波特率integer bitpos="7"; //当前位parameters0=0,s1=1,s2=2,s3=3;reg2:0state;reg4:0counter; //用来计算报头报尾中1的个数reg tag,tag1;reg2:0cnt3;reg txdone="1"''''b1;//一个字节数据传输完毕标志提取有效数据位并按串行通讯格式装载数据always posedge nclk or posedge rstbegin ifrst begin state<=0; counter<=0; tag1=0; tag="0"; indata_buf<=8''''bz; dout_buf<=10''''bz; bitpos ="7"; cnt3<=0; end else casestate s0:begin tag="0";//表示数据没有装好ifdinbegin counter<=counter+1; state<=s0; ifcounter==15//如果检测到16个1则转入s1状态检测接下来的是不是0begin state<=s1; counter<=0;end endelse begin counter<=0; state<=s0;end end s1:ifdin//如果是0的话,转入s2状态,提取八位有效数据state<=s2; else //否则转到s0状态重新检测state<=s0; s2:ifcnt3==3//是否采集四次数据begin cnt2<=0; indata_bufbitpos<=din; //先进来的是高位数据bitpos="bitpos-1"; ifbitpos==-1begin bitpos=7;state<=s3;endend elsecnt3<=cnt3+1; s3:begin tag1=tag; tag=1''''b1; //标志输入寄存器满;表明已把有用数据装入寄存器iftag&&~tag1&&txdone //检测到tag的上升沿以及txdone为高才把输入缓冲数据放到输出缓冲去dout_buf<={1''''b1,indata_buf7:0,1''''b0};//停止位,高位,低位,起始位state<=s0; end endcaseend//发送数据模块reg3:0 state_tx=0;txclk or posedge rstbegin ifrst begindout_ser<=1''''bz;state_tx<=0;txdone=1; end elsecasestate_tx0:begin dout_ser<=dout_buf0;state_tx<=state_tx+1;txdone=1''''b0;end 1:begin dout_ser<=dout_buf1;s tate_tx<=state_tx+1;end 2:begin dout_ser<=dout_buf2;state_tx<=state_tx+1;end 3:begin dout_ser<=dout_buf 3;state_tx<=state_tx+1;end 4:begin dout_ser<=dout_buf4;state_tx<=state_tx+1;end 5:begin dout_ser<=dout_ buf5;state_tx<=state_tx+1;end 6:begin dout_ser<=dout_buf6;state_tx<=state_tx+1;end 7:begin dout_ser<=do ut_buf7;state_tx<=state_tx+1;end 8:begin dout_ser<=dout_buf8;state_tx<=state_tx+1;end 9:begin dout_ser< =dout_buf9;state_tx<=state_tx+1;end endcase endendmodule注:两个频率信号nclk、txclk由相应的分频程序产生;由于篇幅所限未在文中列出;FPGA模块接收从RS-485发送过来的串行数据;25位为一个字符;数据的传输速率是700kbps,用四倍于波特率的速率进行采样,这样可以大大降低系统的噪声;数据的串行输出波特率选为11200bps;由输入输出波形图可以看出:本段程序实现了对输入数据的有效数据位的提取,并按照一定的波特率进行串行输出;程序中,波特率可以根据需要通过分频程序进行改动;硬件电路搭建简单,程序代码书写容易;数据传输稳定可靠,可以满足串口通信的要求;。

fpga语法知识点总结

fpga语法知识点总结

fpga语法知识点总结一、Verilog语言Verilog是一种硬件描述语言(HDL),用于描述数字电路和系统级设计。

在FPGA设计中,Verilog语言常常用于描述逻辑功能和时序控制。

Verilog语言包括模块、端口、信号声明、组合逻辑、时序逻辑、行为模拟等部分。

1. 模块:Verilog中的模块是一个最基本的组织单位,它类似于面向对象编程中的类。

每个模块都有自己的输入输出端口和内部逻辑实现。

在FPGA设计中,通常会设计多个模块来实现不同的功能,然后将这些模块连接起来,构成一个完整的系统。

2. 端口:在Verilog中,端口用于定义模块与外部环境的接口。

端口可以被定义为输入端口(input)、输出端口(output)、双向端口(inout)等,用于进行与外部信号的通信。

3. 信号声明:在Verilog中,信号用于传递逻辑信息。

信号可以是单个的位(bit)信号,也可以是多位(bus)信号。

在FPGA设计中,对信号的声明和使用是非常重要的,可以影响到设计的性能和资源占用。

4. 组合逻辑:组合逻辑是一种不含时钟的逻辑电路,其输出仅由输入决定。

在Verilog中,组合逻辑常常使用逻辑运算符和条件语句来描述。

5. 时序逻辑:时序逻辑是一种包含时钟信号的逻辑电路,其输出由时钟信号和输入信号共同决定。

在FPGA设计中,时序逻辑和时序约束非常重要,可以影响到设计的时序性能。

6. 行为模拟:行为模拟是一种用于验证设计功能和性能的技术。

在Verilog中,可以使用行为模拟语句来描述设计的行为,并进行仿真验证。

二、VHDL语言VHDL(VHSIC Hardware Description Language)是一种硬件描述语言,用于描述数字电路和系统级设计。

在FPGA设计中,VHDL语言和Verilog语言一样,用于描述逻辑功能和时序控制。

VHDL语言包括实体、端口、信号声明、组合逻辑、时序逻辑、行为模拟等部分。

1. 实体:在VHDL中,实体是描述一个硬件单元的基本描述。

fpga做485通信

fpga做485通信

在FPGA中实现RS485通信,需要控制发送方和接收方的差分信号输出和输入。

以下是一个基本的步骤:
1. 定义输入输出端口:在Verilog代码中,通过定义不同的输入输出端口来实现发送和接收功能。

2. 编码数据:发送方将要发送的数据通过编码后转换成差分信号输出。

常用的编码方式有NRZ(非归零码)、Manchester码等。

3. 接收数据:接收设备检测到双绞线上的RS485电平的每一个单bit数据,将其转换为普通的TTL电平信号,并通过接收器输出脚送给UART控制器的接收脚。

4. 解码数据:UART控制器将接收脚上的每一个单bit信号按照UART协议进行接收解码,得到以字节为单位的实际数据。

5. 数据解析:MODBUS协议栈将UART接收到的多个字节数据进行解析得到完整的数据帧,并解帧得到实际的数据部分。

在实际应用时,MODBUS协议栈一般由CPU通过软件方式实现。

以上步骤仅供参考,建议咨询专业人士获取具体信息。

《FPGA设计与应用》实验指导书全(Verilog版)

《FPGA设计与应用》实验指导书全(Verilog版)

《FPGA设计与应用》实验指导书某某编武汉理工大学华夏学院2011年9月前言一、实验课目的数字电路与系统设计实验课是电子工程类专业教学中重要的实践环节,包括了ISE开发环境基本操作及FPGA的基本原理、基带传输系统的设计、Uart串口控制器电路的设计、PS/2接口的设计、VGA显示接口设计。

要求学生通过实验学会正确使用EDA技术,掌握FPGA器件的开发,熟练使用ISE开发环境,掌握Verilog语言的编程,掌握数字电路和系统的设计。

通过实验,使学生加深对课堂专业教学内容的理解,培养学生理论联系实际的能力,实事求是,严谨的科学作风,使学生通过实验结果,利用所学的理论去分析研究EDA技术。

培养学生使用Basys 2开发板的能力以及运用实验方法解决实际问题的能力。

二、实验要求:1.课前预习①认真阅读实验指导书,了解实验内容;②认真阅读有关实验的理论知识;③读懂程序代码。

2.实验过程①按时到达实验室;②认真听取老师对实验内容及实验要求的讲解;③认真进行实验的每一步,观察程序代码与仿真结果是否相符;④将实验过程中程序代码和仿真结果提交给老师审查;⑤做完实验后,整理实验设备,关闭实验开发板电源、电脑电源后方可离开。

3.实验报告①按要求认真填写实验报告书;②认真分析实验结果;③按时将实验报告交给老师批阅。

三、实验学生守则1.保持室内整洁,不准随地吐痰、不准乱丢杂物、不准大声喧哗、不准吸烟、不准吃东西;2.爱护公务,不得在实验桌及墙壁上书写刻画,不得擅自删除电脑里面的文件;3.安全用电,严禁触及任何带电体的裸露部分,严禁带电接线和拆线;4.任何规章或不按老师要求操作造成仪器设备损坏须论价赔偿。

目录实验一Uart通用串口接口的设计 (4)实验二PS/2接口的设计 (28)实验三VGA显示接口设计 (30)附录一 basys 2开发板资料 (36)实验一 Uart串口控制接口电路的设计一、实验目的1.掌握分频模块的设计方法。

串行器verilog代码

串行器verilog代码

串行器verilog代码串行器(Serializer)是一种电子设备,用于将并行数据转换为串行数据,以便在单个通道上进行传输。

以下是一个简单的串行器的 Verilog 代码示例:verilogmodule Serializer (input wire clk, // 时钟信号input wire reset, // 复位信号input wire [7:0] parallel_data, // 并行数据输入output reg serial_data // 串行数据输出);reg [2:0] shift_reg; // 移位寄存器,用于存储并行数据的位reg [2:0] count; // 计数器,用于控制移位寄存器的移位次数always @(posedge clk or posedge reset) beginif (reset) begin// 当复位信号为高电平时,将计数器和移位寄存器清零count <= 0;shift_reg <= 0;serial_data <= 0;end else beginif (count == 3'd7) begin// 当计数器达到最大值时,将并行数据的最低位存入移位寄存器,并将计数器清零shift_reg <= {parallel_data[0], shift_reg[2:1]};count <= 0;end else begin// 否则,将移位寄存器向左移动一位,并将计数器加1shift_reg <= {shift_reg[1:0], serial_data};count <= count + 1;end// 将移位寄存器的最低位作为串行数据输出serial_data <= shift_reg[0];endendendmodule需要注意的是,上述代码中的计数器 count 用于控制移位寄存器的移位次数,当计数器达到最大值时,将并行数据的最低位存入移位寄存器,并将计数器清零。

基于FPGA的串口通信电路设计

基于FPGA的串口通信电路设计

基于FPGA的串口通信电路设计[摘要]串行通信接口是一种应用广泛的通信接口。

目前,大部分处理器都集成了支持rs-232接口的通用异步收发器,本文基于fpga开发板设计了一个串口数据采集和处理程序,介绍了用verilog hdl硬件描述语言来开发波特率发生器、接收模块和发送模块这三个模块,以及系统各个模块的具体设计方法和原理,用quartus ii软件进行仿真并给出结果,分别验证各个模块的正确性及用fpga实现串行通信的可行性。

[关键词]串行通信 rs-232 verilog hdl fpga中图分类号:tn 文献标识码:a 文章编号:1009-914x(2013)08-320-011.fpga概述fpga现场可编程逻辑门阵列是数字系统设计的主要硬件平台,其主要特点是完全由用户通过软件进行配置和编程,从而完成某种特定的功能,且可以反复擦写。

fpga具有运算速度快、根据需求在内部嵌入硬/软ip核,以及反复编程,擦写,使用的特点,被广泛应用于通信,数字信号处理,工业控制等领域。

2.rs232串口通信接口串口即串行数据接口主要用于网管控制或主业务数据的传输,支持数据的双向传输,速率9600-115200bps,即可以完成和pc的通信,也可以完成与带有标准串口的外设相连。

其中串口接口分为带插孔和带插针的两种,其中插针端称为dce,插孔端称为dte。

3.串口通信的verilog hdl实现本设计要求在fpga开发板上实现波特率为115200bps,停止位为1比特、1比特校验位的串口通信,并要求和pc机通过串口调试助手完成双向通信。

3.1波特率发生器模块的verilog hdl实现波特率发生器实际上是一个分频器,从给定的系统时钟频率得到要求的波特率。

一般来讲,为了提高系统的容错性处理,要求波特率发生器的输出时钟为实际串口数据波特率的n倍,n可以取值为8、16、32、64等。

在本设计中,系统的时钟为50mhz,取n为16,则分频系数为50000000/(16*115200)=27.127,取整为27。

Verilog实现串口通信

Verilog实现串口通信

FPGA实现串行接口RS232时间:2007-06-29 来源: 作者: 点击:26463 字体大小:【大中小】-串行接口(RS-232)串行接口是连接FPGA和PC机的一种简单方式。

这个项目向大家展示了如果使用FPGA来创建RS-232收发器。

整个项目包括5个部分RS232是怎样工作的如何产生需要的波特率发送模块接收模块应用实例RS-232接口是怎样工作的作为标准设备,大多数的计算机都有1到2个RS-232串口。

特性RS-232有下列特性:使用9针的"DB-9"插头(旧式计算机使用25针的"DB-25"插头).允许全双工的双向通讯(也就是说计算机可以在接收数据的同时发送数据).最大可支持的传输速率为10KBytes/s.DB-9插头你可能已经在你的计算机背后见到过这种插头它一共有9个引脚,但是最重要的3个引脚是:引脚2: RxD (接收数据).引脚3: TxD (发送数据).引脚5: GND (地).仅使用3跟电缆,你就可以发送和接收数据.串行通讯数据以每次一位的方式传输;每条线用来传输一个方向的数据。

由于计算机通常至少需要若干位数据,因此数据在发送之前先“串行化”。

通常是以8位数据为1组的。

先发送最低有效位,最后发送最高有效位。

异步通讯RS-232使用异步通讯协议。

也就是说数据的传输没有时钟信号。

接收端必须有某种方式,使之与接收数据同步。

对于RS-232来说,是这样处理的:串行线缆的两端事先约定好串行传输的参数(传输速度、传输格式等)当没有数据传输的时候,发送端向数据线上发送"1"每传输一个字节之前,发送端先发送一个"0"来表示传输已经开始。

这样接收端便可以知道有数据到来了。

开始传输后,数据以约定的速度和格式传输,所以接收端可以与之同步每次传输完成一个字节之后,都在其后发送一个停止位("1")让我们来看看0x55是如何传输的:0x55的二进制表示为:01010101。

verilog电路模块的端口描述

verilog电路模块的端口描述

verilog电路模块的端口描述Verilog电路模块的端口描述在Verilog语言中,模块是电路设计的基本单元。

模块定义了电路的功能和接口,其中端口描述了模块与外部环境的交互方式。

本文将围绕Verilog电路模块的端口描述展开讨论,介绍常见的端口类型和其功能。

一、输入端口(Input Port)输入端口用于接收外部信号输入到模块中,以供模块内部进行处理。

输入端口通常用于接收控制信号、数据信号等。

例如,一个简单的输入端口描述如下:input reg clk;input [7:0] data_in;在上述描述中,input关键字表示该端口为输入端口,reg关键字表示该端口是一个寄存器类型的信号。

clk是一个时钟信号,data_in 是一个8位的数据输入端口。

二、输出端口(Output Port)输出端口用于将模块内部处理的结果输出到外部环境中。

输出端口通常用于输出计算结果、状态信号等。

例如,一个简单的输出端口描述如下:output reg [7:0] data_out;在上述描述中,output关键字表示该端口为输出端口,reg关键字表示该端口是一个寄存器类型的信号。

data_out是一个8位的数据输出端口。

三、双向端口(Inout Port)双向端口可以实现输入和输出的双向传输。

它可以在一个时钟周期内既作为输入端口接收信号,又作为输出端口输出信号。

例如,一个简单的双向端口描述如下:inout [7:0] data_io;在上述描述中,inout关键字表示该端口为双向端口。

data_io是一个8位的双向数据端口,可以同时作为输入和输出。

四、时钟端口(Clock Port)时钟端口用于接收时钟信号,是数字电路设计中非常重要的一个端口。

时钟信号用于同步电路中的时序操作。

例如,一个简单的时钟端口描述如下:input reg clk;在上述描述中,input关键字表示该端口为输入端口,reg关键字表示该端口是一个寄存器类型的信号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实现功能,FPGA里实现从PC串口接收数据,接着把接收到的数据发回去。

波特率可选9600bps,可调1bit起始位,8bit数据,1bit停止位,无校验位。

参考《VHDL硬件描述语言与和数字逻辑电路设计》模块介绍如下一、串口数据接收模块:特别注意一个数据位占4个clk_bps_4时钟周期。

串口数据接收控制当数据接收端rxd出现起始位低电平,启动接收控制计数器rx_cnt,置位为8’b0111_00(28),即rx_cnt[5:2]== 4’b0111(7),rx_cnt[1:0] == 2'b00(0);一个计数周期开始,伴随clk_bps_4, rx_cnt加1(每一个数据位加4)串口接收数据移位控制(关键采样点的选取)每当rx_cnt[1:0] == 2'b01,为了保证在rxd一位数据靠近中间位置采样;每4个clk_bps_4, rx_cnt[5:2]加1当rx_cnt[5:2] == 8,9,10….15,完成8位的数据采样,串并变换置位标志位rxdF数据接收标志rxd出现起始位低电平, rxdF置1,表示数据接收开始;当rx_cnt计数到8’b1111_11(63),数据接收完成,rxdF置0置位标志位rdFULL;//接收锁存器满标志空闲时rdFULL置0,当数据接收完成,数据锁存到do_latch,同时rdFULL置1,向上层模块表示数据以准备OK,可以来读取;rd置0,表示上层模块开始读取数据,rdFULL置0,表示数据已读走二、串口数据发送模块:数据发送依赖于wr(低电平有效)空闲时wr置1,数据发送时wr产生低电平脉冲,wr上升沿将数据锁存到din_latch;串口数据发送控制:wr由0跳变为1后,启动发送控制计数器tx_cnt,置位为8’b0111_00(28),即tx_cnt[5:2]== 4’b0111(7), tx_cnt[1:0] == 2'b00(0);一个计数周期开始,伴随clk_bps_4, tx_cnt加1(每一个数据位加4)串口发送数据移位控制每4个clk_bps_4, tx_cnt[5:2]加1当tx_cnt[5:2] ==7,8,9,10….15,完成一位起始位,8位的数据位发送,随后txd置1(停止位),完成并串转换置位标志位txdF,tdEMPTY //发送完成标志当写数据到发送寄存器din_latch时,txdF,tdEMPTY置0;当tx_cnt计数到8’b1111_11(63),数据发送完成,txdF,tdEMPTY置1;三、串口数据自收发控制模块当rdFULL == 1&& tdEMPTY == 1(rdFULL == 1表示数据准备OK,tdEMPTY == 1表示上次发送已完成) ,rd,wr产生低脉冲,rd置0,数据读取到DATA,wr置0使能发送数据控制,低脉冲将DATA锁存到din_latch四、波特率发生模块:针对9600bps,生成4倍于波特率38.4KHz的时钟信号,用于采样代码如下:串口数据自收发控制模块module UART(clk, rst_n, rxd, txd, LED1 );input clk; //时钟周期50MHzinput rst_n; //低电平复位input rxd; //串口引脚输入<--接收<--PCoutput txd; //串口引脚输出-->发送-->PCoutput reg LED1;//lED测试用/****************************************/wire tdEMPTY;//发送寄存器空标志reg wr;//发送使能信号reg [7:0]DATA;wire clk_bps_4;//4倍于波特率时钟信号reg[1:0] wr_cnt;//wr低电平计数reg rd;//读接收锁存器信号wire[7:0] do_latch;//接收数据锁存wire rdFULL;//接收锁存器满标志reg[1:0] rd_cnt;//rd低电平计数/*当rdFULL == 1&& tdEMPTY == 1(rdFULL == 1表示接收锁锁存器数据准备OK,tdEMPTY == 1表示上次发送已完成),rd,wr产生低脉冲,rd置0,do_latch数据读取到DATA,wr置0用于使能发送数据控制,低脉冲将DATA锁存到din_latch*/always@(posedge clk_bps_4 or negedge rst_n)beginif(!rst_n)beginrd <= 1;wr <= 1;wr_cnt <= 0;rd_cnt <= 0;endelsebeginif(rdFULL == 1)beginrd <= 0;wr <= 0;wr_cnt <= 0;rd_cnt <= 0;DATA <= do_latch;endif(rd == 0)//产生rd低电平2个clk_bps_4周期beginrd_cnt <= rd_cnt + 1;if(rd_cnt == 3)rd <= 1;endif(wr == 0)//产生wr低电平2个clk_bps_4周期beginwr_cnt <= wr_cnt + 3;if(wr_cnt == 1)wr <= 1;endendend/*发送*/Uart_TX tx( .rst_n(rst_n),.clk_bps_4(clk_bps_4),.wr(wr),.tdEMPTY(tdEMPTY),.DATA(DATA),.txd(txd));//output to tx_m/*接收*/Uart_RX rx( .rst_n(rst_n),.clk_bps_4(clk_bps_4),.rd(rd),.rdFULL(rdFULL),.do_latch(do_latch),.rxd(rxd));/*针对9600bps,生成38.4KHz的时钟信号,用于接收数据采样与数据发送*/Baudrate baud(.clk(clk),.rst_n(rst_n),.clk_bps_4(clk_bps_4));Endmodule串口数据接收模块:module Uart_RX(rst_n, clk_bps_4, rd, rdFULL, do_latch, rxd);input rst_n; //低电平复位input clk_bps_4; //4倍于波特率时钟信号即一个数据位占4个时钟周期input rd;//接收使能,低电平有效output reg[7:0] do_latch;//接收数据锁存output reg rdFULL;//接收锁存器满标志input rxd;//串口引脚输入reg[7:0] data_r = 8'bx; //接收数据寄存器reg[5:0] rx_cnt;reg rxdF;//数据接收标志,RX模块内部信号/*当数据接收端rxd出现起始位低电平,启动接收控制计数器rx_cnt,置位为8’b0111_00(28),即rx_cnt[5:2]== 4’b0111(7),rx_cnt[1:0] == 2'b00(0);一个计数周期开始,伴随clk_bps_4, rx_cnt加1(每一个数据位加4)*/always@(posedge clk_bps_4 or negedge rst_n)beginif(!rst_n)begin rx_cnt <= 0; endelse if(rx_cnt <= 27 && rxd == 0)begin rx_cnt <= 28; endelse if(rx_cnt <= 27 && rxd == 1)//串口无数据时,rx_cnt保持0begin rx_cnt <= 0; endelsebegin rx_cnt <= rx_cnt + 1;endend/*空闲时rdFULL置0,当数据接收完成,数据锁存到do_latch,同时rdFULL置1,向上层模块表示数据以准备OK,可以来读取;rd置0,表示上层模块开始读取数据,rdFULL置0,表示数据已读走*/always@(posedge clk_bps_4 or negedge rst_n)//置位标志位rdFULLbeginif(!rst_n)begin rdFULL <= 0; endelse if(rd == 0)begin rdFULL <= 0; endelse if(rxdF == 1 && rx_cnt == 63)begindo_latch <= data_r;//数据锁存rdFULL <= 1;//锁存器数据准备OKendend/*rxd出现起始位低电平, rxdF置1,表示数据接收开始;当rx_cnt计数到8’b1111_11(63),数据接收完成,rxdF置0*/always@(posedge clk_bps_4 or negedge rst_n)//置位标志位rxdFbeginif(!rst_n)begin rxdF <= 0; endelse if(rxd == 0)//拉低表示有数据来begin rxdF <= 1;endelse if(rxdF == 1 && rx_cnt == 63)begin rxdF <= 0;endend/*每当rx_cnt[1:0] == 2'b01,为了保证在rxd一位数据靠近中间位置采样;每4个clk_bps_4, rx_cnt[5:2]加1当rx_cnt[5:2] == 8,9,10…15,完成8位的数据采样,串并变换*/always@(posedge clk_bps_4)//数据接收beginif( rx_cnt[1:0] == 2'b01 )case(rx_cnt[5:2])//4'd7:rxd==0;起始位4'd8:data_r[0] <= rxd;// 低第1位4'd9:data_r[1] <= rxd;// 第2位4'd10:data_r[2] <= rxd;// 第3位4'd11:data_r[3] <= rxd;// 第4位4'd12:data_r[4] <= rxd;// 第5位4'd13:data_r[5] <= rxd;// 第6位4'd14:data_r[6] <= rxd;// 第7位4'd15:data_r[7] <= rxd;//高第8位endcaseendendmodule串口数据发送模块:module Uart_TX(rst_n, clk_bps_4,wr,tdEMPTY, DATA, txd);input rst_n; //低电平复位input clk_bps_4; //4倍于波特率时钟信号input [7:0]DATA;input wr;//发送使能信号output reg tdEMPTY;//发送寄存器空标志对外输出output txd;//串口引脚输出reg txdF;//发送完成标志模块内部信号reg txd_r; //发送寄存器reg[7:0] din_latch;//发送数据锁存reg[5:0] tx_cnt;//发送计数器/*空闲时wr置1,数据发送时wr产生低电平脉冲,wr上升沿将数据锁存到din_latch;*/ always@(posedge wr)begin//din_latch <= 8'hAB;din_latch <= DATA;end/*wr由0跳变为1后,启动发送控制计数器tx_cnt,置位为8’b0111_00(28),即tx_cnt[5:2]== 4’b0111(7), tx_cnt[1:0] == 2'b00(0);一个计数周期开始,伴随clk_bps_4, tx_cnt加1(每一个数据位加4)*/always@(posedge clk_bps_4 or negedge rst_n)beginif(!rst_n)begin tx_cnt <= 0; endelse if(tx_cnt <= 27)beginif(tdEMPTY == 0 && wr == 1)begin tx_cnt <= 28;endelse begin tx_cnt <= 0; endendelsebegin tx_cnt <= tx_cnt + 1;endend/*当写数据到发送寄存器din_latch时,txdF,tdEMPTY置0;当tx_cnt计数到8’b1111_11(63),数据发送完成,txdF,tdEMPTY置1;*/always@(posedge clk_bps_4 or negedge rst_n)beginif(!rst_n)begintxdF <= 1;tdEMPTY <= 1;endelse if(wr == 0)begintxdF <= 0;tdEMPTY <= 0;endelse if(txdF == 0 && tx_cnt == 63)begintxdF <= 1;tdEMPTY <= 1;endend/*每4个clk_bps_4, tx_cnt[5:2]加1当tx_cnt[5:2] ==7,8,9,10…15,完成一位起始位,8位的数据位发送,随后txd置1(停止位),完成并串转换*/always@(posedge clk_bps_4 or negedge rst_n)if(!rst_n)begintxd_r <= 1;endelsebegincase(tx_cnt[5:2])4'd7:txd_r <= 1'b0; //起始位04'd8:txd_r <= din_latch[0]; //低第1位4'd9:txd_r <= din_latch[1]; // 第2位4'd10:txd_r <= din_latch[2];// 第3位4'd11:txd_r <= din_latch[3];// 第4位4'd12:txd_r <= din_latch[4];// 第5位4'd13:txd_r <= din_latch[5];// 第6位4'd14:txd_r <= din_latch[6];// 第7位4'd15:txd_r <= din_latch[7];//高第8位default:txd_r <= 1;endcaseendassign txd = txd_r;endmodule波特率发生模块:/*针对9600bps,生成4倍于波特率38.4KHz的时钟信号,用于采样*/ module Baudrate(clk, rst_n,clk_bps_4);input clk; //时钟周期50MHzinput rst_n; //低电平复位output clk_bps_4; //38.4KHz时钟信号9600*4reg clk_bps_4;reg [12:0] bps_cnt; //波特率产生时计数parameter N=1302;//分频系数9600bpsalways@(posedge clk or negedge rst_n)beginif(!rst_n) begin clk_bps_4 <= 0; bps_cnt <= 0;endelsebeginif(bps_cnt == N/2 - 1)begin clk_bps_4 <= ~clk_bps_4; bps_cnt <= 0;endelsebegin bps_cnt <= bps_cnt + 1;endendendendmoduleModelsim仿真波形图:rxd端输入数据01010101,txd发送01010101连接PC 串口助手。

相关文档
最新文档