寄存器自動化配置通用案例


  本博文設計思想采用明德揚至簡設計法。之前都是通過一些完整的案例來分享設計心得,而這篇文章以需要配置多個寄存器的場景講述核心設計技巧。

  在設計案例時發現,經常會配置比較復雜的IP核或驅動一些接口進而操作外設。此時,為了讓外設或IP核正常工作,需要對其內部多個寄存器進行適當配置來保證在所需模式下正常工作。我們一般先設計接口模塊或IP核頂層文件,之后通過控制模塊按照先后順序自動給出所需指令,如讀寫等(下面的講述以只有讀寫指令為例)。接口模塊或IP核頂層模塊收到指令后完成相應的操作。

  第一個問題:如何實現多個寄存器且每個寄存器多個指令的自動化配置?

  我們可以在控制模塊中建立一個“配置表”,把讀寫指令以及相應的地址和待寫入數據保存其中,然后通過計數器進行指令掃描。這里需要兩級計數器,第一級計數一個寄存器的指令數,第二級計數器記錄已經操作過的寄存器個數。配置表以always組合邏輯中case語句塊形式給出,使用寄存器計數值區分不同寄存器。區分出待操作寄存器后根據操作計數器解析出讀寫指令。

  第二個問題:當控制模塊給出指令時,接口模塊或IP核一定能有時間響應么?

  這是我們設計時需要深思熟慮的問題:如何才能保證給出的指令一定會被下一模塊有效地響應?為了實現這一目的,可以在控制(配置)模塊和時序接口模塊或IP核頂層模塊之間放置一個接口銜接模塊,結構如下:

  根據上述需求定義銜接模塊功能:在下游模塊准備好后才讓上游模塊ctrl給出下一命令,否則等待。並完成讀出的有效數據送到上游模塊的任務。很簡單,下游模塊輸出給控制模塊一個信號rdy,當它為高電平時代表當前沒有指令或者上一指令已響應完成。控制模塊中指令計數器的原有計數條件和rdy==1條件邏輯與就完成了上述功能。這里需要特別注意的是:rdy信號必須以組合邏輯形式給出,否則由於rdy信號晚一拍輸出,上游模塊會出現誤認情況。核心代碼如下:

控制模塊中:

 1     //讀寫操作計數器    
 2      always  @(posedge clk or negedge rst_n)begin
 3         if(rst_n==1'b0)begin
 4             rw_cnt <= 0;
 5         end
 6         else if(add_rw_cnt) begin
 7             if(end_rw_cnt)
 8                 rw_cnt <= 0;
 9             else
10                 rw_cnt <= rw_cnt + 1;
11         end
12     end
13 
14     assign  add_rw_cnt = con_flag && rdy;
15     assign  end_rw_cnt = add_rw_cnt && rw_cnt==RW_NUM-1;    
16 
17    //寫使能 wr_flag和rd_flag由配置表給出
18     always  @(posedge clk or negedge rst_n)begin
19         if(rst_n==1'b0)begin
20             wr_en <= 1'b0;
21         end
22         else if(add_rw_cnt && rw_cnt==0 && wr_flag)begin
23             wr_en <= 1'b1;
24         end
25         else begin
26             wr_en <= 1'b0;
27         end
28     end
29 
30    //讀使能
31     always  @(posedge clk or negedge rst_n)begin
32         if(rst_n==1'b0)begin
33             rd_en <= 1'b0;
34         end
35         else if(add_rw_cnt && rw_cnt==1 && rd_flag)begin
36             rd_en <= 1'b1;
37         end
38         else begin
39             rd_en <= 1'b0;
40         end
41     end

 銜接模塊中:

 1     //空閑輸出
 2     always@(*)begin
 3         if(rd_en || wr_en || rd_com || wr_com)
 4             rdy <= 0;
 5         else 
 6             rdy <= 1;
 7     end
 8     
 9     //命令區間標志位 表示正在響應該命令  狀態機實現時序接口模塊情況
10     always@(posedge clk or negedge rst_n)begin
11         if(!rst_n)
12             wr_com <= 0;
13         else if(wr_en)
14             wr_com <= 1;
15         else if(wr_com && stop2idle)
16             wr_com <= 0;
17     end    
18     
19     always@(posedge clk or negedge rst_n)begin
20         if(!rst_n)
21             rd_com <= 0;
22         else if(rd_en)
23             rd_com <= 1;
24         else if(rd_com && stop2idle)
25             rd_com <= 0;
26     end    
27     
28     //地址更新
29     always@(posedge clk or negedge rst_n)begin
30         if(!rst_n)
31             addr_tmp <= 0;
32         else if(wr_en || rd_en)
33             addr_tmp <= addr;
34     end

   到此,寄存器自動化配置中兩個重點問題已然解決。本文是我在設計攝像頭圖像采集和以太網兩個案例過程中總結所得。本人認為這種設計思想非常具有通用性,並不僅僅局限於這兩個案例,因此單獨提出,以備今后回顧和重用。

 


免責聲明!

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



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