一、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程式碼設計的資深工程師團隊。