1、Verilog之UART源程序/2011-12-08 zheng/* 程序说明 *功能:UART串口通讯实信实验描述:本程序共四个模块 模块1:接收数据的波特率发生模块,接收模块在接收到下降沿时,通过标志位启 动该模块的波特率计数器,并在计数中返回一个采样标志位给接受模块, 通知接收模块采样; - 模块2:数据接收模块,该模块一旦监测到数据输入端有下降沿,就立即启动波 特率(标志位置1),并使能接收标志位rx_int,接收开始; - 模块3:发送数据的波特率发生模块,发送模块在监测到接收标志位rx_int产生下 降沿时,通过标志位启动该模块的的波特率计数器,并在计数中返回一 个发送标志位给发送
2、模块,通知发送模块发送数据; - 模块4:数据发送模块,该模块一旦监测到接收标志位rx_int有下降沿,就立即启 动波特率(标志位置1),并使能接收标志位tx_en,发送开始; -引脚: clk: 50Mhz时钟输入,Pin23; rst_n: 复位,低电平有效,Pin144; receive: 数据接收端,Pin160,需要跳线帽 send: 数据发送端,Pin163,需要跳线帽*/module lesson5(clk,rst_n,receive,send);input clk;input rst_n;input receive;output send;wire7:0data;/连接接收模块
3、与发送模块,以便数据传输wire baud_start1,baud_start2; /baud_start1:接收模块的波特率启动标志位; /baud_start2:发送模块的波特率启动标志位;wire mid_flag1,mid_flag2; /mid_flag1:接收数据标志位,由接收波特率发生模块发来; /mid_flag2:发送数据标志位,由发送波特率发生模块发来;wire interrupt; /接收完数据的标志位,同时也是发送数据的启示标志位; /*本程序采用模块化设计,即模块例化,分为4个模块,其中两个波特率发生模块共用; 注意:例化的格式很重要!*/baud_select ba
4、ud_receive( .clk(clk), .rst_n(rst_n), .baud_start(baud_start1), .mid_flag(mid_flag1) ); /模块1:接收数据的波特率发生模块;/- receive_uart recsive_232( .clk(clk), .rst_n(rst_n), .rs232_rx(receive), .baud_start(baud_start1), .mid_flag(mid_flag1), .rx_int(interrupt), .rx_data(data) ); /模块2:数据接收模块;/-baud_select baud_se
5、nd( .clk(clk), .rst_n(rst_n), .baud_start(baud_start2), .mid_flag(mid_flag2) ); /模块3:发送数据的波特率发生模块;/- send_uart send_232( .clk(clk), .rst_n(rst_n), .rs232_tx(send), .baud_start(baud_start2), .mid_flag(mid_flag2), .tx_int(interrupt), .tx_data(data) ); /模块4:数据发送模块;/- endmodule/* over */ /2011-12-08 zhe
6、ng/* 程序说明 *功能:波特率发生模块描述: 在收到来自接收模块或者发送模块的启动信号baud_start后,启动波特率计数器, 产生9600的比特率端口: clk: 50Mhz时钟输入,Pin23; rst_n: 复位,低电平有效,Pin144; mid_flag: 接收/发送数据标志位,接收或者发送数据位的中间采样点; baud_start: 波特率启动标志位;波特率计算:eg:9600bps=9600bit/s 9600bit/s=9600bit/1000 000us, 那么传输每bit要1000 000/9600us,而一个时钟周期位0.02us, 由此可计算出 1000 000/
7、9600us有多少个0.02us,即多少个时钟, 计算得:传输每bit要5208个时钟周期,计数从0到5207;*/module baud_select(clk,rst_n,baud_start,mid_flag);input clk;input rst_n;input baud_start;output mid_flag;/parameter bps9600 = 5207, /波特率为9600bps/ bps19200 = 2603, /波特率为19200bps/ bps38400 = 1301, /波特率为38400bps/ bps57600 = 867, /波特率为57600bps/ b
8、ps115200 = 433; /波特率为115200bps/parameter bps9600_2 = 2603,/ bps19200_2 = 1301,/ bps38400_2 = 650,/ bps57600_2 = 433,/ bps115200_2 = 216; define BPS_PARA 5207define BPS_PARA_2 2603/*/波特率分频计数器,当启动信号标志位为1时计数开始reg12:0cont;always (posedge clk or negedge rst_n) if(!rst_n)cont= 13d0; else if(cont=BPS_PARA)
9、|!baud_start)cont= 13b0_0000_0000_0000; else cont=cont+1b1; /*/发送一个位需要5028个时钟周期,在一个数据位中间时刻,即计数到2603时,接收或发送/标志位置1,并传输给接收模块或者发送模块,以发送或接收数据;reg mid_flag_1; always (posedge clk or negedge rst_n) if(!rst_n)mid_flag_1=1b0; else if(cont=BPS_PARA_2)mid_flag_1=1b1; else mid_flag_1=1b0;assign mid_flag=mid_fla
10、g_1;/*endmodule /* over */2011-12-08 zheng/* 程序说明 *功能:接收数据模块描述: 在接收波特率的驱动下,该模块将从数据输入端接收的数据存放在寄存器 rx_data7:0里,并输出给发送模块端口: clk: 50Mhz时钟输入,Pin23; rst_n: 复位,低电平有效,Pin144; rs232_rx: 与顶层模块的输入引脚receive对应; mid_flag: 由接收波特率发生模块发来,1-标志采样,0-不采样; 与顶层mid_flag1对应; baud_start: 接收波特率启动标志位,与顶层mbaud_start1对应; rx_data
11、7:0:将接收的数据输出,与顶层的data7:0对应; rx_int: 接收数据标志位:在接收数据时一直保持1,接收完或者 接收数据时保持0,对应顶层interrupt;UART时序: _* * 0 * * 1 0:启示位0,*:8位数据,1:结束位1*/module receive_uart(clk,rst_n,rs232_rx,mid_flag,baud_start,rx_data,rx_int);input clk;input rst_n;input rs232_rx;input mid_flag;output baud_start;output7:0rx_data;output rx_
12、int;/*/利用按键消抖原理,先后采样接收端的的电平进行对比,以判断是否有下降沿;reg rs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3;always (posedge clk or negedge rst_n) begin if(!rst_n) begin rs232_rx0 = 1b0; rs232_rx1 = 1b0; rs232_rx2 = 1b0; rs232_rx3 = 1b0; end else begin rs232_rx0 = rs232_rx; rs232_rx1 = rs232_rx0; rs232_rx2 = rs232_rx1; rs
13、232_rx3 = rs232_rx2; endendwire neg_rs232_rx= rs232_rx3 & rs232_rx2 & rs232_rx1 & rs232_rx0;/*/如果有下降沿来临,即neg_rs232_rx为1时,波特率发生标志位置1,接收数据标志置1;/一旦数据接收结束,即num为12时,关断波特率发生器,接收数据标志清零;reg baud_start_r,rx_int_r;reg3:0num;always (posedge clk or negedge rst_n) begin if(!rst_n) begin baud_start_r=1b0; rx_int_
14、r=1b0; end else if(neg_rs232_rx) begin baud_start_r=1b1; rx_int_r=1b1; end else if(num=4d12) begin baud_start_r=1b0; rx_int_r=1b0; end; endassign baud_start = baud_start_r;assign rx_int = rx_int_r;/*/num:接收位数标志;/buffer:接收数据缓冲器;/data:数据寄存器;/波特率发生模块发来采样标志信号(mid_flag为1)后就进行采样;reg7:0data;reg 7:0buffer;a
15、lways (posedge clk or negedge rst_n) begin if(!rst_n) begin data=8d0; buffer=8d0; num=4d0; end else if(rx_int_r) begin if(mid_flag) begin num=num+1b1; /注意:此句与下面case语句是并行的,即case中的num是自加1之前的值; case(num) /num=0时为起始位,不存储 4d1:buffer0=rs232_rx; 4d2:buffer1=rs232_rx; 4d3:buffer2=rs232_rx; 4d4:buffer3=rs232
16、_rx; 4d5:buffer4=rs232_rx; 4d6:buffer5=rs232_rx; 4d7:buffer6=rs232_rx; 4d8:buffer7=rs232_rx; /num=9时为结束位,不存储 default:; endcase end else if(num=4d12) begin num=4d0; data=buffer; end end endassign rx_data=data;/* endmodule/* over */ /2011-12-08 zheng/* 程序说明 *功能:发送数据模块描述: 在发送波特率的驱动下,该模块将从接收模块传输来的数据发送出去
17、端口: clk: 50Mhz时钟输入,Pin23; rst_n: 复位,低电平有效,Pin144; rs232_tx: 与顶层模块的输入引脚send对应; mid_flag: 由发送波特率发生模块发来,1-发送,0-不发送; 与顶层mid_flag2对应; baud_start: 发送波特率启动标志位,与顶层baud_start2对应; tx_data7:0:准备发送的数据,与顶层的data7:0对应; tx_int: 接收数据标志位:在接收数据时一直保持1,接收完或者 接收数据时保持0,对应顶层interrupt;UART时序: _* * 0 * * 1 0:启示位0,*:8位数据,1:结束
18、位1*/module send_uart(clk,rst_n,rs232_tx,mid_flag,tx_data,tx_int,baud_start);input clk;input rst_n;input mid_flag;output baud_start;output rs232_tx;input7:0tx_data;input tx_int;/*/利用按键消抖原理,先后采样接收数据标志位tx_int的电平,以判断是否有下降沿产生reg int0,int1,int2;always (posedge clk or negedge rst_n) begin if(!rst_n) begin
19、int0=1b0; int1=1b0; int2=1b0; end else begin int0=tx_int; int1=int0; int2=int1; end endwire int_lock=int1&int2;/*/如果tx_int有下降沿产生,即int_lock为1,就启动波特率发生器,同时使能发送数据,/并将接收模块发来的数据送入发送数据缓冲器;/如果发送数据结束,即num=11时,波特率关断,发送使能清零,发送数据缓冲器清零;reg baud_start_t,send_en;reg 7:0data; reg3:0num;always (posedge clk or neged
20、ge rst_n) begin if(!rst_n) begin baud_start_t=1b0; send_en=1b0; data=8d0; end else if(int_lock) begin baud_start_t=1b1; send_en=1b1; data=tx_data; end else if(num=4d11) begin baud_start_t=1b0; send_en=1b0; data=8d0; end endassign baud_start=baud_start_t;/*/rs232_tx_r:数据输出寄存器;/num:发送数据位数;reg rs232_tx_r;always (posedge clk or negedge rst_n) begin if(!rst_n) begin num=1b0; rs232_tx_r=1b0; end else if(send_en) begin if(mid_flag) begin num=num+1b1; case(num) 4d0:rs232_tx_r=1b0; /起始信号0; 4d1:rs232_tx_r=data0; 4d2:rs232_tx_r=data1; 4d3:rs232_tx_r
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2