FPGA 學習筆記(十二) 如何用串列埠傳送32位資料?
阿新 • • 發佈:2019-01-01
在筆者之前所用的串列埠中,串列埠一次只能傳送資料為8位,這跟串列埠通訊的協議方式有關係。而最近筆者的專案中需要用到一次傳送32位的資料。筆者最開始想到的是32位資料傳送4次。
為了不改動原來的串列埠通訊協議驅動,筆者設計瞭如下發送方式:
設計四個狀態state,每個狀態傳送8位資料,傳送完畢使能訊號txd_flag送給state加一繼續傳送下一組8位資料,依次將32位資料傳送完畢;
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
state<=0 ;
end
else if(txd_flag)
if(state < 4'd4)
state<=state+1;
else
state<=0;
else
state<=state;
end
檢測state變化,state的每個變化的狀態代表串列埠輸入的資料不同:
即 state為0傳送32位資料的低8為,state為1傳送32為資料的後8位,依次類推;
if(state==4'd1)
data<=txd_data[7:0];
else if(state==4'd2)
data<=txd_data[15:8];
else if(state==4'd3)
data<=txd_data[23:16];
else if(state==4'd4)
data<=txd_data[31:24];
然後呼叫原來的串列埠驅動程式即可
`timescale 1ns/1ns
module uart_transfer
(
//gobal clock
input clk,
input rst_n,
//uart interface
input clken_16bps,//clk_bps * 16
output reg txd, //uart txd interface
//user interface
input txd_en, //uart data transfer enable
input [7:0] txd_data, //uart transfer data
output reg txd_flag //uart data transfer done
);
/**************************************************************************
..IDLE...Start...............UART DATA........................End...IDLE...
________ ______________
|____< D0 >< D1 >< D2 >< D3 >< D4 >< D5 >< D6 >< D7 >
Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 Bit8 Bit9
**************************************************************************/
//---------------------------------------
//parameter of uart transfer
localparam T_IDLE = 2'b0; //test the flag to transfer data
localparam T_SEND = 2'b1; //uart transfer data
reg [1:0] txd_state; //uart transfer state
reg [3:0] smp_cnt; //16 * clk_bps, the center for sample
reg [3:0] txd_cnt; //txd data counter
localparam SMP_TOP = 4'd15;
localparam SMP_CENTER = 4'd7;
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
smp_cnt <= 0;
txd_cnt <= 0;
txd_state <= T_IDLE;
end
else
begin
case(txd_state)
T_IDLE:
begin
smp_cnt <= 0;
txd_cnt <= 0;
if(txd_en == 1)
txd_state <= T_SEND;
else
txd_state <= T_IDLE;
end
T_SEND:
begin
if(clken_16bps == 1)
begin
smp_cnt <= smp_cnt + 1'b1;
if(smp_cnt == SMP_TOP)
begin
if(txd_cnt < 4'd9)
begin
txd_cnt <= txd_cnt + 1'b1;
txd_state <= T_SEND;
end
else
begin
txd_cnt <= 0;
txd_state <= T_IDLE;
end
end
else
begin
txd_cnt <= txd_cnt;
txd_state <= txd_state;
end
end
else
begin
txd_cnt <= txd_cnt;
txd_state <= txd_state;
end
end
endcase
end
end
//--------------------------------------
//uart 8 bit data transfer
[email protected](*)
begin
if(txd_state == T_SEND)
case(txd_cnt)
4'd0: txd = 0;
4'd1: txd = txd_data[0];
4'd2: txd = txd_data[1];
4'd3: txd = txd_data[2];
4'd4: txd = txd_data[3];
4'd5: txd = txd_data[4];
4'd6: txd = txd_data[5];
4'd7: txd = txd_data[6];
4'd8: txd = txd_data[7];
4'd9: txd = 1;
default:txd = 1;
endcase
else
txd = 1'b1; //default state
end
//-------------------------------------
//Capture the falling of data transfer over
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n)
txd_flag <= 0;
else if(clken_16bps == 1 && txd_cnt == 4'd9 && smp_cnt == SMP_TOP) //Totally 8 data is done
txd_flag <= 1;
else
txd_flag <= 0;
end
endmodule
以上程式筆者親測可行。