一、b2s協議背景介紹
本單總線傳輸協議為精橙FPGA團隊原創,含傳送端(transmitter)和接收端(receiver)兩部分,基於verilog語言,僅使用單個I/O口進行多位數據的傳輸,傳輸方向為單向,用於I/O不夠用的情況,已上板驗證通過,大家可直接使用。二、b2s協議Verilog源碼
ps. 帶★號處可根據需要進行修改.
發送端源碼:
/****************************************************************************************** File Name: b2s_transmitter.v Function: b2s發送端,默認發送32bit數據 ********************************************************************************************/ module b2s_transmitter ( clk, //時鐘基準,不限頻率大小,但必須與接收端一致 din, //待發送數據 b2s_dout //b2s數據輸出端口 ); parameter WIDTH=32; //★設定b2s發送數據位數 input clk; input [WIDTH-1:0] din; output b2s_dout; //============================================================== //b2s數據發送時序 //============================================================== reg b2s_dout_r; reg [3:0] state; reg [9:0] cnt; reg [4:0] count; //★與發送數據位數保持一致(如發送32bit數據時,count寬度為5;發送8bit時,count寬度為4) always @ (posedge clk) begin case(state) //初始化 0: begin count<=0; b2s_dout_r<=1; if(cnt==19) //b2s_dout_r高電平持續20個時鐘 begin state<=1; cnt<=0; end else begin cnt<=cnt+1; end end //開始信號時序 1: begin b2s_dout_r<=0; if(cnt==19) //b2s_dout_r低電平持續20個時鐘 begin state<=2; cnt<=0; end else begin cnt<=cnt+1; end end 2: begin b2s_dout_r<=1; if(cnt==19) //b2s_dout_r高電平持續20個時鐘 begin cnt<=0; state<=3; end else begin cnt<=cnt+1; end end //待發送數據的邏輯電平判斷 3: begin if(din[count]==1) state<=4; else state<=8; end //邏輯1的發送時序 4: begin b2s_dout_r<=0; if(cnt==9) //b2s_dout_r低電平持續10個時鐘 begin cnt<=0; state<=5; end else begin cnt<=cnt+1; end end 5: begin b2s_dout_r<=1; if(cnt==29) //b2s_dout_r高電平持續30個時鐘 begin cnt<=0; state<=6; end else begin cnt<=cnt+1; end end //邏輯0的發送時序 8: begin b2s_dout_r<=0; if(cnt==29) //b2s_dout_r低電平持續30個時鐘 begin cnt<=0; state<=9; end else begin cnt<=cnt+1; end end 9: begin b2s_dout_r<=1; if(cnt==9) //b2s_dout_r高電平持續10個時鐘 begin cnt<=0; state<=6; end else begin cnt<=cnt+1; end end //統計已發送數據位數 6: begin count<=count+1'b1; state<=7; end 7: begin if(count==WIDTH) //當一組數據所有位發送完畢,返回並繼續下一次發送 begin b2s_dout_r<=1; if(cnt==999) //b2s_dout_r高電平持續1000個時鐘 begin cnt<=0; state<=0; end else begin cnt<=cnt+1; end end else //當一組數據未發送完畢,則繼續此組下一位數據的發送 state<=3; end //default值設定 default: begin state<=0; cnt<=0; count<=0; end endcase end assign b2s_dout=b2s_dout_r; endmodule
接收端源碼:
/****************************************************************************************** File Name: b2s_receiver.v Function: b2s接收端,默認接收32bit數據 ********************************************************************************************/ module b2s_receiver ( clk, //時鐘基準,不限頻率大小,但必須與發送端一致 b2s_din, //b2s發送端發送過來的信號 dout //b2s接收端解碼出的數據 ); parameter WIDTH=32; //★設定b2s接收數據位數 input clk; input b2s_din; output [WIDTH-1:0] dout; //================================================== //b2s_din信號邊沿檢測 //================================================== reg [1:0] b2s_din_edge=2'b01; always @ (posedge clk) begin b2s_din_edge[0] <= b2s_din; b2s_din_edge[1] <= b2s_din_edge[0]; end //================================================== //time_cnt - 存儲b2c_din信號下降沿及其最近的下一個上升沿之間的時間 //================================================== reg [1:0] state0; reg [5:0] time_cnt_r; always @ (posedge clk) begin case(state0) 0: begin time_cnt_r<=0; state0<=1; end 1: begin if(b2s_din_edge==2'b10) state0<=2; else state0<=state0; end 2: begin if(b2s_din_edge==2'b01) begin state0<=0; end else time_cnt_r<=time_cnt_r+1'b1; end default: begin time_cnt_r<=0; state0<=0; end endcase end wire [5:0] time_cnt; assign time_cnt=(b2s_din_edge==2'b01)?time_cnt_r:'b0; //當b2s_din上升沿瞬間,讀取time_cnt_r的值 //================================================== //b2s解碼時序 //================================================== reg [2:0] state; reg [4:0] count; //★與接收數據位數保持一致(如接收32bit數據時,count寬度為5;接收8bit時,count寬度為4) reg [WIDTH-1:0] dout_r; always @ (posedge clk) begin case(state) 0: begin count<=WIDTH; if((time_cnt>15)&&(time_cnt<25)) //判斷起始信號 state<=1; else state<=state; end 1: begin if((time_cnt>5)&&(time_cnt<15)) //邏輯1的條件 begin dout_r[WIDTH-1]<=1; state<=2; end else if((time_cnt>25)&&(time_cnt<35))//邏輯0的條件 begin dout_r[WIDTH-1]<=0; state<=2; end else begin state<=state; end end 2: begin count<=count-1'b1; //每讀取一個bit,count減1 state<=3; end 3: if(count==0) //數據讀取完畢,返回並繼續下一組數據的讀取 begin state<=0; end else state<=4; //數據未讀取完畢,則進行移位 4: begin dout_r<=(dout_r>>1);//數據右移1位 state<=1; end default: begin state<=0; count<=WIDTH; end endcase end assign dout=(count==0)?dout_r:dout; //每當一組數據讀取完畢,則更新一次dout的值 endmodule
三、源碼例化方法
調用發送端,通過單個I/O發送出一組32bit數據:
/****************************************************************************************** File Name: b2s_transmitter_test.v Function: b2s功能測試:通過b2s transmitter模塊將預置的32bit數據發送出去 ********************************************************************************************/ module b2s_transmitter_test ( input clk, //基準時鐘 output b2s_dout //b2s數據輸出端口 ); parameter WIDTH=32; //★設定b2s發送和接收數據位寬,此處可根據需要進行修改 //============================================================== //預置待發送數據 //============================================================== wire [WIDTH-1:0] din; assign din='b01010101_00111100_11011100_11001111; //★此處可根據需要進行修改,不限於固定數值 //================================ //調用b2s_transmitter模塊 //================================ b2s_transmitter # ( .WIDTH(WIDTH) //例化發送數據位寬 ) b2s_transmitter_isnt0 ( .clk (clk), //時鐘基準,不限頻率大小,但必須與接收端一致 .din (din), //待發送數據 .b2s_dout (b2s_dout) //b2s數據輸出端口 ); endmodule
調用接收端,解碼發送端所發出的32bit數據:
/****************************************************************************************** File Name: b2s_receiver_test.v Function: b2s功能測試:通過b2s receiver模塊進行對b2s transmitter發送的數據進行接收解碼 ********************************************************************************************/ module b2s_receiver_test ( input clk, //基準時鐘 input b2s_dout, //b2s發送端發送過來的信號 output [31:0] dout //解碼出的32bit數據 ); parameter WIDTH=32; //★設定b2s發送和接收數據位數,此處可根據需要進行修改 //================================ //調用b2s_receiver模塊 //================================ b2s_receiver # ( .WIDTH (WIDTH) //例化接收數據位寬 ) b2s_receiver_inst0 ( .clk (clk), //時鐘基準,不限頻率大小,但必須與發送端一致 .b2s_din (b2s_dout), //b2s發送端發送過來的信號 .dout (dout) //b2s接收端解碼出的數據 ); endmodule
四、總結
本協議優缺點如下:
優點:
1. 僅使用單個I/O口進行多bit數據發送和接收(串行),可節省大量I/O口留作它用。
2. 傳輸頻率不限,只需保證發送端和接收端工作頻率一致即可。
3. 接收端所得到的信息始終是最新的,傳輸頻率高時,近乎實時。
4. 發送和接收數據bit數量可根據需要進行增加/減少。
缺點:
1. 由於單線,無其他控制信號,發送端和接收端會一直處於工作狀態(發送端一直髮,接收端一直接)。

如您有此功能的定製開發或其他的FPGA設計需求,請查看下面這篇文章瞭解我們的業務範圍和聯繫方式,我們將竭誠為您服務。
精橙FPGA,一個承接FPGA代碼設計的資深工程師團隊。