FPGA串口verilogWord下载.docx

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

FPGA串口verilogWord下载.docx

《FPGA串口verilogWord下载.docx》由会员分享,可在线阅读,更多相关《FPGA串口verilogWord下载.docx(32页珍藏版)》请在冰豆网上搜索。

FPGA串口verilogWord下载.docx

reg[7:

0] 

TxD_dataReg;

//寄存器发送模式,因为在串口发送过程中输入端不可能一直保持有效电平

reg[3:

state;

parameter 

ClkFrequency=25000000;

//时钟频率-25MHz

Baud=115200;

//串口波特率-115200 

//波特率产生

parameterBaudGeneratorAccWidth=16;

[BaudGeneratorAccWidth:

0]BaudGeneratorAcc;

wire[BaudGeneratorAccWidth:

0]BaudGeneratorInc=((Baud<

<

(BaudGeneratorAccWidth-4))+(ClkFrequency>

>

5))/(ClkFrequency>

4);

wireBaudTick=BaudGeneratorAcc[BaudGeneratorAccWidth];

wireTxD_busy;

always@(posedgeclkornegedgerst)

if(~rst)

BaudGeneratorAcc<

=0;

elseif(TxD_busy)

=BaudGeneratorAcc[BaudGeneratorAccWidth-1:

0]+BaudGeneratorInc;

//发送端状态

wire 

TxD_ready=(state==0);

//当state=0时,处于准备空闲状态,TxD_ready=1

assignTxD_busy=~TxD_ready;

//空闲状态时TxD_busy=0

//把待发送数据放入缓存寄存器TxD_dataReg

TxD_dataReg<

=8'

b00000000;

elseif(TxD_ready&

TxD_start)

TxD_dataReg<

=TxD_data;

//发送状态机

if(~rst)

begin

state<

=4'

b0000;

//复位时,状态为0000,发送端一直发1电平

TxD<

=1'

b1;

end

else 

case(state)

4'

b0000:

if(TxD_start)begin

b0100;

//接受到发送信号,进入发送状态

 

b0100:

if(BaudTick)begin

b1000;

//发送开始位-0电平

b0;

b1000:

b1001;

//bit0

=TxD_dataReg[0];

b1001:

b1010;

//bit1

=TxD_dataReg[1];

b1010:

b1011;

//bit2

=TxD_dataReg[2];

b1011:

b1100;

//bit3

=TxD_dataReg[3];

b1100:

b1101;

//bit4

=TxD_dataReg[4];

b1101:

b1110;

//bit5

=TxD_dataReg[5];

b1110:

b1111;

//bit6

=TxD_dataReg[6];

b1111:

b0010;

//bit7

=TxD_dataReg[7];

b0010:

b0011;

//stop1

b0011:

//stop2

default:

endcase

endmodule

接收端:

modulercv(clk,

RxD,

RxD_data,

RxD_data_ready,

RxD;

output[7:

0]RxD_data;

//接收数据寄存器 

output 

RxD_data_ready;

//接收完8位数据,RxD_data值有效时,RxD_data_ready输出读信号

//时钟频率-25MHz

//波特率-115200

reg[2:

bit_spacing;

reg 

RxD_delay;

RxD_start;

reg[3:

reg[7:

RxD_data;

//波特率产生,使用8倍过采样

parameterBaud8=Baud*8;

parameterBaud8GeneratorAccWidth=16;

wire 

[Baud8GeneratorAccWidth:

0]Baud8GeneratorInc=((Baud8<

(Baud8GeneratorAccWidth-7))+(ClkFrequency>

8))/(ClkFrequency>

7);

0]Baud8GeneratorAcc;

Baud8GeneratorAcc<

else 

=Baud8GeneratorAcc[Baud8GeneratorAccWidth-1:

0]+Baud8GeneratorInc;

//Baud8Tick为波特率的8倍-115200*8=921600

Baud8Tick=Baud8GeneratorAcc[Baud8GeneratorAccWidth];

//next_bit为波特率-115200

if(~rst||(state==0))

bit_spacing<

elseif(Baud8Tick)

bit_spacing<

=bit_spacing+1;

wirenext_bit=(bit_spacing==7);

//检测到RxD有下跳沿时,RxD_start置1,准备接收数据

always@(posedgeclk)

if(Baud8Tick)

begin

RxD_delay<

=RxD;

RxD_start<

=(Baud8Tick&

RxD_delay&

(~RxD));

end 

//状态机接收数据

always@(posedgeclkornegedgerst)

case(state)

4'

if(RxD_start)state<

//检测到下跳沿

if(next_bit) 

b0001;

b0001:

//停止位

default:

endcase

//保存接收数据到RxD_data中

RxD_data<

elseif(Baud8Tick&

&

next_bit&

state[3])

RxD_data<

={RxD,RxD_data[7:

1]};

//RxD_data_ready置位信号

RxD_data_ready<

else

state==4'

b0001);

为了测试收发是否正常,写的TestBench

`timescale1ns/1ns

modulers232_test;

TxD_data;

wire[7:

RxD_data;

//RxD,

TxD_busy,

transtrans(.clk(clk),

.rst(rst),

.TxD_start(TxD_start),

.TxD_busy(TxD_busy),

.TxD_data(TxD_data),

.TxD(TxD)

);

rcvrcv(.clk(clk),

.RxD(TxD), 

//收发相接时RxD=TxD

.RxD_data(RxD_data),

.RxD_data_ready(RxD_data_ready)

initial 

TxD_start=0;

TxD_data=0;

clk=0;

rst=1;

#54rst=0;

#70rst=1;

#40TxD_start=1'

#10TxD_data=8'

b11011001;

#100TxD_start=1'

alwaysbegin

#30clk=~clk;

#10clk=~clk;

二、综合

三、

FPGA与PC串口自收发通信

串口通信其实简单实用,这里我就不多说,只把自己动手写的verilog代码共享下。

实现的功能如题,就是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的高电平为接收或者发送数据位的中间采样点

0]rx_data;

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

wirerx_int;

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

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

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

.rst_n(rst_n),

.bps_start(bps_start),

.clk_bps(clk_bps)

);

my_uart_rxmy_uart_rx(.clk(clk),//接收数据模块

.rs232_rx(rs232_rx),

.clk_bps(clk_bps),

.rx_data(rx_data),

.rx_int(rx_int)

my_uart_txmy_uart_tx(.clk(clk),//发送数据模块

.rx_int(rx_int),

.rs232_tx(rs232_tx),

.bps_start(bps_start)

modulespeed_select(clk,rst_n,bps_start,clk_bps);

inputbps_start;

outputclk_bps;

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

parameterbps9600=5207,//波特率为9600bps

bps19200=2603,//波特率为19200bps

bps38400=1301,//波特率为38400bps

bps57600=867,//波特率为57600bps

bps115200=433;

//波特率为115200bps

parameterbps9600_2=2603,

bps19200_2=1301,

bps38400_2=650,

bps57600_2=433,

bps115200_2=216;

reg[12:

0]bps_para;

//分频计数最大值

0]bps_para_2;

//分频计数的一半

0]cnt;

//分频计数

regclk_bps_r;

//波特率时钟寄存器

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

0]uart_ctrl;

//uart波特率选择寄存器

always@(posedgeclkornegedgerst_n)begin

if(!

rst_n)begin

uart_ctrl<

=3'

d0;

//默认波特率为9600bps

end

elsebegin

case(uart_ctrl)//波特率设置

3'

d0:

bps_para<

=bps9600;

bps_para_2<

=bps9600_2;

end

d1:

=bps19200;

=bps19200_2;

d2:

=bps38400;

=bps38

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

当前位置:首页 > 幼儿教育 > 幼儿读物

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

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