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



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

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

發布時間:2021-06-24   作者:admin 瀏覽量:

        

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


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


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


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


設計模板化:

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


思考步驟化:

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


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

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

二. USB3.0數據通信

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

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

信號
類型
位寬
意義
clk
輸入
1
時鐘信號
pclk_in
輸入
1
USB芯片復位信號
rst_n
輸入
1
復位信號,低電平有效
flag_a
輸入
1
USB芯片標志位,控制寫狀態
flag_b
輸入
1
USB芯片標志位,控制寫狀態
flag_c
輸入
1
USB芯片標志位,控制讀狀態
flag_d
輸入
1
USB芯片標志位,控制讀狀態
pclk
輸出
1
USB芯片復位信號
slcs
輸出
1
USB芯片片選信號
sloe
輸出
1
USB芯片控制信號
slrd
輸出
1
USB芯片讀狀態選擇信號
slwr
輸出
1
USB芯片寫狀態選擇信號
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                         ;//寫觸發
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. 明德揚的signaltap教程及仿真驗證

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

三. 結論

       

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



   拓展閱讀
主站蜘蛛池模板: 国产一级黄毛片 | 国产日韩欧美 | 在线播放免费人成毛片乱码 | 亚洲精品久久成人福利 | 亚洲欧美在线播放 | 免费观看性欧美毛片 | 国产成人在线小视频 | 小视频在线免费观看 | 高清国产精品入口麻豆 | 久久国产精品久久久久久小说 | 6969精品视频在线观看 | 俺去鲁婷婷六月色综合 | 911亚洲精品 | 国产高清精品自在久久 | 六月丁香深爱六月综合激情 | 免费国产成人高清在线观看视频 | 91中文字幕在线一区 | 成年美女毛片黄网站色奶头大全 | 国产精品久久久亚洲第一牛牛 | 国产精品免费视频网站 | 免费看国产做爰大片 | 亚洲性69影院在线观看 | 两性色午夜视频自由成熟的性 | 欧美一级专区免费大片俄罗斯 | 久久久久99 | 黄色一级小视频 | 亚洲国产美女 | 亚洲欧美日韩国产综合久 | 黄色生活片 | vr专区日韩精品中文字幕 | 免费看黄色毛片 | 亚洲一区在线免费 | 99久久免费国产香蕉麻豆 | 国产aaa毛片 | 国产久热美女福利视频 | 亚洲国产午夜精品乱码 | 国产精品1024永久观看 | 成人国产精品视频频 | 欧美特欧美特级一片 | 天天插综合网 | 在线精品免费观看综合 |