基于FPGA与PC串口自收发通信Verilog.docx

上传人:b****6 文档编号:7125227 上传时间:2023-01-20 格式:DOCX 页数:13 大小:16.56KB
下载 相关 举报
基于FPGA与PC串口自收发通信Verilog.docx_第1页
第1页 / 共13页
基于FPGA与PC串口自收发通信Verilog.docx_第2页
第2页 / 共13页
基于FPGA与PC串口自收发通信Verilog.docx_第3页
第3页 / 共13页
基于FPGA与PC串口自收发通信Verilog.docx_第4页
第4页 / 共13页
基于FPGA与PC串口自收发通信Verilog.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

基于FPGA与PC串口自收发通信Verilog.docx

《基于FPGA与PC串口自收发通信Verilog.docx》由会员分享,可在线阅读,更多相关《基于FPGA与PC串口自收发通信Verilog.docx(13页珍藏版)》请在冰豆网上搜索。

基于FPGA与PC串口自收发通信Verilog.docx

基于FPGA与PC串口自收发通信Verilog

FPGA与PC串口自收发通信

实现的功能如题,就是FPGA里实现从PC接收数据,然后把接收到的数据发回去。

使用的是串口UART协议进行收发数据。

上位机用的是通用的串口调试助手。

发送数据的波特率可选9600bps,19200bps,38400bps,57600bps,115200bps等,

是可调的。

发送格式为:

1bit起始位,8bit数据,1bit停止位,无校验位。

以下的代码有比较详细的注释,经过下载验证,存在误码率(<5%),仅供学习!

代码如下:

(顶层模块):

modulemy_uart_top(clk,rst_n,rs232_rx,rs232_tx);

inputclk;

//50MHz主时钟

inputrst_n;

//低电平复位信号

inputrs232_rx;

//RS232接收数据信号

outputrs232_tx;

//

RS232发送数据信号

wirebps_start;

//接收到数据后,波特率时钟启动信号置位

wireclk_bps;

//clk_bps的高电平为接收或者发送数据位的中间采样点

wire[7:

0]rx_data;

//接收数据寄存器,保存直至下一个数据来到

wirerx_int;

//接收数据中断信号,接收到数据期间始终为高电平

//----------------------------------------------------

speed_select

speed_select(

.clk(clk),

//波特率选择模块,接收和发送模块复用,不支持全双工通信

.rst_n(rst_n),

.bps_start(bps_start),

.clk_bps(clk_bps)

);

my_uart_rx

my_uart_rx(

.clk(clk),

//接收数据模块

.rst_n(rst_n),

.rs232_rx(rs232_rx),

.clk_bps(clk_bps),

.bps_start(bps_start),

.rx_data(rx_data),

.rx_int(rx_int)

);

my_uart_tx

my_uart_tx(

.clk(clk),

//发送数据模块

.rst_n(rst_n),

.clk_bps(clk_bps),

.rx_data(rx_data),

.rx_int(rx_int),

.rs232_tx(rs232_tx),

.bps_start(bps_start)

);

endmodule

 

modulespeed_select(clk,rst_n,bps_start,clk_bps);

inputclk;

//50MHz主时钟

inputrst_n;

//低电平复位信号

inputbps_start;

//接收到数据后,波特率时钟启动信号置位

outputclk_bps;

//clk_bps的高电平为接收或者发送数据位的中间采样点

parameter

bps9600

=5207,

//波特率为9600bps

 

bps19200

=2603,

//波特率为19200bps

bps38400

=1301,

//波特率为38400bps

bps57600

=867,

//波特率为57600bps

bps115200

=433;

//波特率为115200bps

parameter

bps9600_2

=2603,

bps19200_2

=1301,

bps38400_2

=650,

bps57600_2

=433,

bps115200_2=216;

 

reg[12:

0]bps_para;

//分频计数最大值

reg[12:

0]bps_para_2;

//分频计数的一半

reg[12:

0]cnt;

//分频计数

regclk_bps_r;

//波特率时钟寄存器

//----------------------------------------------------------

reg[2:

0]uart_ctrl;

//uart波特率选择寄存器

//----------------------------------------------------------

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

uart_ctrl<=3'd0;

//默认波特率为9600bps

end

elsebegin

case(uart_ctrl)

//波特率设置

3'd0:

begin

bps_para<=bps9600;

bps_para_2<=bps9600_2;

end

3'd1:

begin

bps_para<=bps19200;

bps_para_2<=bps19200_2;

end

3'd2:

begin

bps_para<=bps38400;

bps_para_2<=bps38400_2;

end

3'd3:

begin

bps_para<=bps57600;

bps_para_2<=bps57600_2;

end

3'd4:

begin

bps_para<=bps115200;

bps_para_2<=bps115200_2;

end

default:

;

endcase

end

end

always@(posedgeclkornegedgerst_n)

if(!

rst_n)cnt<=13'd0;

elseif(cnt

//波特率时钟计数启动

elsecnt<=13'd0;

always@(posedgeclkornegedgerst_n)

if(!

rst_n)clk_bps_r<=1'b0;

elseif(cnt==bps_para_2&&bps_start)clk_bps_r<=1'b1;

//clk_bps_r高电平为接收或者发送数据位的中间采样点

elseclk_bps_r<=1'b0;

assignclk_bps=clk_bps_r;

endmodule

 

modulemy_uart_rx(clk,rst_n,rs232_rx,clk_bps,bps_start,rx_data,rx_int);

inputclk;

//50MHz主时钟

inputrst_n;

//低电平复位信号

inputrs232_rx;

//RS232接收数据信号

inputclk_bps;

//clk_bps的高电平为接收或者发送数据位的中间采样点

outputbps_start;

//接收到数据后,波特率时钟启动信号置位

output[7:

0]rx_data;

//接收数据寄存器,保存直至下一个数据来到

outputrx_int;

//接收数据中断信号,接收到数据期间始终为高电平

//----------------------------------------------------------------

regrs232_rx0,rs232_rx1,rs232_rx2;

//接收数据寄存器,滤波用

wireneg_rs232_rx;

//表示数据线接收到下降沿

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

rs232_rx0<=1'b1;

rs232_rx1<=1'b1;

rs232_rx2<=1'b1;

end

elsebegin

rs232_rx0<=rs232_rx;

rs232_rx1<=rs232_rx0;

rs232_rx2<=rs232_rx1;

end

end

assignneg_rs232_rx=rs232_rx2&~rs232_rx1;

//接收到下降沿后neg_rs232_rx置高一个时钟周期

//----------------------------------------------------------------

regbps_start_r;

reg[3:

0]

num;

//移位次数

regrx_int;

//接收数据中断信号,接收到数据期间始终为高电平

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

bps_start_r<=1'bz;

rx_int<=1'b0;

end

elseif(neg_rs232_rx)begin

bps_start_r<=1'b1;

//启动接收数据

rx_int<=1'b1;

//接收数据中断信号使能

end

elseif(num==4'd12)begin

bps_start_r<=1'bz;

//数据接收完毕

rx_int<=1'b0;

//接收数据中断信号关闭

end

end

assignbps_start=bps_start_r;

//----------------------------------------------------------------

reg[7:

0]rx_data_r;

//接收数据寄存器,保存直至下一个数据来到

//----------------------------------------------------------------

reg[7:

0]

rx_temp_data;

//但前接收数据寄存器

regrx_data_shift;

//数据移位标志

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

rx_data_shift<=1'b0;

rx_temp_data<=8'd0;

num<=4'd0;

rx_data_r<=8'd0;

end

elseif(rx_int)begin

//接收数据处理

if(clk_bps)begin

//读取并保存数据,接收数据为一个起始位,8bit数据,一个结束位

 

rx_data_shift<=1'b1;

num<=num+1'b1;

if(num<=4'd8)rx_temp_data[7]<=rs232_rx;

//锁存9bit(1bit起始位,8bit数据)

end

elseif(rx_data_shift)begin

//数据移位处理

 

rx_data_shift<=1'b0;

if(num<=4'd8)rx_temp_data<=rx_temp_data>>1'b1;

//移位8次,第1bit起始位移除,剩下8bit正好时接收数据

elseif(num==4'd12)begin

num<=4'd0;

//接收到STOP位后结束,num清零

rx_data_r<=rx_temp_data;

//把数据锁存到数据寄存器rx_data中

end

end

 

end

end

assignrx_data=rx_data_r;

 

endmodule

 

modulemy_uart_tx(clk,rst_n,clk_bps,rx_data,rx_int,rs232_tx,bps_start);

inputclk;

//50MHz主时钟

inputrst_n;

//低电平复位信号

inputclk_bps;

//clk_bps的高电平为接收或者发送数据位的中间采样点

input[7:

0]rx_data;

//接收数据寄存器

inputrx_int;

//接收数据中断信号,接收到数据期间始终为高电平,在次利用它的下降沿来启动发送数据

outputrs232_tx;

//RS232发送数据信号

outputbps_start;

//接收或者要发送数据,波特率时钟启动信号置位

//---------------------------------------------------------

regrx_int0,rx_int1,rx_int2;

//rx_int信号寄存器,捕捉下降沿滤波用

wireneg_rx_int;

//rx_int下降沿标志位

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

rx_int0<=1'b0;

rx_int1<=1'b0;

rx_int2<=1'b0;

end

elsebegin

rx_int0<=rx_int;

rx_int1<=rx_int0;

rx_int2<=rx_int1;

end

end

assignneg_rx_int=

~rx_int1&rx_int2;

//捕捉到下降沿后,neg_rx_int拉地保持一个主时钟周期

//---------------------------------------------------------

reg[7:

0]tx_data;

//待发送数据的寄存器

//---------------------------------------------------------

regbps_start_r;

regtx_en;

//发送数据使能信号,高有效

reg[3:

0]num;

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

bps_start_r<=1'bz;

tx_en<=1'b0;

tx_data<=8'd0;

end

elseif(neg_rx_int)begin

//接收数据完毕,准备把接收到的数据发回去

bps_start_r<=1'b1;

tx_data<=rx_data;

//把接收到的数据存入发送数据寄存器

tx_en<=1'b1;

//进入发送数据状态中

end

elseif(num==4'd11)begin

//数据发送完成,复位

bps_start_r<=1'bz;

tx_en<=1'b0;

end

end

assignbps_start=bps_start_r;

//---------------------------------------------------------

regrs232_tx_r;

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

num<=4'd0;

rs232_tx_r<=1'b1;

end

elseif(tx_en)begin

if(clk_bps)

begin

num<=num+1'b1;

case(num)

4'd0:

rs232_tx_r<=1'b0;

//发送起始位

4'd1:

rs232_tx_r<=tx_data[0];

//发送bit0

4'd2:

rs232_tx_r<=tx_data[1];

//发送bit1

4'd3:

rs232_tx_r<=tx_data[2];

//发送bit2

4'd4:

rs232_tx_r<=tx_data[3];

//发送bit3

4'd5:

rs232_tx_r<=tx_data[4];

//发送bit4

4'd6:

rs232_tx_r<=tx_data[5];

//发送bit5

4'd7:

rs232_tx_r<=tx_data[6];

//发送bit6

4'd8:

rs232_tx_r<=tx_data[7];

//发送bit7

4'd9:

rs232_tx_r<=1'b0;

//发送结束位

 

default:

rs232_tx_r<=1'b1;

endcase

end

elseif(num==4'd11)num<=4'd0;

//复位

end

end

assignrs232_tx=rs232_tx_r;

endmodule

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

当前位置:首页 > 解决方案 > 学习计划

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

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