在笔者之前所用的串口中,串口一次只能发送数据为8位,这跟串口通信的协议方式有关系。而最近笔者的项目中需要用到一次发送32位的数据。笔者最开始想到的是32位数据发送4次。
为了不改动原来的串口通信协议驱动,笔者设计了如下发送方式:
设计四个状态state,每个状态发送8位数据,发送完毕使能信号txd_flag送给state加一继续发送下一组8位数据,依次将32位数据发送完毕;
always@(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;
always@(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
always@(*)
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
always@(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
以上程序笔者亲测可行。