99在线精品免费视频九九视-99在线精品视频-99在线精品视频免费观里-99在线精品视频在线观看-99在线免费播放



官方論壇
官方淘寶
官方博客
微信公眾號
點擊聯(lián)系吳工 點擊聯(lián)系周老師

【文章】USB3.0數據通信設計

發(fā)布時間:2021-06-24   作者:admin 瀏覽量:

        

作為一個即將畢業(yè)但由于疫情不能回校的研三學生的獨白。。。。。。


真正和FPGA打交道應該是剛讀研一的時候,不知道市場上什么資料好,可能和剛開始學習FPGA的同學們一樣,主要心態(tài)是想快速掌握這門技術,經過一番調查選擇了潘老師的《手把手教你學FPGA設計》,終于被大道至簡的至簡設計法所打敗了。


一、為什么大道至簡好用且方便


由于《手把手教你學FPGA設計》書中講解詳細且區(qū)域劃分鮮明,至簡設計法最大特點2個,設計模板化和思考步驟化。


設計模板化:

在設計上明德?lián)P把一些功能模板規(guī)范成可復用的模板,我們只需要填入參數就能把設計做出來,極大地減少代碼上不必要的錯誤,我們只需要專心做好設計; 


思考步驟化:

至簡設計法能幫助我們形成嚴謹的邏輯思維,做到設計有根據、思考有步驟。 


過多贅述不必多說,就像潘老師所說過那樣,學好FPGA最重要就是狀態(tài)機和計數器,記住,這是重點,要考的!!!

其實剛開始我沒認為這兩項多么重要,哈哈哈,但是隨著工程代碼量的不斷增大以及對時序等要求的不斷增強,愈發(fā)覺得基礎才能決定上層建筑。而反觀三段式或四段式狀態(tài)機代碼清晰,結構分明,你所需要做的只是添磚加瓦,也就是你自己的狀態(tài),因為地基已經為你搭好了。再說計數器,應該說沒有什么說的了,抬手就寫,因為代碼放在那了啊,只需要添加你的加一和結束條件就可以了啊!!!現(xiàn)在想想當初的我為什么要特立獨行!!!導致在仿真階段浪費好多時間。

二. USB3.0數據通信

        最近寫的代碼(也不是最近了,大約在過年回家之前)是關于USB3.0數據通信的,這里多說幾句,板子前期是購買的,后來自己設計的。代碼部分是賣家提供(具體名稱不方便透露,因為我不是挑事的人,哈哈哈),但是真的是他的代碼太繁瑣以及太不易搞懂且移植性太差了,但比較好的是我自己寫也不浪費什么事情,我將USB3.0的狀態(tài)分為讀,寫,空閑三個,然后根據三段式順利寫好屬于自己的代碼。源代碼在下面,哈哈哈,如果可以的話請不要亂發(fā)或者幫我打碼,畢竟畢業(yè)論文里還在用。并且家里電腦真的是什么軟件都沒安裝,我就用記事本復制過來的。

2.1. USB3.0控制模塊參考代碼

信號
類型
位寬
意義
clk
輸入
1
時鐘信號
pclk_in
輸入
1
USB芯片復位信號
rst_n
輸入
1
復位信號,低電平有效
flag_a
輸入
1
USB芯片標志位,控制寫狀態(tài)
flag_b
輸入
1
USB芯片標志位,控制寫狀態(tài)
flag_c
輸入
1
USB芯片標志位,控制讀狀態(tài)
flag_d
輸入
1
USB芯片標志位,控制讀狀態(tài)
pclk
輸出
1
USB芯片復位信號
slcs
輸出
1
USB芯片片選信號
sloe
輸出
1
USB芯片控制信號
slrd
輸出
1
USB芯片讀狀態(tài)選擇信號
slwr
輸出
1
USB芯片寫狀態(tài)選擇信號
pktend
輸出
1
USB芯片數據包信號
fifo_addr
輸出
2
USB芯片數據讀取方向控制信號
usb_data
雙向
32
USB3.0數據
cmd_flag
輸出
1
USB傳輸數據標志位
cmd_data
輸出
32
USB傳輸數據

module  USB_command(
        input                   clk  ,
        input                   pclk_in  ,
        input                   rst_n  ,
        //usb
        input                   flag_a  ,
        input                   flag_b  ,
        input                   flag_c  ,
        input                   flag_d  ,
output  wirepclk                            ,
output  wireslcs                            ,
output  reg             sloe                            ,
output  regslrd                            ,
output  regslwr                            ,
output  wirepktend                          ,
output  reg   [ 1: 0]   fifo_addr                       ,
inoutwire  [31: 0]   usb_data                        ,
output  regcmd_flag                        ,
output  wire  [31: 0]   cmd_data
                
                                
);
parameter   IDLE            =   4'b0001                         ;
parameter   WRITE           =   4'b0010                         ;
parameter   READ            =   4'b0100                         ;
reg   [ 3: 0]                 state_c /*synthesis preserve*/  ;
reg   [ 3: 0]                 state_n /*synthesis preserve*/  ;
//cnt
reg   [31: 0]                 cnt                             ;
wire                            add_cnt  ;
wire                            end_cnt  ;
reg   [15: 0]                 rd_cnt                          ;
reg   [15: 0]                 rd_data_len                     ;
regwr_trig                         ;//寫觸發(fā)
assign  slcs        =   1'b0;
assign  pclk        =   pclk_in;
assign  pktend      =   1'b1;
assign  usb_data    =   (!slwr) ? usb_write_data : 32'dz;
wire[31:0]  usb_write_data ;
//state_c
always@(posedgeclk or negedgerst_n)begin
    if(!rst_n)begin
state_c<= IDLE;
    end
    else begin
state_c<= state_n;
    end
end
//state_n
always@(*)begin
    case(state_c)
IDLE:begin
if(flag_a&&flag_b&&wr_trig)begin
state_n = WRITE;
            end
            else if(flag_c&&flag_d)begin
state_n = READ;                                        
            end
            else begin
state_n = state_c;                                        
            end
        end
WRITE:begin
            if(flag_b == 1'b0)begin //寫滿
state_n = IDLE;
            end
            else begin
state_n = state_c;
            end
        end
READ:begin
            if(flag_d == 1'b0)begin //讀空
state_n = IDLE;
            end
            else begin
state_n = state_c;
            end
        end
default:begin
state_n = IDLE;
        end
endcase
end
//fifo_addr
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
fifo_addr<=  2'b00;
        sloe        <=  1'b1;
    end
    else if(state_c==READ)begin
fifo_addr<=  2'b11;
        sloe        <=  1'b0;
    end
    else begin
fifo_addr<=  2'b00;
        sloe        <=  1'b1;
    end
end
//slwr 輸出信號,用時序邏輯好點
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
slwr<=  1'b1;
    end
    else if(state_c==WRITE)begin
slwr<=  1'b0;
    end
    else begin
slwr<=  1'b1;
    end
end
//slrd
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
slrd<=  1'b1;
    end
    else if(state_c==READ)begin
slrd<=  1'b0;
    end
    else begin
slrd<=  1'b1;
    end
end
//rd_cnt
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
rd_cnt<=  16'd0;
    end
    else if(slrd)begin
rd_cnt<=  16'd0;
    end
    else begin
rd_cnt<=  rd_cnt + 1'b1;
    end
end
//rd_data_len
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
rd_data_len<=  16'd0;
    end
    else if(rd_cnt == 16'd3)begin
rd_data_len<=  usb_data + 16'd3;
    end
end
//cmd_flag
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
cmd_flag<=  1'b0;
    end
    else if(rd_cnt == 16'd3)begin
cmd_flag<=  1'b1;
    end
    else if(rd_cnt == rd_data_len)begin
cmd_flag<=  1'b0;
    end
end
assign  cmd_data   =   usb_data ;  //將cmd_flag與cmd_data配合使用                                   
//cnt
always @(posedgeclk or negedgerst_n)begin
    if(!rst_n)begin
cnt<= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
cnt<= 0;
        else
cnt<= cnt + 1;
    end
    else begin
cnt<= 0;
    end
end
assign  add_cnt     =       state_c==WRITE;      
assign  end_cnt     =       add_cnt&&cnt == 4096-1;   //測試用的計數數據
//wr_trig
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
wr_trig<=  1'b0;
    end
    else if(cmd_flag&&cmd_data == 32'h11111111)begin
wr_trig<=  1'b1;
    end
    //else if(slwr == 1'b0)begin //開始寫的時候,將wr_trig拉低   
      //  wr_trig<=  1'b0;
    //end
end
//fifo 讀請求
regfifo_rdeq;
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
fifo_rdeq<=  1'b0;                
    end
    else if(flag_a )begin                
                fifo_rdeq<=  1'b1;        
    end
    else fifo_rdeq<= 1'b1;
end
//fifo 寫請求
regfifo_wdeq;
always  @(posedgeclk or negedgerst_n)begin
if(rst_n == 1'b0)begin
fifo_wdeq<=  1'b0;
    end
    else if(flag_c)begin
fifo_wdeq<=  1'b1;
    end
    else fifo_wdeq<= 1'b1;
end
//FIFO
fifo        fifo_inst (        
        .clock (clk),
        .data ( cnt ),
        .rdreq ( fifo_rdeq ),
        .wrreq ( fifo_wdeq ),
        .q ( usb_write_data )
        );
Endmodule

2.2. 明德?lián)P的signaltap教程及仿真驗證

       這里還得感謝明德?lián)P的signaltap教程,因為USB通信的數據線為32根,因此調試階段使用modelsim真的不太好用,所以根據明德?lián)P所講的signaltap教程,我很容易的實現(xiàn)了抓圖,分析出代碼問題,并且我自己的體會,signaltap真的就像現(xiàn)實的示波器啊!!!好處自己去鉆研吧。下面是抓圖,通過抓圖分析數據簡直不要太快!!

三. 結論

       

無論是FPGA初學者,還是已經工作的工程師,都推薦學習明德?lián)P的至簡設計法,一定會有大大的收獲。最后,祝福明德?lián)P越來越好,大道至簡,受益匪淺。愿桃李不言下自成蹊,終其教育,無外乎傳道授業(yè)解惑,古有孔丘弟三千,愿今師者百樹人。



   拓展閱讀
主站蜘蛛池模板: 精品日韩 | 亚洲一区二区免费在线观看 | 欧美黑人粗硬大在线看 | 国产丝袜脚| 六度国产福利午夜视频黄瓜视频 | 国产高清在线精品一区免费97 | 99视频在线观看视频一区 | 成人久久18免费网站入口 | 免费一级毛片在线播放不收费 | 亚洲四区 | 特黄特色大片免费视频大全 | 国产中文视频 | 欧美一级高清片欧美国产欧美 | 成人情趣视频无遮掩免费 | 免费观看爱爱视频 | 久久精品在线 | 在线观看免费播放网址成人 | 精品久久国产老人久久综合 | 毛片综合| 日本精品国产 | 黄色的毛片 | 全免费a级毛片免费看视频免 | 国产特黄特色的大片观看免费视频 | 亚洲成人三级 | 日本xxxx韩国护士 | 午夜国产精品理论片久久影院 | 俄罗斯小屁孩cao大人免费 | 黄视频网址 | 特黄特色大片免费高清视频 | 青青草社区 | aⅴ一区二区三区无卡无码 aⅴ在线免费观看 | 黄色在线播 | 国内精品福利视频 | 91黄视频| 亚洲网视频| 成人爱爱网站在线观看 | 一区二区视频在线观看免费的 | 国产精品久久久久久福利 | 久久99亚洲综合精品首页 | 国产欧美日韩综合精品一区二区 | 免费特级 |