Stories

Detail Return Return

原創單總線傳輸協議b2s (附全部verilog源碼) - Stories Detail

一、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    
View Code

接收端源碼:

/******************************************************************************************
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    
View Code

三、源碼例化方法

調用發送端,通過單個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
View Code

調用接收端,解碼發送端所發出的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        
View Code

四、總結

本協議優缺點如下:
優點:

1. 僅使用單個I/O口進行多bit數據發送和接收(串行),可節省大量I/O口留作它用。
2. 傳輸頻率不限,只需保證發送端和接收端工作頻率一致即可。
3. 接收端所得到的信息始終是最新的,傳輸頻率高時,近乎實時。
4. 發送和接收數據bit數量可根據需要進行增加/減少。
缺點:

1. 由於單線,無其他控制信號,發送端和接收端會一直處於工作狀態(發送端一直髮,接收端一直接)。

 

如您有此功能的定製開發或其他的FPGA設計需求,請查看下面這篇文章瞭解我們的業務範圍和聯繫方式,我們將竭誠為您服務。

精橙FPGA,一個承接FPGA代碼設計的資深工程師團隊。

 

user avatar Rocky-IC Avatar
Favorites 1 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.