补充一些串口里用到的数值的相关知识点
接收端串口时序图:
程序设计:
`timescale 1ns / 1ps
/串口接收端 串行转并行
module uart_rx(input sys_clk ,input rst_n ,input rx_data , //输入串行数据output reg[7:0] uart_data , // 输出并行数据output reg rx_done //数据传输完成结束信号 );parameter SYSCLK = 50_000_000 ;parameter Baud = 115200 ;parameter COUNT = SYSCLK/Baud ;//434 传输1比特所需要的时钟周期parameter MID = COUNT/2 ;///产生开始信号(检测下降沿-----二级寄存)reg rx_reg1 ;reg rx_reg2 ;wire start_flag ; 开始信号reg rx_flag ;reg [3:0] cnt_bit ;///0~9reg [9:0] cnt ;///434reg [7:0] data_reg ;always@(posedge sys_clk)if(!rst_n)beginrx_reg1 <= 1 ; //处于空闲位 数据线上无数据rx_reg2 <= 1 ; //处于空闲位 数据线上无数据endelsebeginrx_reg1 <= rx_data ;rx_reg2 <= rx_reg1 ;endassign start_flag = ~rx_reg1 & rx_reg2 ; //rx_flagalways@(posedge sys_clk )if(!rst_n)rx_flag <= 0 ;else if (start_flag)rx_flag <= 1 ;else if ( cnt_bit == 9 && cnt == MID -1 )rx_flag <= 0 ;elserx_flag <= rx_flag ;cnt 434 always@(posedge sys_clk )if(!rst_n)cnt <= 0;else if ( rx_flag == 1 )beginif ( cnt == COUNT -1) ///一定要减一,如果不减一,实际会计到435次,反算回去波特率就不是115200了cnt <= 0;elsecnt <= cnt +1 ;endelsecnt <= 0 ;/计数器always@(posedge sys_clk )if(!rst_n)cnt_bit <= 0 ;else if ( rx_flag )beginif ( cnt == COUNT -1)beginif(cnt_bit == 9)cnt_bit <= 0 ;elsecnt_bit <= cnt_bit +1 ;endelsecnt_bit <= cnt_bit ;endelsecnt_bit <= 0 ;[7:0]uart_data/*cnt_bit = 0 起始位cnt_bit = 1-8 数据位cnt_bit = 9 停止位但是 [7:0]uart_data 没有uart[8]所以if ( cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9 )uart_data[cnt_bit -1] <= rx_data ;*/
// always@(posedge sys_clk )
// if(!rst_n)
// uart_data <= 0 ;
// else if ( rx_flag )begin
// if ( cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9 )
// uart_data[cnt_bit -1] <= rx_data ; //这里uart_data是不断随着cnt_bit变化的,只有在第九位的时候才有正确的最终值
// else
// uart_data <= uart_data ;
// end
// else
// uart_data <= 0 ;因为这里要让uart_data只在rx_done的时候有值,所以定义一个中间寄存器data_regalways@(posedge sys_clk )if(!rst_n)data_reg <= 0 ;else if ( rx_flag )beginif ( cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9 )data_reg[cnt_bit -1] <= rx_data ; //这里uart_data是不断随着cnt_bit变化的,只有在第九位的时候才有正确的最终值elsedata_reg <= data_reg ;endelsedata_reg <= 0 ;
// 其他赋值方法1
// always@(posedge sys_clk )
// if(!rst_n)
// uart_data <= 0;
// else if (cnt == MID -1)begin
// case(cnt_bit)
// 0: uart_data <= 0 ;
// 1: uart_data [0] <= rx_data ;
// 2: uart_data [1] <= rx_data ;
// 3: uart_data [2] <= rx_data ;
// 4: uart_data [3] <= rx_data ;
// 5: uart_data [4] <= rx_data ;
// 6: uart_data [5] <= rx_data ;
// 7: uart_data [6] <= rx_data ;
// 8: uart_data [7] <= rx_data ;
// 9: uart_data <= uart_data ; ///停止位的时候数据传完,保持
// endcase
// end
// else
// uart_data <= uart_data ;// 其他赋值方法2
// always@(posedge sys_clk )
// if(!rst_n)
// uart_data <= 0 ;
// else if (cnt == MID -1 && cnt_bit > 0 && cnt_bit < 9)
// uart_data <= {rx_data,uart_data[7:1]} ;
// else
// uart_data <= uart_data ;给uart_data赋值always@(posedge sys_clk )if(!rst_n) uart_data <= 0 ; else if (rx_flag)beginif (cnt_bit == 9 && cnt == MID/4 -1)uart_data <= data_reg ;elseuart_data <= uart_data ;endelseuart_data <= uart_data ; 可以保持到下一个数据到来uart_data <= 0 ; 只保持在rx_done处于高电平的时候/rx_donealways@(posedge sys_clk )if(!rst_n) rx_done <= 0 ;else if (rx_flag)beginif ( cnt_bit == 9 && cnt == MID/2 -1)rx_done <= 1 ;elserx_done <= 0 ; endelserx_done <= 0 ; endmodule
仿真程序
`timescale 1ns / 1ps
module test_bench( );reg sys_clk ;reg rst_n ;reg rx_data ; //输入串行数据wire[7:0] uart_data ; // 输出并行数据wire rx_done ;//数据传输完成结束信号 parameter SYSCLK = 50_000_000 ;parameter Baud = 115200 ;parameter COUNT = SYSCLK/Baud ;//434 传输1比特所需要的时钟周期parameter MID = COUNT/2 ;initialbeginsys_clk = 0 ;rst_n = 0 ;#10rst_n = 1 ;endalways #1 sys_clk = ~sys_clk ; //2nsinitialbeginuart_out (8'h34);uart_out (8'hef);uart_out (8'h98);uart_out (8'h70);uart_out (8'h14);end//任务函数task uart_out ;input [7:0] DATA ;beginrx_data = 1 ;///空闲位初始#20 rx_data = 0 ;///起始位///传输1bit的计时次数*1周期时间=总时间#(COUNT*2) rx_data = DATA[0] ;///数据位第一位#(COUNT*2) rx_data = DATA[1] ;///数据位第二位#(COUNT*2) rx_data = DATA[2] ;#(COUNT*2) rx_data = DATA[3] ;#(COUNT*2) rx_data = DATA[4] ;#(COUNT*2) rx_data = DATA[5] ;#(COUNT*2) rx_data = DATA[6] ;#(COUNT*2) rx_data = DATA[7] ;#(COUNT*2) rx_data = 1 ;#(COUNT*2) ;//停止位也需要时间endendtaskuart_rx uart_rx1(. sys_clk (sys_clk ) ,. rst_n (rst_n ) ,. rx_data (rx_data ) , //输入串行数据. uart_data (uart_data) , // 输出并行数据. rx_done (rx_done ) //数据传输完成结束信号 );
endmodule
仿真波形