基于FPGA与PC串口自收发通信Verilog.docx
- 文档编号:6076599
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:13
- 大小:16.39KB
基于FPGA与PC串口自收发通信Verilog.docx
《基于FPGA与PC串口自收发通信Verilog.docx》由会员分享,可在线阅读,更多相关《基于FPGA与PC串口自收发通信Verilog.docx(13页珍藏版)》请在冰豆网上搜索。
基于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
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 FPGA PC 串口 收发 通信 Verilog