匯流排通訊協議-UART
阿新 • • 發佈:2021-01-26
技術標籤:verilog 程式設計題
目錄
1. 簡介
UART:universal asynchronous receiver and transmitter通用非同步收發器,序列介面,適用於速度較慢的點對點通訊場景,由於是非同步通訊,沒有時鐘訊號,因此需要收發雙方的波特率相同、
USART:universal synchronous asynchronous receiver and transmitter通用同步/非同步收/發器,是UART的升級版,可以進行同步通訊
1.1 特點
非同步,序列介面,速度較慢,20Kbps,可以實現全雙工傳輸和接收
1.2. 介面
tx:傳送資料線
rx:接受資料線
一般還會加上VCC和GND
1對1傳輸,所以不用傳輸地址,I2C是要傳輸地址的,PSI由於有片選訊號,所以也不用傳輸地址。
2. 傳輸協議
預設:高電平
起始:1bit/低電平
資料:8bit
校驗位:1bit; 奇校驗表示資料中1的個數為奇數,則校驗位為0,如果為偶數,那麼校驗位為1,也就是說資料碼+校驗位共有奇數個1.
終止位 : 1bit/ 高電平
2.1 傳輸時序圖
TX:
2.2 模組實現
傳送模組
module tx #( parameter DATA_WIDTH = 8, parameter ODD_EVEN = 0 // 0 stand for the even )( input wire [DATA_WIDTH-1 : 0] data_in, input wire data_vld, input wire sys_clk, input wire sys_rst_n, output reg data_out ); parameter IDLE = 5'b00001; parameter START = 5'b00010; parameter DATA_TRA = 5'b00100; parameter CHECK = 5'b01000; parameter STOP = 5'b10000; reg [4:0] cur_state; reg [4:0] nxt_state; always_ff @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) cur_state <= IDLE; else cur_state <= nxt_state; end reg [7:0] data_in_reg; always_ff @(posedge sys_clk or negedge sys_rst_n) begin : proc_data_in_reg if(~sys_rst_n) begin data_in_reg <= 0; end else if (data_vld)begin data_in_reg <= data_in; end end reg [2:0] data_cnt; always_latch begin nxt_state = IDLE; case (cur_state) IDLE : if (data_vld) nxt_state = START; START : nxt_state = DATA_TRA; DATA_TRA : if(data_cnt == DATA_WIDTH-1) nxt_state = CHECK; else nxt_state = DATA_TRA; CHECK : nxt_state = STOP; STOP : nxt_state = IDLE; endcase end always_ff @(posedge sys_clk or negedge sys_rst_n) begin : proc_data_cnt if(~sys_rst_n) begin data_cnt <= 'd0; end else if (cur_state == DATA_TRA)begin data_cnt <= data_cnt + 1'b1; end else data_cnt <= 'd0; end reg check_tmp; always_ff @(posedge sys_clk or negedge sys_rst_n) begin : proc_check_tmp if(~sys_rst_n) begin check_tmp <= 'b0; end else if (cur_state == DATA_TRA)begin check_tmp <= check_tmp + (data_in_reg >> data_cnt); //calculate the number of 1 end else if (cur_state == STOP) check_tmp <= 'b0; end always_ff @(posedge sys_clk or negedge sys_rst_n) begin : proc_data_out if(~sys_rst_n) begin data_out <= 'b1; end else if (cur_state == START) begin data_out <= 'b0; end else if (cur_state == DATA_TRA ) begin data_out <= data_in_reg >> data_cnt; end else if (cur_state == CHECK) begin data_out <= check_tmp ^ ODD_EVEN; end else data_out <= 'b1; end endmodule
整個程式碼的狀態機就是根據時序圖得到的,因為一般傳輸協議的時序圖都代表著一定的順序關係,所以用狀態機實現是最方便的。
2.3 模組測試
module tb_tx(); parameter DATA_WIDTH = 8; parameter ODD_EVEN = 0; reg [DATA_WIDTH-1 : 0] data_in; reg data_vld; reg sys_clk, sys_rst_n; wire data_out; initial begin sys_clk = 'b0; sys_rst_n = 'b0; # 15 sys_rst_n = 'b1; end always #5 sys_clk = ~sys_clk; initial begin data_vld = 'b0; data_in = 'd0; repeat(2) @ (posedge sys_clk) ; data_vld = 'b1; data_in = 'b10010001; @(posedge sys_clk) ; data_vld = 'b0; data_in = 'd0; #10000 $finish; end tx tx_dut( data_in, data_vld, sys_clk, sys_rst_n, data_out ); initial begin $fsdbDumpfile("tb_tx.fsdb"); $fsdbDumpvars(0, tb_tx); $fsdbDumpon; end endmodule
從波形圖可以看出,和我們的時序圖幾乎一致,開始,資料傳輸10001001, 奇偶校驗位:採用的是偶校驗,所以校驗位為1,結束高電平。
3. 小結
- URRT是非同步的,因為它沒有時鐘訊號作為基準,它以一個低電平作為開始訊號,因為Tx預設是拉高的,然後通過設定波特率讓接受方和傳送方同步。
參考連結:https://blog.csdn.net/z123canghai/article/details/88411302