根据小梅哥教程和网上资料编写。
1.串口通信原理:
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART)是一种异步收发传输器,其在数据发送时将并行数据转换成串行数据来传输,在数据接收时将接收到的串行数据转换成并行数据,可以实现全双工传输和接收。它包括了 RS232、RS449、RS423、RS422和RS485等接口标准规范和总线标准规范。
数据帧格式:起始位(1‘b0)+ 数据位(8bit) + 1位校验位 + 停止位(1’b1)
大多资料记在笔记本里,这里记一下实现代码。
设计功能:波特率为9600,8位数据位,无校验位,无流控功能,每1s发送一次当前8位拨码开关的值,每次发送完成后将LED的状态翻转。
2.uart_tx:
module UART_tx(
input clk ,
input reset_n ,
input [7:0]data , //数据
input Send_Go , //发送使能
output reg uart_tx , //输出寄存器,并行数据->串行数据发送出去
output reg Tx_Done ); //发送完成信号
//默认使用波特率BAUD 9600 时钟频率 CLK_FREQ 50MHz
parameter start_bit = 0 ;
parameter stop_bit = 1 ;
parameter BAUD = 9600;
parameter CLK_FREQ = 50_000_000;
parameter bps_c = CLK_FREQ / BAUD ;
reg Send_en;
always@(posedge clk or negedge reset_n )
if(! reset_n)
Send_en <= 0 ;
else if(Send_Go )
Send_en <= 1 ;
else if((tx_flag==9)&&(counter_bps == bps_c - 1))
//else if (Tx_Done) tx_flag <= 0 ;
Send_en <= 0 ;
// bps
reg [30:0] counter_bps ;
always@(posedge clk or negedge reset_n)
if(! reset_n)
counter_bps <= 0 ;
else if (Send_en)
if(counter_bps == bps_c - 1)
counter_bps <= 0 ;
else
counter_bps <= counter_bps + 1'b1 ;
else
counter_bps <= 0 ;
// 发送状态
reg [3:0] tx_flag;
always@(posedge clk or negedge reset_n)
if(! reset_n)
tx_flag <= 0 ;
else if (!Send_en) tx_flag <= 0 ;
else if ((tx_flag==9)&&(counter_bps == bps_c - 1))
//else if (Tx_Done) tx_flag <= 0 ;
tx_flag <= 0 ;
else
if(counter_bps == bps_c - 1)
tx_flag <= tx_flag + 1'b1 ;
// Send_Go改变发送信号
reg [7:0]r_data;
always@(posedge clk)
if(Send_Go )
r_data <= data;
else
r_data <= r_data;
// tx_flag
always@(*)
if(!Send_en) uart_tx <= 1'b1;
else
begin
case(tx_flag)
4'b0000 : uart_tx <= start_bit;
4'b0001 : uart_tx <= r_data[0];
4'b0010 : uart_tx <= r_data[1];
4'b0011 : uart_tx <= r_data[2];
4'b0100 : uart_tx <= r_data[3];
4'b0101 : uart_tx <= r_data[4];
4'b0110 : uart_tx <= r_data[5];
4'b0111 : uart_tx <= r_data[6];
4'b1000 : uart_tx <= r_data[7];
4'b1001 : uart_tx <= stop_bit;
default : uart_tx <= uart_tx;
endcase
end
always@(posedge clk or negedge reset_n)
Tx_Done <= (tx_flag==9)&&(counter_bps == bps_c - 1);
endmodule
3.uart_tx_tb:测试:
`timescale 1ns / 1ns
module UART_tx_tb();
reg clk ,reset_n , Send_Go ;
reg [7:0]data;
wire uart_tx , Tx_Done;
UART_tx uart_tx_inst(
.clk(clk) ,
.reset_n(reset_n) ,
.data(data) ,
.Send_Go(Send_Go),
.uart_tx(uart_tx) ,
.Tx_Done(Tx_Done) );
initial begin clk = 0 ;
forever
#10 clk = ~clk ;
end
initial
begin
Send_Go = 0;
data = 8'b0110_0000;
reset_n = 0 ;
#20001;
reset_n = 1 ;
Send_Go = 1 ; #40;
Send_Go = 0 ; #400000;
data = 8'b0101_1111;
Send_Go = 0 ; #500000;
data = 8'b1101_0101;#500000;
Send_Go = 1 ;#40;
Send_Go = 0 ;#1200000 ;
$stop;
end
endmodule