00 簡介
和接收部分相反,UART發送數據部分是CPU將需要發送的數據寫到發送數據寄存器(TX_DATA),發送模塊進行數據的發送。由于系統時鐘速率一般會比UART發送數據快,所以發送數據將緩存到發送數據FIFO(TX_FIFO)。當TX_FIFO非空時,發送數據模塊會根據UART傳輸協議將數據發送出去,直到TX_FIFO為空。
類似的,發送模塊也涉及到ARM時鐘和26MHz功能時鐘。其中 發送FIFO讀寫邏輯是ARM時鐘域,發送數據狀態機和同步邏輯等是功能時鐘域 。
01 模塊接口與描述
02 實現
UART_TX模塊主要由三部分組成: 配置信息同步 、TX_FIFO讀控制部分和 發送狀態機 。
配置信息是reg_if模塊由APB總線配置寄存器產生,功能時鐘域做兩級同步處理。(比如校驗位使能、奇偶校驗控制、停止位使能等)
發送數據FIFO控制部分將FIFO中的數據讀出,通過發送數據狀態機將數據發送。
發送狀態機是根據串口協議劃分,分為IDLE、IRQ、START_BIT、TX_DATA、CHECK_BIT、STOP和DELAY六種狀態。
配置信息同步
和接收模塊類似,由于配置信息是由APB時鐘產生,到接收模塊的功能時鐘域需要做同步處理。配置信息是電平信號,通常不會像數據一樣變化快,所以只需要兩級同步。
接收狀態機
使用典型的三段式狀態機設計,狀態轉移圖如下:
uart發送狀態轉移圖
IDLE: 發送狀態機的IDLE狀態會產生tx_start的發送請求信號,FIFO讀邏輯部分會判斷讀空信號tx_fifo_rempty和tx_start,如果TX_FIFO非空且發送請求有效,則產生發送響應tx_ack,并發出FIFO讀使能。IDLE狀態機內發現tx_ack有效,跳轉到IRQ狀態。IRQ: IRQ狀態目的是等待FIFO數據讀出。進入IRQ后使能波特率時鐘,tx_start信號disable,跳轉到START_BIT。
START_BIT: 發送起始位。拉低utxd_o后跳轉到發送數據狀態TX_DATA。
TX_DATA: 發送從TX_FIFO讀出的8bit數據,發送完8bit數據后判斷校驗位是否使能(check_syn2),使能則進入CHECK_BIT,不使能則進入STOP狀態。
CHECK_BIT: 8bit數據按位異或(偶校驗)或同或(奇校驗),計算出校驗位發送,判斷是否使能停止位(stop_bit_syn2),如使能停止位則進入STOP狀態,不使能則進入DELAY狀態。
這里提一下 奇偶校驗 。
所謂奇校驗,就是判斷發送的數據位中1的個數是否是奇數,如果數據位中1的個數是偶數,那就給校驗位賦值1;如果數據位中1的個數是奇數,那就給校驗位賦值0。目的是確保發送的數據中1的個數是奇數。
偶校驗則相反,判斷發送的數據位中1的個數是否是偶數,如果數據位中1的個數是偶數,那就給校驗位賦值0;如果數據位中1的個數是奇數,那就給校驗位賦值1。目的是確保發送的數據中1的個數是偶數。
實現時,奇偶校驗可以用同或和異或操作計算,相同的8bit數奇偶校驗的值一定是相反的。
STOP: STOP狀態拉高utxd_o,然后進入DELAY狀態。
DELAY: DELAY狀態控制相鄰兩次發送之間的間隔,間隔時間以波特率時鐘為單位,受CPU控制(配置字two_tx_delay),默認delay兩個波特率時鐘周期。延時后回到IDLE狀態進行等待或下一Byte數據傳輸。
前兩段狀態機,狀態跳轉:
// state to nextstate with clk in this block.
always@(posedge clk26m ornegedge rst26m_) begin
if(!rst26m_) begin
state <= IDLE;
end
elsebegin
state <= nextstate;
end
end
// nextstate transform
always@(*) begin
case(state)
IDLE: begin
if(tx_ack_delay2) begin
nextstate = IRQ;
end
elsebegin
nextstate = IDLE;
end
end
IRQ: begin
if(tx_bpsclk) begin
nextstate = START_BIT;
end
elsebegin
nextstate = IRQ;
end
end
START_BIT: begin
if(tx_bpsclk) begin
nextstate = TX_DATA;
end
elsebegin
nextstate = START_BIT;
end
end
TX_DATA: begin
// send 8 bit data
if(data_cnt < 4'd8) begin
nextstate = TX_DATA;
end
elsebegin
if(tx_bpsclk) begin
if(check_syn2) begin
nextstate = CHECK_BIT;
end
elsebegin
nextstate = STOP;
end
end
elsebegin
nextstate = TX_DATA;
end
end
end
CHECK_BIT: begin
if(tx_bpsclk) begin
if(stop_bit_syn2) begin
nextstate = STOP;
end
elsebegin
nextstate = DELAY;
end
end
elsebegin
nextstate = CHECK_BIT;
end
end
STOP: begin
if(tx_bpsclk) begin
nextstate = DELAY;
end
elsebegin
nextstate = STOP;
end
end
DELAY: begin
if(baud_cnt < two_tx_delay_syn2) begin
nextstate = DELAY;
end
elsebegin
nextstate = IDLE;
end
end
default: begin
nextstate = IDLE;
end
endcase
end