FPGA-串列埠通訊的接收模組(傳送接收模組)
阿新 • • 發佈:2018-12-24
接收模組和傳送模組類似:
在接收的過程中為了保證接收資料的準確性對單個時鐘波特率進行分頻,單個時鐘訊號下分頻16次,進行資料採集保證了資料的準確性,這裡的程式碼思想借鑑了小梅哥的程式碼的編寫思想。
傳送接收模組的驗證:
這裡傳送接收的驗證是通過PC端進行傳送,由開發板先接收到資料,然後進行傳送,這裡如果要是驗證些字串或者是一些特殊的指令,用狀態機或者類似狀態機的思想進行設計。
這裡只貼出任務要求的接收模組的驗證基本任務和程式碼
任務要求:
由PC埠進行傳送指令檢測單個字元和字串
如果傳送I Like FPGA led 全亮,如果錯誤led閃爍,當傳送單個字元時,利用LED燈指示該字元的ASCII碼。
串列埠接收模組:
module uart_rxd(clk,rst_n,bps_set,rxd,data_byte,rxd_finish,uart_state
);
input clk ;//輸入時鐘
input rst_n ;//復位訊號
input [1:0] bps_set ;//波特率選擇
input rxd ;//接收模組
output [7:0] data_byte ;//接收資料
output rxd_finish;//傳送完成標誌
output uart_state;//串列埠通訊狀態
reg [7:0] data_byte ;
reg rxd_finish;
reg uart_state;
parameter BPS_4800 =16'd324,
BPS_9600 =16'd162,
BPS_19200 =16'd80 ,
BPS_115200 =16'd13 ;
//消除亞穩態
reg rxd_s0,rxd_s1; //同步暫存器
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rxd_s0<=1'b0;
rxd_s1<=1'b0;
end
else begin
rxd_s0<=rxd;
rxd_s1<=rxd_s0;
end
end
reg rxd_temp0,rxd_temp1;//資料暫存器
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rxd_temp0<=1'b0;
rxd_temp1<=1'b0;
end
else begin
rxd_temp0<=rxd_s1;
rxd_temp1<=rxd_temp0;
end
end
wire rxd_negedge =~rxd_temp0&rxd_temp1;
reg [15:0] div_cnt;
reg [15:0] time_div;
//波特率選擇模組
[email protected](*)begin
if(rst_n==1'b0)begin
time_div=BPS_9600;
end
else begin
case(bps_set)
2'b00: time_div = BPS_4800;
2'b01: time_div = BPS_9600;
2'b10: time_div = BPS_19200;
2'b11: time_div = BPS_115200;
default:time_div = BPS_9600;
endcase
end
end
//波特率計數模組
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
div_cnt<=1'b0;
end
else if(uart_state==1'b1)begin
if(div_cnt==time_div)begin
div_cnt<=1'b0;
end
else begin
div_cnt<=div_cnt+1'b1;
end
end
else begin
div_cnt<=1'b0;
end
end
//波特率時鐘模組
reg bps_clk;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
bps_clk<=1'b0;
end
else if(div_cnt==time_div)begin
bps_clk<=1'b1;
end
else begin
bps_clk<=1'b0;
end
end
//bps計數模組
reg [7:0] bps_cnt;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
bps_cnt<=8'd0;
end
else if(rxd_finish==1'b1||(bps_cnt==8'd12 && (Start>3'd3)))begin
bps_cnt<=8'd0;
end
else if(bps_clk==1'b1)begin
bps_cnt<=bps_cnt+1'b1;
end
else begin
bps_cnt<=bps_cnt;
end
end
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rxd_finish=1'b0;
end
else if(bps_cnt==8'd159)begin
rxd_finish=1'b1;
end
else begin
rxd_finish=1'b0;
end
end
//資料緩衝區模組
reg [2:0] r_data_byte[7:0];
reg [2:0]Start,Stop;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
Start<=3'd0;
r_data_byte[0]<=3'd0;
r_data_byte[1]<=3'd0;
r_data_byte[2]<=3'd0;
r_data_byte[3]<=3'd0;
r_data_byte[4]<=3'd0;
r_data_byte[5]<=3'd0;
r_data_byte[6]<=3'd0;
r_data_byte[7]<=3'd0;
Stop<=3'd0;
end
else if(bps_clk==1'b1)begin
if(bps_cnt==1'b0)begin
Start<=3'd0;
r_data_byte[0]<=3'd0;
r_data_byte[1]<=3'd0;
r_data_byte[2]<=3'd0;
r_data_byte[3]<=3'd0;
r_data_byte[4]<=3'd0;
r_data_byte[5]<=3'd0;
r_data_byte[6]<=3'd0;
r_data_byte[7]<=3'd0;
Stop<=3'd0;
end
if(16'd6<=bps_cnt&&bps_cnt<=16'd12)begin
Start<=Start+rxd_s1;
end
else if(16'd22<=bps_cnt&&bps_cnt<=16'd28)begin
r_data_byte[0]<=r_data_byte[0]+rxd_s1;
end
else if(16'd38<=bps_cnt&&bps_cnt<=16'd44)begin
r_data_byte[1]<=r_data_byte[1]+rxd_s1;
end
else if(16'd54<=bps_cnt&&bps_cnt<=16'd60)begin
r_data_byte[2]<=r_data_byte[2]+rxd_s1;
end
else if(16'd70<=bps_cnt&&bps_cnt<=16'd76)begin
r_data_byte[3]<=r_data_byte[3]+rxd_s1;
end
else if(16'd86<=bps_cnt&&bps_cnt<=16'd92)begin
r_data_byte[4]<=r_data_byte[4]+rxd_s1;
end
else if(16'd102<=bps_cnt&&bps_cnt<=16'd108)begin
r_data_byte[5]<=r_data_byte[5]+rxd_s1;
end
else if(16'd118<=bps_cnt&&bps_cnt<=16'd124)begin
r_data_byte[6]<=r_data_byte[6]+rxd_s1;
end
else if(16'd134<=bps_cnt&&bps_cnt<=16'd140)begin
r_data_byte[7]<=r_data_byte[7]+rxd_s1;
end
else if(16'd150<=bps_cnt&&bps_cnt<=16'd156)begin
Stop<=Stop+rxd_s1;
end
end
else;
end
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
data_byte<=8'd0;
end
else if(bps_cnt==8'd159)begin
data_byte[0]<=(r_data_byte[0]>3'd3)?1'b1:1'b0;
data_byte[1]<=(r_data_byte[1]>3'd3)?1'b1:1'b0;
data_byte[2]<=(r_data_byte[2]>3'd3)?1'b1:1'b0;
data_byte[3]<=(r_data_byte[3]>3'd3)?1'b1:1'b0;
data_byte[4]<=(r_data_byte[4]>3'd3)?1'b1:1'b0;
data_byte[5]<=(r_data_byte[5]>3'd3)?1'b1:1'b0;
data_byte[6]<=(r_data_byte[6]>3'd3)?1'b1:1'b0;
data_byte[7]<=(r_data_byte[7]>3'd3)?1'b1:1'b0;
end
else begin
data_byte<=data_byte;
end
end
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
uart_state<=1'b0;
end
else if(rxd_negedge==1'b1)begin
uart_state<=1'b1;
end
else if(rxd_finish==1'b1||(bps_cnt==8'd12 && (Start>3'd3)))begin
uart_state<=1'b0;
end
else begin
uart_state<=uart_state;
end
end
endmodule
字元緩衝模組:
module uart_dat_buf(clk,rst_n,rxd_sel,rxd_finish,rxd_state,data_byte,led
);
input clk ;//輸入時鐘
input rst_n ;//復位訊號
input rxd_sel ;//指令選擇
input rxd_finish;//一位資料傳送完成標誌
input rxd_state ;//傳送狀態標誌
input [7:0] data_byte ;
output reg[7:0] led ;
parameter TIME = 25'd2500_0000,
S0 =4'd0,
S1 =4'd1,
S2 =4'd2,
S3 =4'd3,
S4 =4'd4,
S5 =4'd5,
S6 =4'd6,
S7 =4'd7,
S8 =4'd8,
S9 =4'd9,
S10=4'd10,
ERROR =4'd15;
//資料接收模組
reg [7:0] data_byte_temp;
[email protected](*)begin
if(rst_n==1'b0)begin
data_byte_temp=8'd0;
end
else if(rxd_state==1'b1)begin
data_byte_temp=data_byte;
end
else begin
data_byte_temp=data_byte_temp;
end
end
//狀態轉換
reg [3:0] state_c;
reg [3:0] state_n;
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
state_c<=S0;
end
else if(rxd_state==1'b1)begin
state_c<=state_c;
end
else begin
state_c<=state_n;
end
end
//狀態判斷
[email protected](*)begin
if(rst_n==1'b0)begin
state_n=S0;
end
else if(rxd_sel==1'b0&&rxd_state==1'b1)begin
case(state_c)
S0 :
if(data_byte_temp=="I")begin
state_n=S1;
end
else begin
state_n=ERROR;
end
S1 :
if(data_byte_temp==" ")begin
state_n=S2;
end
else begin
state_n=ERROR;
end
S2 :
if(data_byte_temp=="L")begin
state_n=S3;
end
else begin
state_n=ERROR;
end
S3 :
if(data_byte_temp=="i")begin
state_n=S4;
end
else begin
state_n=ERROR;
end
S4 :
if(data_byte_temp=="k")begin
state_n=S5;
end
else begin
state_n=ERROR;
end
S5 :
if(data_byte_temp=="e")begin
state_n=S6;
end
else begin
state_n=ERROR;
end
S6 :
if(data_byte_temp==" ")begin
state_n=S7;
end
else begin
state_n=ERROR;
end
S7 :
if(data_byte_temp=="F")begin
state_n=S8;
end
else begin
state_n=ERROR;
end
S8 :
if(data_byte_temp=="P")begin
state_n=S9;
end
else begin
state_n=ERROR;
end
S9 :
if(data_byte_temp=="G")begin
state_n=S10;
end
else begin
state_n=ERROR;
end
S10:
if(data_byte_temp=="A")begin
state_n=S0;
end
else begin
state_n=ERROR;
end
ERROR:if(data_byte_temp=="I")begin
state_n=S1;
end
else begin
state_n=ERROR;
end
default:state_n=S0;
endcase
end
else begin
state_n=state_n;
end
end
reg [1:0] flag_led;
//輸出模組
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_led<=2'd3;
end
else if(rxd_sel==1'b1)begin
flag_led<=2'b10;
end
else if(rxd_sel==1'b0)begin
if(state_c==ERROR)begin
flag_led<=2'b01;
end
else if(state_c==S10)begin
flag_led<=2'b00;
end
else begin
flag_led<=flag_led;
end
end
else begin
flag_led<=2'b11;
end
end
//閃爍led設計
reg [24:0] cnt;//存放計數器的值
//數碼管特殊狀態閃爍計數器模組
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt <=25'd0;
end
else if(cnt ==TIME-1'b1)begin
cnt <=1'b0;
end
else if(flag_led==2'b01)begin
cnt <=cnt + 1'b1;
end
else begin
cnt <=25'd0;
end
end
//led燈指示
[email protected](posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
led<=8'b1111_1111;
end
else if(flag_led==2'b10)begin
led<=data_byte_temp;
end
else if(flag_led==2'b00)begin
led<=8'b0000_0000;
end
else if(flag_led==2'b01)begin
if(cnt<(TIME/2-1'b1))begin
led<=8'b1111_1111;
end
else begin
led<=8'b0000_0000;
end
end
else if(flag_led==2'b11)begin
led<=8'b1111_1111;
end
else begin
led<=led;
end
end
endmodule
頂層檔案:
module uart_rxd_top(ext_clk_25m,ext_rst_n,uart_rx,led,switch0
);
input ext_clk_25m ;//系統時鐘
input ext_rst_n ;//復位訊號
input uart_rx ;//串列埠通訊接收
input switch0 ;//指令切換
output [7:0]led ;//led顯示
wire [7:0]data_byte;
wire uart_state;
wire rxd_finish;
uart_rxd u_r1(
.clk(ext_clk_25m),
.rst_n(ext_rst_n),
.bps_set(1),
.rxd(uart_rx),
.data_byte(data_byte),
.rxd_finish(rxd_finish),
.uart_state(uart_state)
);
uart_dat_buf u_dat1(
.clk(ext_clk_25m),
.rst_n(ext_rst_n),
.rxd_sel(switch0),
.rxd_finish(rxd_finish),
.rxd_state(uart_state),
.data_byte(data_byte),
.led(led)
);
endmodule