FPGA串口调试文档格式.docx

上传人:b****6 文档编号:20215596 上传时间:2023-01-20 格式:DOCX 页数:12 大小:102.46KB
下载 相关 举报
FPGA串口调试文档格式.docx_第1页
第1页 / 共12页
FPGA串口调试文档格式.docx_第2页
第2页 / 共12页
FPGA串口调试文档格式.docx_第3页
第3页 / 共12页
FPGA串口调试文档格式.docx_第4页
第4页 / 共12页
FPGA串口调试文档格式.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

FPGA串口调试文档格式.docx

《FPGA串口调试文档格式.docx》由会员分享,可在线阅读,更多相关《FPGA串口调试文档格式.docx(12页珍藏版)》请在冰豆网上搜索。

FPGA串口调试文档格式.docx

其中,数据线上没有数据传输的时候是保持高电平,而第一个低电平的出现就是起始位。

当发送数据和接收数据的时候,按以上格式进行就可以了。

不知道大家会不会有这样一个问题,经常听说串口传输的速度是多少多少,看了这个数据帧格式,没发现速度是怎么控制的啊。

对的,这儿就引出了波特率的问题。

波特率时钟并没有表现在传输线上,它其实是用来指示我们每采样或发送一个数据位的速度的。

比如说,我们定义一个波特率时钟为96k,那么我们用这个时钟把数据串行一个一个打出去,接收端只要匹配一个相同的时钟,一个一个数据位接受进来,那数据传输就可以了!

2.代码这部分的代码相对于前面的就稍稍有点多了,我们来一点一点分析,由于这次用到了模块调用,这次上代码,我们把每个文件名都写上。

首先我们来看下这个工程的树状代码:

33.jpg(9.46KB)2011-5-1014:

02通过这个树状图,大家应该就对这个工程有一定了解了,主模块是uart,它包含四个子模块,分别是接收模块rx、接收模块的波特率时钟rx_clk、发送模块tx、发送模块的波特率时钟tx_clk。

1、主模块:

uart.v复制内容到剪贴板代码:

moduleuart(clk,rst_n,rxd,txd);

inputclk;

/输入时钟,50Minputrst_n;

inputrxd;

/串口输入rxoutputtxd;

/串口输出txwirebps_start1,bps_start2;

/rx、tx的波特率启动信号wirebps_clk1,bps_clk2;

/rx、tx的波特率时钟wirerx_done;

/数据接收完毕信号,有rx输出到tx,rx接收数据由tx发送回去wire7:

0data;

/数据寄存器bps_generaterx_clk(.clk(clk),/50M.rst_n(rst_n),.bps_start(bps_start1),/拉高,产生波特率时钟.bps_clk(bps_clk1);

rxrx(.clk(clk),.rst_n(rst_n),.rxd(rxd),.bps_clk(bps_clk1),.bps_start(bps_start1),.rx_done(rx_done),.data(data);

bps_generatetx_clk(.clk(clk),/50M.rst_n(rst_n),.bps_start(bps_start2),/拉高,产生波特率时钟.bps_clk(bps_clk2);

txtx(.clk(clk),.rst_n(rst_n),.bps_clk(bps_clk2),.bps_start(bps_start2),.data(data),.rx_done(rx_done),.txd(txd);

endmodule通常,我们在顶层模块里不会写具体操作的代码,主模块的作用是将各个模块连接在一起。

这样有利于代码的维护!

我们看到主模块对外的输入输出引脚只有时钟clk,复位rst_n,以及数据输入线rx和输出线tx。

往下看,我们看到一堆wire的定义,这个很重要。

由于input和output的端口Quartus软件会自动配置成wire型,所以这些端口不用再wire定义。

而其他剩下的端口,如果不“wire”一下,那么下面的各模块例化相互的端口就不会连接在一起。

接下来终于要说到模块例化了,所谓“例化”,是从英文的instantiate翻译过来的。

这里我说个不太严谨的说法:

就是把另一个模块添加在这个模块当中,更不严谨的,也可以说是调用吧。

代码:

bps_generaterx_clk(.clk(clk),/50M.rst_n(rst_n),.bps_start(bps_start1),/拉高,产生波特率时钟.bps_clk(bps_clk1);

我们引用波特率时钟模块来说明例化的格式吧。

首先,bps_generate是原来模块的模块名,后面加一个或几个空格,紧跟着rx_clk是在这个模块下(也就是uart)的模块名。

通常,我们会把两个命名一样,或者后面的命名为:

i1、i2,意思是模块1,2这个可以随意。

接下来在();

里添加这个模块的输入输出引脚,其中.clk()是原来模块的名称,而括号里则是在当前模块下的名称。

在当前模块里,两个名称一样,再“wire”一下,那这个信号就连接在一起了。

这儿,你可以直接给这个接口赋一个数,例如.data(16h11),这样,也是可以的。

2、波特率产生模块:

bps_generate.v代码:

modulebps_generate(clk,rst_n,bps_start,bps_clk);

/50Minputrst_n;

inputbps_start;

/高电平,产生波特率时钟outputbps_clk;

parameterCNT_NUM=434;

/波特率为50M/434=115200parameterCNT_NUM_2=216;

/计数值的一半,产生一个高电平reg15:

0cnt;

always(posedgeclkornegedgerst_n)beginif(!

rst_n)cnt=16b0;

elseif(cnt=CNT_NUM)cnt=16b0;

elseif(bps_start)cnt=cnt+1b1;

elsecnt=16b0;

endregbps_clk_r;

rst_n)bps_clk_r=1b0;

elseif(cnt=CNT_NUM_2)bps_clk_r=1b1;

elsebps_clk_r=1b0;

endassignbps_clk=bps_clk_r;

endmodule这里,我们首先用到了parameter,因为我们常通过修改计数值来改波特率时钟,所以,用parameter是很方便的!

接下来就是计数的操作,我想不用介绍太多。

最后产生的波特率时钟差不多是这样的,我们利用每个高电平来采集、发送数据。

44.jpg(3.81KB)2011-5-1014:

02这里,还要讲到一个模块重复调用的问题。

由于接收和发送的波特率时钟是一样的,我们在顶层模块uart调用的时候都是调用了这个代码文件,但分别命名为rx_clk和tx_clk,Quartus软件在综合的时候就会综合成两个电路。

不同于软件程序的调用,大家一定要引起重视!

3、接收模块:

rx.v代码:

modulerx(clk,rst_n,bps_clk,rxd,bps_start,rx_done,data);

inputrst_n;

inputbps_clk;

outputbps_start;

outputrx_done;

output7:

regreg_rxd0;

rst_n)reg_rxd0=1b1;

elsereg_rxd0=rxd;

endregreg_rxd1,reg_rxd2;

rst_n)beginreg_rxd1=1b1;

reg_rxd2=1b1;

endelsebeginreg_rxd1=reg_rxd0;

reg_rxd2=reg_rxd1;

endendwirereg_negedge=reg_rxd2&

(reg_rxd1);

/下降沿检测regbps_start_r;

regrx_done_r;

rst_n)beginbps_start_r=1b0;

rx_done_r=1b0;

endelseif(reg_negedge)bps_start_r=1b1;

/检测到起始位,打开波特率时钟elseif(state=4d9)rx_done_r=1b1;

/数据接收完成,启动一次数据传输elseif(state=4d10)beginbps_start_r=1b0;

/一帧数据传输完毕,关闭波特率时钟rx_done_r=1b0;

/标志位关闭,避免重复传输endendassignbps_start=bps_start_r;

assignrx_done=rx_done_r;

/数据传输标志位,拉高,表明rx接收一帧数据完成,tx发送一次该组数据reg3:

0state;

rst_n)state=4b0;

elseif(state=4d10)state=4b0;

/一帧数据传输完毕,回到初始状态elseif(bps_clk)/波特率每个高电平进行状态转移begincase(state)4d0:

state=4d1;

4d1:

state=4d2;

4d2:

state=4d3;

4d3:

state=4d4;

4d4:

state=4d5;

4d5:

state=4d6;

4d6:

state=4d7;

4d7:

state=4d8;

4d8:

state=4d9;

4d9:

state=4d10;

4d10:

state=4b0;

default:

endcaseendendreg7:

0data_temp;

rst_n)begindata_temp=8b0;

endelseif(bps_clk)begincase(state)4d1:

data_temp0=rxd;

data_temp1=rxd;

data_temp2=rxd;

data_temp3=rxd;

data_temp4=rxd;

data_temp5=rxd;

data_temp6=rxd;

data_temp7=rxd;

/逐位存入数据endcaseendendassigndata=data_temp;

endmodule在这个代码文件中,蓝色部分是用来下降沿检测的,前面已经介绍过。

红色部分,是一个简单的状态机。

FPGA内部相当于硬件电路,都是并行执行,但是,有些逻辑却是有一定顺序的,这时候,我们就需要使用状态机来完成顺序执行。

大家发现,红色部分第一个always模块的case结构,状态state是随着波特率的高电平elseif(bps_clk)一个一个转移的。

而在第二个always模块里,利用每一个状态执行一次数据读入的操作!

4、数据发送模块:

tx.v代码:

moduletx(inputclk,inputrst_n,inputbps_clk,inputrx_done,input7:

0data,outputbps_start,outputtxd);

regbps_start_r;

rst_n)bps_start_r=1b0;

elseif(rx_done)bps_start_r=1b1;

elseif(state=4d11)bps_start_r=1b0;

endassignbps_start=bps_start_r;

reg7:

0tx_data;

rst_n)tx_data=8b0;

elseif(rx_done)tx_data=data;

endreg3:

elseif(bps_clk)begincase(state)4d0:

state=4d11;

/4d10:

4d11:

endcaseendendregtxd_r;

rst_n)txd_r=1b1;

elseif(bps_clk)begincase(state)4d1:

txd_r=1b0;

txd_r=tx_data0;

txd_r=tx_data1;

txd_r=tx_data2;

txd_r=tx_data3;

txd_r=tx_data4;

txd_r=tx_data5;

txd_r=tx_data6;

txd_r=tx_data7;

txd_r=1b1;

/crc4d11:

/stopendcaseendendassigntxd=txd_r;

endmodule发送模块和接收模块是非常相似的,这里就不重复介绍了。

3.调试前准备对于我们这个串口调试:

1、我们需要准备一个USB数据线,是标准的一边小头,一边大头的那种,我想,很多MP3,手机都是采用这种数据线的,很好找。

2、安装串口转USB的驱动程序。

3、安装一个串口调试助手。

这些,我们都将在帖子里附件打包。

4.上电调试分配好管脚,下载代码,打开串口大师如下图:

当上面的窗口能显示出下面窗口我们发送的内容,就算是调试成功了O(_)O!

55.jpg(38.68KB)2011-5-1014:

025.总结这次实验,我们学习了简单的串口RS232的通信时序和逻辑设计。

也是我们第一次用到了模块调用,第一次设计了一个相对长一些的代码。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 初中教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1