首页 FPGA verilog uart串口收发代码

FPGA verilog uart串口收发代码

举报
开通vip

FPGA verilog uart串口收发代码ART波形图如下图所示,最简单的一种形式:1位起始位(低),8位数据位,1位停止位(高)。UART没有同步时钟,按照约定好的时间(波特率)进行间隔采样。 1, UART 数据发送模块 只需按照上图所示的波形图把需要传输的数据输出即可,由于发射时钟和系统时钟同步,我们使用一个计数器对50MHz系统时钟分频产生发送数据时钟。建立一个发送状态机,共四种状态,在每个状态输出相应的信息。 本模块为了方便调试,输出一个闪烁灯,按下一个键,发送一个固定的数据。代码如下: module UART_TX( tx, rx, sw0...

FPGA verilog uart串口收发代码
ART波形图如下图所示,最简单的一种形式:1位起始位(低),8位数据位,1位停止位(高)。UART没有同步时钟,按照约定好的时间(波特率)进行间隔采样。 1, UART 数据发送模块 只需按照上图所示的波形图把需要传输的数据输出即可,由于发射时钟和系统时钟同步,我们使用一个计数器对50MHz系统时钟分频产生发送数据时钟。建立一个发送状态机,共四种状态,在每个状态输出相应的信息。 本模块为了方便调试,输出一个闪烁灯,按下一个键,发送一个固定的数据。代码如下: module UART_TX( tx, rx, sw0, sendkey0, clk, rst, led ); output                    tx; input                    rx; input        [3:0]                sw0; input                        sendkey0; input                    clk,rst; output                    led; //output discribe reg                        led; reg                        tx; // baud rate:38400 parameter                UART_CLK_DIV    =50000000/38400/2;//额外的/2是因为产生时钟使用了~方式 //发送数据状态机 parameter                sstate_idle        =0; parameter                sstate_begin    =1; parameter                sstate_sdat        =2; parameter                sstate_end        =3; reg        [2:0]            curstate;    //当前状态 reg        [7:0]            senddata;    //需要发送的数据 reg        [3:0]            tosendcnt;    //需要发送计数器计数 reg        [3:0]            alsendcnt;    //已经发送数据计数 reg                        sendclk;        //数据发送时钟 reg        [15:0]        clk_divcnt; //发送时钟分频计数器 reg        [2:0]            bitcnt;        //发送数据的位选择 //产生发送数据的对应时钟 always@(posedgeclk, negedgerst)begin if(!rst)begin sendclk<=1'b0; clk_divcnt<=0; end else begin if(clk_divcnt==UART_CLK_DIV-1)begin clk_divcnt<=0; sendclk<=~sendclk; end else begin clk_divcnt<=clk_divcnt+1; end end end //状态转换 always@(posedgesendclk,negedgerst)begin if(!rst)begin alsendcnt<=0; curstate<=sstate_idle; end else begin case(curstate) sstate_idle:begin if(alsendcnt!=tosendcnt)begin // have data to send alsendcnt<=alsendcnt+1;        // count the number have send curstate<=sstate_begin; end else begin curstate<=sstate_idle; end end sstate_begin:begin curstate<=sstate_sdat; bitcnt<=3'b0; senddata<=sw0+8'd97;                // get the data to send end sstate_sdat:begin if(bitcnt==7)begin curstate<=sstate_end; end else begin bitcnt<=bitcnt+1; end end sstate_end:begin curstate<=sstate_idle;            end default:curstate<=sstate_idle; endcase end end //输出数据 always@(*)begin if(~rst)tx<=1; else begin case(curstate) sstate_idle:begin tx<=1;    end sstate_begin:begin tx<=1'b0;                end sstate_sdat:begin tx<=senddata[bitcnt];            end sstate_end:begin tx<=1'b1;        end endcase end end //按下一个键发送一个数据 always@(posedge sendkey0, negedgerst)begin if(!rst)begin tosendcnt<=0; end else begin tosendcnt<=tosendcnt+1'b1; end end // led debug use reg        [31:0]        ledcnt; always@(posedgeclk,negedgerst)begin if(!rst)begin ledcnt<=0; led<=1'b1; end else begin if(ledcnt<20000000)begin ledcnt<=ledcnt+1'b1; end else begin led<=~led; ledcnt<=0; end end end endmodule 2, UART数据接收模块 由于不清楚何时数据到达,即时钟并不同步,使用和串口一样的时钟来判断输入数据并不适合。这里为了稳定,在每个数据波形的中间进行采样。代码如下: module UART_RX( tx, rx, hex1,//使用数码管显示收到的数据 hex0, clk, rst, led ); output                    tx; input                    rx; output    [6:0]            hex1,hex0; input                    clk,rst; output                    led; //output declaration reg                        led; reg        [7:0]            dispdat; assign                    tx    =1'b1; // baud rate:38400 // parameter                UART_CLK_DIV    =50000000/38400;//需要分频比例 //状态 parameter                rstate_idle        =0; parameter                rstate_beginq    =1;//是否真的有数据传输 parameter                rstate_begin    =2; parameter                rstate_rdata    =3; parameter                rstate_end        =4; reg        [2:0]            curstate; reg        [15:0]        clkcnt; reg        [2:0]            bitcnt;    reg        [7:0]            recdata; always@(posedgeclk, negedgerst)begin if(!rst)begin curstate<=rstate_idle; clkcnt<=0; end else begin case(curstate) rstate_idle:begin if(~rx)begin curstate<=rstate_beginq; bitcnt<=0; clkcnt<=0; recdata<=0; end else  curstate<=rstate_idle; end rstate_beginq:begin if(clkcnt==UART_CLK_DIV/2-1)begin//1/2是为了在每个波形的中间进行判断 clkcnt<=0; if(~rx)begin curstate<=rstate_rdata; end else    begin curstate<=rstate_idle; end    end else begin clkcnt<=clkcnt+1'b1; end end rstate_rdata:begin if(clkcnt==UART_CLK_DIV-1)begin clkcnt<=0; recdata[bitcnt]<=rx; if(bitcnt==7)begin curstate<=rstate_end; end else begin bitcnt<=bitcnt+1'b1; end end else begin clkcnt<=clkcnt+1'b1; end end rstate_end:begin if(clkcnt==UART_CLK_DIV-1)begin clkcnt<=0; curstate<=rstate_idle; end else begin clkcnt<=clkcnt+1'b1; end end default:curstate<=rstate_idle; endcase end end always@(curstate,bitcnt)begin case(curstate) rstate_rdata:begin end rstate_end:begin dispdat<=recdata;/////////////debug end default:begin end endcase end // led debug use reg        [31:0]        ledcnt; always@(posedgeclk,negedgerst)begin if(!rst)begin ledcnt<=0; led<=1'b1; end else begin if(ledcnt<20000000)begin ledcnt<=ledcnt+1'b1; end else begin led<=~led; ledcnt<=0; end end end SEG7 seg1( .oSEG(hex1), .Sel(dispdat[7:4])); SEG7 seg0( .oSEG(hex0), .Sel(dispdat[3:0])); endmodule
本文档为【FPGA verilog uart串口收发代码】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_589748
暂无简介~
格式:doc
大小:33KB
软件:Word
页数:0
分类:互联网
上传时间:2019-09-19
浏览量:45