Altera series- The UART of FPGA


  UART :  Universal Asynchronous Receiver/Transmitter : 异步收发传输器; 分为2个PART(发送  和接收);-------------学习笔记(一) Alex.Lee

**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

PART I   发送部分

      本实验是以波特率为9600,为例来讲述UART;

           首先,先介绍下串口的发送机制( 如图一 )

Altera series- The UART of FPGA_第1张图片


    即 UART 的发送(TX)机制,一般分为5个状态,即空闲位、 起始位、发送数据位、校验、停止位;

空闲(Idle):TX空闲时为High Level status;

起始(Start):TX 从高跳变到低电平,标志着下一个Bit将传送有效的数据;

数据(Data): TX将根据发送寄存器里的数据值,依次发送;(【注】:在传送的数据顺序为 First LSB ,Last MSB,先低位,后高位;)数据一般为7或8bit;

               校验( Check): TX 发送完数据位后,可使用校验位来使传送的数据更加准确,即使用 奇偶校验; 也可以不使用校验;

              停止(Stop): 发送停止位,即TX发送一 个BIt 的高电平,标志本次数据传送结束;一般用 帧错误检测 (Frame error:传送一帧数据是否出错);


 发送机制的过程可概括 为:  

Step 1 : 在空闲时TX为High Level ,当要发送数据时,则将pull down  TX 线 作为 发送起始位标志,即TX 发送一个Bit 位的低电平。

               Step 2 : 发送完起始位后,将进入发送数据, TX 将从接收缓冲器中依次从最低位 到最高位取出数据并在时钟周期到来时发送;一般数据位为8位即 1Byte。

       Step 3 : 发送完一帧数据后,为了确保数据的准确传输,一般会使一个bit位 用 于奇偶校验,来判断数据是否出错。

       Step 4 ::最后将发送一个bit的高电平作为发送停止位的标志,同时表明一帧数据传输完成。


    CODE :

`timescale 1ns / 1ps
module Uart_tx(clk,rst_n,wrig,datain,tx,idle);
input clk;
input rst_n;
input wrig;
input [7:0]datain;




output tx;
output idle;


reg tx, idle;
reg send;
reg result;
reg[7:0] timer;
reg tx_temp,tx_raising;


parameter poritymode = 1'b0;


always@(posedge clk)  // raise edge valid 
begin
tx_temp <= wrig;
tx_raising <= wrig & (~tx_temp);
end


always@(posedge clk)
begin
if(tx_raising &&(~idle))
begin
send <= 1'b1;
end
else if(timer == 8'd168)
begin
send <= 1'b0;
end
end


always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
tx <= 1'b0; 
idle <= 1'b0;
timer <= 8'd0; 
result <= 1'b0; 
end
else if(send == 1'b1)
begin
case(timer)
8'd0: //Start 
begin
tx <= 1'b0;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd16://Send Bit0
begin
tx <= datain[0];
result <= datain[0]^poritymode;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd32://Send Bit1
begin
tx <= datain[1];
result <= datain[1]^result;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd48:// Send Bit2
begin
tx <= datain[2];
result <= datain[2]^result;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd64: //Send Bit3
begin
tx <= datain[3];
result <= datain[3]^result;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd80://Send Bit4
begin
tx <= datain[4];
result <= datain[4]^result;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd96:// Send Bit5
begin 
tx <= datain[5];
result <= datain[5]^result;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd112://Send Bit6
begin
tx <= datain[6];
result <= datain[6]^result;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd128://Send Bit7 
begin
tx <= datain[7];
result <= datain[7]^result;
idle <= 1'b1;
timer <= timer + 8'd1;
end

8'd144://Send Poritymode
begin
 tx <= result;
result <= datain[0]^poritymode;  //non-blocking assign
idle <= 1'b1;
timer <= timer + 8'd1;
//if(tx == result)
end

8'd160://Send stop Bit
begin
idle <= 1'b1;
tx <= 1'b1;
timer <= timer + 8'd1;
end

 8'd168:// a frame data finished
begin

tx <= 1'b1;
idle <= 1'b0;
timer <= timer + 8'd1;
end

  default: begin
timer <= timer + 8'd1;
end
endcase
end

else begin
tx <= 1'b1;
timer <= 8'd0;
idle <= 1'b0;
end
end
endmodule
 

*****************************************

*****************************************

RTL图:


Altera series- The UART of FPGA_第2张图片

图二 RTL









**********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

PART II    接收部分

接收部分 :  由RX来负责接收数据;

Altera series- The UART of FPGA_第3张图片


 图三  RX 

CODE:


 `timescale 1ns / 1ps

module Uart_rx(clk,rst_n,rx,dataout,error,frameerror,rsig);
input clk;
input rst_n;
input rx;


output reg [7:0]dataout;
output error;
output frameerror;
output rsig;
//output idle;






reg rsig ,error;
reg[7:0]timer;
//reg [7:0]dataout;
reg frameerror;
reg rx_temp, rx_falling;
reg result;
reg idle;
reg receive;


parameter poritymode = 1'b0;


always@(posedge clk ) //Generate falling edge timing  //first high ,than low .
begin
rx_temp <= rx; 
rx_falling <= rx_temp &(~rx);
end


//Generate Ack Signal 


always@(posedge clk )
begin
if(rx_falling &&(~idle)) // !!!!!!!!  at the same time  satisfy the select 
begin
receive <= 1'b1;
end
else if(timer == 8'd168)
begin
receive <= 1'b0;
end
end




//Receive Data 
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
error <= 1'b0;   // high voltage represent error !
frameerror <= 1'b0;// H
idle <= 1'b0; // 
timer <= 8'd0; // counter clear 0
result <= 1'b0; // clear 0 
//dataout <= 8'd0;
rsig <= 1'b0;
end

else if(receive == 1'b1) // receive data becycle 
begin
case(timer)
8'd0://Generate Start pulse  
begin

idle <= 1'b1;
timer <= timer + 8'd1;
rsig <= 1'b0;
end

8'd24:// Receive Bit0 
begin
idle <= 1'b1;
rsig <= 1'b0;
dataout[0] <= rx; 
timer <= timer + 8'd1;
 // data restore in buffer 
result <=  poritymode^rx; // compare odd
end

8'd40: // Received Bit1
begin
idle <= 1'b1;
rsig <= 1'b0;
dataout[1] <= rx;
timer <= timer + 8'd1;
result <=  result^rx;
end

8'd56: // Receive Bit2
begin
idle <= 1'b1;
rsig <= 1'b0;
dataout[2]<= rx;
timer <= timer + 8'd1;
result <=  result^rx;
end

8'd72: // Receive Bit3
begin
idle <= 1'b1;
rsig <= 1'b0;
dataout[3] <= rx;
timer <= timer + 8'd1;
result <=  result^rx;
end

8'd88: // Receive Bit4
begin
idle <= 1'b1;
rsig <= 1'b0;
dataout[4] <= rx;
timer <= timer + 8'd1;
result <= result^rx;
end

8'd104: // Receive Bit5
begin
idle <= 1'b1;
rsig <= 1'b0;
dataout[5] <= rx;
timer <= timer + 8'd1;
result <=  result^rx;
end

8'd120: // Receive Bit6
begin
idle <= 1'b1;
rsig <= 1'b0;
dataout[6] <= rx;
timer <= timer + 8'd1;
result <=  result^rx;
end

8'd136: // Receive Bit7
begin
idle <= 1'b1;
dataout[7] <= rx;
result <=  result^rx;
timer <= timer + 8'd1;

rsig <= 1'b1;
end

8'd152: // Receive Pority 
begin
idle <= 1'b1;

if(result == rx)
error <= 1'b0;
else 
error <= 1'b1;
timer <= timer + 8'd1;
rsig <= 1'b1;
end

8'd168: //Receive Stop Bit . Frame Judge 
begin
idle <= 1'b1;
if(1'b1 == rx)
frameerror <= 1'b0;
else 
frameerror <= 1'b1;

  //timer <= 8'd0;
timer <= timer + 8'd1;
rsig <= 1'b1;
end
default : timer <= timer + 8'd1;
endcase
end
else 
begin
  timer <= 8'd0;
idle <= 1'b0;
rsig <= 1'b0;

end
end
endmodule

你可能感兴趣的:(Altera series- The UART of FPGA)