lab3:LeNet上板


0.模型訓練:暫時跳過

  CNN有監督,可以用BP訓練:http://www.mamicode.com/info-detail-2288678.html

1.參數:

1.1一開始混亂的點

  (1)每個核有一個bias,每個核出一個通道的結果(一個特征)。

  (2)fcweight1:500行;fcweight1:10行;

  (3)一組核:所求特征(輸出)由多個子特征(輸入)組成,每個子特征有一個核

1.2過程  

  (1)卷積一:輸入28*28,20個核(5*5)20個bias(1*20),輸出20通道24*24,算步長:28=5+(24-1)*步長,所以步長=1;

  (2)卷積一池化:每2*2選一個最大值,無重合,規模橫縱減半;

  (3)卷積二:輸入20通道12*12,20*50個核(50組核,一組核對應一個bias,得一個通道結果)(每個通道輸入*對應組對應通道的核),50個bias,輸出50通道8*8,12=5+7*1,步長=1;

  (4)卷積二池化:減半

  (5)全連接層一:輸入50通道4*4,展開1*800,映射到1*500(全連接->每個輸入都要乘weightN+biasN=iN,所以有500*800個參數,500個bias,:(500*800)* (800*1)=(500*1)+bias(500*1)

  (6)全連接層一過濾:輸入1*500,負數取正,輸出1*500

  (7)全連接層二:輸入1*500,輸出1*10:(10*500)*(500*1)=10*1+bias(10*1)

  (8)輸出:找到1*10向量中最大值,輸出下標為識別結果

 weight=20*25+20*50*25+500*800+10*500=500+25000+400000+5000=430500 開440000空間

bias=20+50+500+10=580 開600

2.設計:看指導書

數據通路不要和控制寫一起,控制單獨寫狀態機!

(1)定點數問題:

  參數和數據處理:轉為8位二進制數(有符號,參數有負數)。運算后要移位?

  教程:https://jingyan.baidu.com/article/f71d6037b3b43f1ab641d10d.html

  處理成1符號+2整數+5小數,相當於一個數放大了2^5倍

  原始數據*32=輸入數據,還要看數據會不會溢出(大於3)

 

錯誤和經驗:

1.clock design生成.v文件后,再把里面的模塊設成top,單獨寫仿真或綜合時是找不到這個模塊的,要把block design生成的.v文件刪了之后才能找到。。。但是重啟vivado后又可以直接改top了?妙

2.lia:https://blog.csdn.net/qq_34322603/article/details/72854621:

然后常規方法進入軟件調試界面,設置斷點。(這里提醒一下,聯合調試一定要在SDK下將比特流下載到FPGA中,而不要在vivado中下載比特流。Xilinx官方給出的解釋是:由於使用PS端的時鍾來接入ILA,所以要現在SDK中將比特流進行下載) 

3.verliog:一個信號只能有一個驅動,多個改變位置要加選擇器。

4.加完debug后布線報錯:

[Chipscope 16-213] The debug port 'dbg_hub/clk' has 1 unconnected channels (bits). This will cause errors during implementation.

原因:綜合之后沒有選debug的設置,有的線還沒有連時鍾。給clk加debug好像有個buff報錯解決不了,就把clk的debug刪了

5.lia的wave出不來:要用sdk燒一遍才行。先用vivado 的hardware燒板子作為啟動,然后用sdk燒,就能彈出來了。

6.#include "xil_io.h"報錯:clean一遍編譯

7.ila的wave圖點運行就走一點點:一次只能抓1000個,要選好時間。令人做藕

8.初始化的使能是必須加的,因為pl初始化好了之后ps可能還沒開始傳東西。。。要用axi-lite告訴初始化模塊我要開始傳有效數據了。

9.可以直接在netlist里面mark debug,要是寫(**)沒加進去的話

選上線右鍵mark debug就行。

10.ila彈不出來:用sdk導完之后再用vivado燒一次就有了。

 11.我放棄了,我還是寫仿真測吧。上板子弄單元測試太麻煩了。而且我發現wrapper會自動生成一個仿真文件。。。可以先不加系統,把輸入輸出都引出來然后寫仿真,最后再把輸入輸出都換成axi。我愛中間輸出。

12.用自帶的wrapper的test,改block的代碼的話,要重新生成一邊wrapper。但是生成完之后自己加的測試代碼也沒有了。所以還是手動搭一個吧,可以把自動的那個文件頂層粘過去

13.我愛子狀態機。for循環拆成狀態機:每個條件判斷一個狀態,執行內容一個狀態,跟編譯插標簽似的

每層:判斷本層邊界,符合則初始化下一層計數,跳出則上層計數加一

14.系統命令錯誤:參數不存在等,准確錯誤報不出來,形如下圖就是$display后面參數不存在的報錯

 15.XXX右移還是XXX

16.綜合時不自動保存,綜合前一定要把文件都保存了。

 

狀態機套路 以cov為例

將for循環改寫,每個循環變量拆分成以下子狀態:

父狀態:循環變量初始化

判條件,轉移

在葉節點自加(不能在當前狀態自加,因為后面可能還要用i的當前值)

always@(posedge clk)begin
        case(s1)
        0:
        begin
            if(state==1||state==3)begin
                s1<=1;
                s1_cha_count<=0;
                cov_en<=0;
                //若復用,需要初始化計數
            end
        end
        1://讀1個通道bias,開始計數
        begin
            //計數:如果>1,finish
            //讀入bias
            if(s1_cha_count>=s1_cha_num) s1<=7;
            else begin
                read_bias<=1;
                read_bias_finish<=0;
                s1<=10;
                s1_wei_count<=0;
            end
        end
        10://等待讀bias
        begin
            if(read_bias_finish==1)begin
                s1<=2;
            end
        end
        2://每個通道,讀20個weight矩陣
        begin
            //計數,若為21轉到1
            if(s1_wei_count>=s1_wei_num)begin
                s1<=1;
                s1_cha_count<=s1_cha_count+1;
            end
            else begin
                read_weight<=1;
                read_weight_finish<=0;
                s1<=8;
                s1_i<=0;
            end
        end
        8://等待讀weight
        begin
            if(read_weight_finish==1)begin
                s1<=3;
            end
        end
        3://讀從data讀i行
        begin
            //計數,如果行數>24,跳到2,否則到4
            if(s1_i>=s1_result_num)begin
                s1<=2;
                s1_wei_count<=s1_wei_count+1;
            end
            else begin
                s1<=4;
                s1_j<=0;
            end
        end
        4://列計數
        begin
            ans_wen<=0;
            //列計數,如果列數>24,跳到3,否則到5
            if(s1_j>=s1_result_num) begin
                s1<=3;
                s1_i<=s1_i+1;
            end
            else begin
                s1<=5;
            end
        end
        5://執行體
        begin
            read_data<=1;//子模塊讀完后置0
            read_data_finish<=0;
            s1<=9;
        end
        9://等讀data
        begin
            if(read_data_finish==1)begin
                s1<=6;
                cov_en<=1;
            end
        end
        6://等待計算結果寫回
        begin
            //寫回,跳到4
            if(COVFINISH==1)begin//測試,待改正COVFINISH==1
                //寫回,待
                s1<=4;
                s1_j<=s1_j+1;
                ans_addr<=s1_cha_count*s1_wei_num*s1_result_num*s1_result_num
                                +s1_wei_count*s1_result_num*s1_result_num
                                +s1_result_num*s1_i
                                +s1_j;
                ans_in<=COVRESULT;
                ans_wen<=1;
                $display("cov%d channel=%d weight=%d i=%d j=%d result=%d addr=%d",state,s1_cha_count,s1_wei_count,s1_i,s1_j,COVRESULT,s1_cha_count*s1_wei_num*s1_result_num*s1_result_num
                                +s1_wei_count*s1_result_num*s1_result_num
                                +s1_result_num*s1_i
                                +s1_j);
            end
            
        end
        7://結束狀態,置finish為1
        begin
            finish<=1;
            s1<=0;
        end
        default:;
        endcase
    end

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM