当前位置:文档之家› rs串口verilog代码

rs串口verilog代码

UART是通用异步收发器的简称,其中有一种电平规范较RS232规范,它用-3~-15V表示正逻辑,3~15V表示负逻辑,通过FPGA芯片实现RS232通信首先要解决的就是FPGA电平和RS232电平之间的矛盾,通常采用MAX3232作为物理层的电平接口,根据MAX3232提供的标准配制方式把物理电路设计好后,接下来的通信就是要实现逻辑的接收和发送……设计最简单的RS232通信逻辑,FPGA实现将接收到的数据会发出去,总共两个数据传输引脚,一收一发。

将此通信模块分为三个部分:接收模块,波特率控制模块,发送模块。

工作原理:此模块接收MAX3232传过来的串行数据,对齐进行判断采样,校验,最后将数据流中的串行数据转换为八位并行数据,将此八位数据储存,或送给发送模块发送出去。

根据RS232通信标准器串行数据分为起始位、数据位、校验位、停止位,空闲时为高电平,起始位通常为低电平,数据位通常为8位,校验位分为奇校验、偶校验等,停止位一位或两位且为高电平。

FPGA接收模块对此数据进行异步接收,首先就要检测其数据传输开始标识,当然就是检测开始位,于是要有下降沿检测电路,检测到下降沿是输出一高脉冲,此电路可以用两个D触发器加上基本门电路实现,脉冲触发开始进入接收状态,输出接收状态标志位,使其为1,此标志位使能波特率控制模块输出采样脉冲,此计数脉冲触发接收模块中的计数器计数,加到相应的位就把当前的串行总线上的值赋给缓冲器,或对其判断,当计数完成11次计数后,已将8位串行数据转成并行数据到缓冲器中,且进行了校验的判断和停止位的判别,这是接收状态结束,接收状态位置0,计数器清零。

对于波特率产生模块用于控制采样数据脉冲的周期,其周期就为串行数据传送一个bit所用的时间,根据此时间和时钟周期设置计数值。

当接收模块完成工作时,接收状态位为0时可以触发发送模块,发送模块检测接收状态的下降沿,由此产生一高脉冲,与发送模块类似,根据波特率控制模块产生的计数脉冲将并行数据转成串行数据,并加上开始位、校验位、停止位。

由此完成整个串行通信模块。

要熟悉:下降沿检测程序设计,并转串设计等。

顶层模块图如下所示:各模块的程序如下://本程序实现rs232通信中的串行数据接收模块module rs232_rx(//inputclk,//50M的时钟输入rst_n,//低电平复位信号输入rx_cnt_pluse,//采样脉冲输入,总共11个采样脉冲,一个时钟宽度的高电平rs232_in_s,//串行数据输入,空闲时为高电平,1bit低电平作为起始位,接着8bit数据位LSB传输模式,接着偶数校验位,接着1bit低电平作为停止位//outputrs232_out_p,//输出8位并行数据rx_flag,//数据接收状态输出,接收状态下为高电平,其余为低电平rx_error_flag//接收校验错误标识位,若检测奇数校验位或者停止位不正确时输出高电平 );parameter WIGTH=8;input clk,rst_n;input rx_cnt_pluse;input rs232_in_s;output [WIGTH-1:0] rs232_out_p;output rx_flag;output rx_error_flag;reg [3:0] cnt=0;reg rx_flag=0;reg [WIGTH-1:0] rs232_out_p;reg rs232_in_s_r1,rs232_in_s_r2,rs232_in_s_r3,rs232_in_s_r4;wire rs232_in_s_start_flag;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginrs232_in_s_r1<=0;rs232_in_s_r2<=0;endelse//串行数据开始传输检测电路,检测其下降沿,有下降沿是输出一个clk宽度的高脉冲beginrs232_in_s_r1<=rs232_in_s;rs232_in_s_r2<=rs232_in_s_r1;rs232_in_s_r3<=rs232_in_s_r2;rs232_in_s_r4<=rs232_in_s_r3;endendassignrs232_in_s_start_flag=rs232_in_s_r4&(~rs232_in_s_r1)&(~rs232_in_s_r2)&(~rs232_in_ s_r3);always@(posedge clk or negedge rst_n)begin//接收状态控制电路,第一个下降沿时标识位置高,当cnt计数到11时置低if(!rst_n)rx_flag<=0; //数据接收状态输出,接收状态下为高电平,其余为低电平else if(rs232_in_s_start_flag)rx_flag<=1;else if(cnt==11)rx_flag<=0;endreg rx_error_flag_r1,rx_error_flag_r2;rx_error_flag//接收校验错误标识位,若检测奇数校验位或者停止位不正确时输出高电平reg [WIGTH-1:0] rs232_out_p_temp=0;always@(posedge clk or negedge rst_n)begin//串转并逻辑if(!rst_n)begincnt<=0;rs232_out_p_temp<=0;rx_error_flag_r1<=0;rx_error_flag_r2<=0;endelse if(rx_flag)//接收有效状态下,开始接收数据beginif(rx_cnt_pluse)//采样脉冲出发cnt累加// rx_cnt_pluse,//采样脉冲输入,总共11个采样脉冲,一个时钟宽度的高电平begincnt<=cnt+1;case(cnt)//将当前串行数据输入线上的数据锁存到寄存器的相应的位1: rs232_out_p_temp[0]<=rs232_in_s;2: rs232_out_p_temp[1]<=rs232_in_s;3: rs232_out_p_temp[2]<=rs232_in_s;4: rs232_out_p_temp[3]<=rs232_in_s;5: rs232_out_p_temp[4]<=rs232_in_s;6: rs232_out_p_temp[5]<=rs232_in_s;7: rs232_out_p_temp[6]<=rs232_in_s;8: rs232_out_p_temp[7]<=rs232_in_s;9:beginif(rs232_in_s!=^rs232_out_p_temp)//偶数校验位,有奇数个1为1,偶数个1为0 rx_error_flag_r1<=1;else//若校验出错,则给出标识1rx_error_flag_r1<=0;end10:beginif(!rs232_in_s)//1bit1作为停止位。

//串行数据输入,空闲时为高电平,1bit低电平作为起始位,接着8bit数据位rx_error_flag_r2<=1;else//若停止位出错,则给出标识2rx_error_flag_r2<=0;enddefault: ;endcaseendelse if(cnt==11)begincnt<=0;//当计数到11时cnt清零,把缓存中的数据输出rs232_out_p<=rs232_out_p_temp;endendend//两标识相或得到错误标识输出assign rx_error_flag=rx_error_flag_r2 | rx_error_flag_r1;endmodule//////////////////////////////////////////////////////////////////////////此程序完成对8位数据通过RS232口发送出去module rs232_tx(//inputclk,//50M的时钟输入rst_n,//异步置位信号输入rs232_in_p,//8位并行数据输入tx_cnt_flag,//并转串同步脉冲输入rx_flag,//发送开始信号,检测其低电平开始发送//outputrs232_out_s,//串行数据输出tx_flag//发送状态标志,高电平表示正在处于发送状态 );parameter WIGTH=8;input clk,rst_n;input [WIGTH-1:0] rs232_in_p;input tx_cnt_flag; //并转串同步脉冲输入input rx_flag; ,//发送开始信号,检测其低电平开始发送output rs232_out_s;output tx_flag; //发送状态标志,高电平表示正在处于发送状态reg rs232_out_s;reg tx_flag;reg rx_flag_r1,rx_flag_r2;wire rx_flag_negedge;always@(posedge clk or negedge rst_n)begin//检测发送开始信号,检测rx_flag信号的下降沿if(!rst_n)beginrx_flag_r1<=0;rx_flag_r2<=0;endelsebeginrx_flag_r1<=rx_flag;rx_flag_r2<=rx_flag_r1;endendassign rx_flag_negedge=(~rx_flag_r1)&rx_flag_r2;reg [3:0] cnt=0;always@(posedge clk or negedge rst_n)beginif(!rst_n)begintx_flag<=0; //发送状态标志,高电平表示正在处于发送状态endelse if(rx_flag_negedge)tx_flag<=1;else if(cnt==12)tx_flag<=0;endalways@(posedge clk or negedge rst_n) beginif(!rst_n)rs232_out_s<=1; //串行数据输出else if(tx_flag)beginif(tx_cnt_flag//并转串同步脉冲输入)begin//并转串逻辑,停止位是0cnt<=cnt+1;case(cnt)0:rs232_out_s<=0;1:rs232_out_s<=rs232_in_p[0];2:rs232_out_s<=rs232_in_p[1];3:rs232_out_s<=rs232_in_p[2];4:rs232_out_s<=rs232_in_p[3];5:rs232_out_s<=rs232_in_p[4];6:rs232_out_s<=rs232_in_p[5];7:rs232_out_s<=rs232_in_p[6];8:rs232_out_s<=rs232_in_p[7];9:rs232_out_s<=^rs232_in_p;10:rs232_out_s<=1;default:rs232_out_s<=1;endcaseendelse if(cnt==12)begincnt<=0;rs232_out_s<=1;endendendendmodule////////////////////////////////////////////////本程序实现对rs232波特率的控制module baudrate_ctr(//inputclk,//50M的时钟输入rx_tx_en,//发送或接收数据有效标识引脚,其为高电平是表示处于发送或接收状态rst_n,baudrate_word,//波特率设置数输入//outputrx_tx_cnt_pluse//此信号给接收模块作为采样基准信号,给发送模块作为发送同步基准信号);input clk,rst_n;input rx_tx_en;input [13:0] baudrate_word;output rx_tx_cnt_pluse;reg rx_tx_cnt_pluse;reg [13:0] cnt=0;reg [13:0] baudrate_word_reg=0;always@(posedge clk or negedge rst_n)begin//波特率设置数锁存逻辑if(!rst_n)baudrate_word_reg<=0;elsebaudrate_word_reg<=baudrate_word;endalways@(posedge clk or negedge rst_n)begin//完成一个bit传输时间的计数if(!rst_n)begincnt<=0;endelseif((cnt==baudrate_word_reg) || !rx_tx_en)cnt<=0;elsecnt<=cnt+1;endalways@(posedge clk or negedge rst_n)begin//当计数到1bit中间是输出一个clk周期宽度的高脉冲作为输出 if(!rst_n)rx_tx_cnt_pluse<=0;elseif(cnt==(baudrate_word_reg>>1))rx_tx_cnt_pluse<=1;elserx_tx_cnt_pluse<=0;endendmodule。

相关主题