首先需要了解uart 的通訊協議和傳輸時序
uart通訊首先將接收到的並行資料轉換成序列資料來傳輸。訊息幀起始位為低電平,後面接7或8個資料位(大部分為8個資料位),1個可用的奇偶校驗位(根據資料中1的個數是否為偶數(偶校驗位)還是奇數(奇校驗位)),1個或者多個高位停止位。(傳輸乙個位元組大約需要10個位元位)
接收器發現開始位時知道資料準備傳送,並嘗試與傳送器時鐘頻率同步。如果選擇了奇偶校驗位,可以用來幫助錯誤校驗。在接收過程中,uart從訊息幀中去掉起始位和結束位,對進來的位元組進行奇偶校驗,並將資料位元組從序列轉成並行。
(t為乙個資料位占用的時間,如果波特率為9600,那麼t4=1/9600)
實驗實現,當按鍵key1按下,不斷傳送乙個常數,在串列埠除錯助手上可以檢視。利用狀態機實現
module uart_tx(
input clk, //時鐘輸入
input rst_n, //復位輸入
input key, //乙個按鍵,用於傳送控制,低電平有效
output reg txd //串列埠傳送管腳
//狀態機狀態定義,空閒位+開始位+8bit資料位+停止位
parameter s_idle = 4'd0; //空閒狀態
parameter s_start = 4'd1; //傳送1bit起始碼0
parameter s_bit0 = 4'd2; //傳送第一位資料
parameter s_bit1 = 4'd3;
parameter s_bit2 = 4'd4;
parameter s_bit3 = 4'd5;
parameter s_bit4 = 4'd6;
parameter s_bit5 = 4'd7;
parameter s_bit6 = 4'd8;
parameter s_bit7 = 4'd9;
parameter s_stop = 4'd10;//傳送停止位 1
reg [3:0] state; //定義狀態暫存器,11個狀態,2^4=16,足夠
reg[15:0] bit_timer; //用於控制波特率的計數器如果波特率是9600,每個資料位50000000/9600個時鐘週期
wire[7:0] tx_data; //傳送的固定資料12
assign tx_data = 8'hab; //此處可以修改傳送的資料
//----------一段式狀態機編寫
always@ (posedge clk or negedge rst_n)
begin
if (!rst_n)
begin
state<=s_idle;
bit_timer<=16'd0;
txd<=1'b1; //復位傳送管腳為高電平,因為開始為低電平
endelse
begin
case(state)
s_idle:
begin
txd<=1'b1;
bit_timer <= 16'd0;
if(!key) //如果按鍵按下
state<=s_start;
else
state<=state;
ends_start:
begin
txd<=1'b0; //開始狀態
if(bit_timer == 16'd5208)//乙個bit的時間到了,狀態轉換
begin
state <= s_bit0;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <=bit_timer+16'd1;
endend
s_bit1:
begin
txd <= tx_data[1]; //第二位資料
if(bit_timer == 16'd5208)
begin
state <= s_bit2;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
s_bit2:
begin
txd <= tx_data[2]; //第三位資料
if(bit_timer == 16'd5208)
begin
state <= s_bit3;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
s_bit3:
begin
txd <= tx_data[3]; //第四位資料
if(bit_timer == 16'd5208)
begin
state <= s_bit4;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
s_bit4:
begin
txd <= tx_data[4]; //第五位資料
if(bit_timer == 16'd5208)
begin
state <= s_bit5;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
s_bit5:
begin
txd <= tx_data[5]; //第六位資料
if(bit_timer == 16'd5208)
begin
state <= s_bit6;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
s_bit6:
begin
txd <= tx_data[6]; //第七位資料
if(bit_timer == 16'd5208)
begin
state <= s_bit7;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
s_bit7:
begin
txd <= tx_data[7];//最後一位資料
if(bit_timer == 16'd5208)
begin
state <= s_stop;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
s_stop:
begin
txd <= 1'b1;//停止位為高電平
if(bit_timer == 16'd5208)
begin
state <= s_idle;
bit_timer <= 16'd0;
endelse
begin
state <= state;
bit_timer <= bit_timer + 16'd1;
endend
default:
begin
state <= s_idle;
endendcase
endend
FPGA學習筆記 串列埠傳送模組的設計與驗證
從上圖我們可以看到,串列埠傳送模組一共被定義了5個訊號,其中4個輸入,1個輸出,下面,對這5個訊號進行一一闡述。clk 我想不用多說,哪怕是小白也知道,這是系統時鐘,自然是輸入訊號。rst n 系統復位訊號,自然也是輸入。另外,n表示低電平有效。tx trig 傳送資料開始訊號,只有當這個訊號出現乙...
FPGA學習 基於FPGA的簡易音訊採集系統
本篇部落格記錄乙個小專案的開發 基於fpga的簡易音訊採集系統,專案 是乙個寒假的活動的題目,直接購買了設計好的板卡,專案的基本要求如下 使用的板卡是lattice的ice40up5k,這裡首先記錄一下在lattice的軟體中開發fpga的簡單流程 參考 windows 下 ice40 fpga 開...
FPGA 學習之路 (七) UART串列埠設計
uart使用的是 非同步,序列通訊。序列通訊是指利用一條傳輸線將資料一位位地順序傳送。特點是通訊線路簡單,利用簡單的線纜就可實現通訊,降低成本,適用於遠距離通訊,但傳輸速度慢的應用場合。非同步通訊以乙個字元為傳輸單位,通訊中兩個字元間的時間間隔多少是不固定的,然而在同乙個字元中的兩個相鄰位間的時間間...