那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

SoC入門:APBmaster設計主站設計原理與實踐

ruikundianzi ? 來源:知乎 ? 2024-01-24 14:33 ? 次閱讀

大家不要以為APB的master和slave很簡單,不需要了解。這是大錯特錯,為什么呢?

不過設計什么模塊,你都要讓它掛在標準總線上,比如你設計DMA,你就同時需要了解AMBA的master和slave設計。又比如你是設計算法計算模塊,你的數據肯定要放到sram,你當然也要了解AMBA的master設計,將數據傳輸到crossbar上,進而放到指定memory。又比如SOC設計,肯定需要各種bridge,假設一個AHB2APB,你就同時需要了解AHB slave和APB master。

以APB為例,還是因為APB簡單,但是我們可以從它學到設計的方法和思路。

既然是設計就需要spec和狀態機。

設計spec如下

1、模塊規劃

5dfad054-ba6e-11ee-8b88-92fbcf53809c.jpg

模塊diagram

2、接口描述

5e0c910e-ba6e-11ee-8b88-92fbcf53809c.jpg

接口描述

3、時序描述

讀時序

5e32259a-ba6e-11ee-8b88-92fbcf53809c.jpg

讀時序

寫時序

5e4577c6-ba6e-11ee-8b88-92fbcf53809c.jpg

寫時序

4、FSM

就是之前講的APB協議狀態機。如下圖

5e5a7360-ba6e-11ee-8b88-92fbcf53809c.png

APB FSM

模塊規劃有了,接口有了,時序有了,狀態機有了,就可以開始設計coding了,代碼如下:

module apb
#(
  parameter RD_FLAG        = 8'b0           ,
  parameter WR_FLAG        = 8'b1           ,
  parameter CMD_RW_WIDTH   = 8              ,
  parameter CMD_ADDR_WIDTH = 16             ,
  parameter CMD_DATA_WIDTH = 32             ,
  parameter CMD_WIDTH      = CMD_RW_WIDTH   + 
                             CMD_ADDR_WIDTH + 
                             CMD_DATA_WIDTH
)(
//-- clkrst signal
  input                           pclk_i       ,
  input                           prst_n_i     ,


//-- cmd_in
  input      [CMD_WIDTH-1:0]      cmd_i        ,
  input                           cmd_vld_i    ,
  output reg [CMD_DATA_WIDTH-1:0] cmd_rd_data_o,


//-- apb interface
  output reg [CMD_ADDR_WIDTH-1:0] paddr_o      ,
  output reg                      pwrite_o     ,
  output reg                      psel_o       ,
  output reg                      penable_o    ,
  output reg [CMD_DATA_WIDTH-1:0] pwdata_o     ,
  input      [CMD_DATA_WIDTH-1:0] prdata_i     ,
  input                           pready_i     ,
  input                           pslverr_i
);


//-- FSM state
parameter IDLE   = 3'b001;
parameter SETUP  = 3'b010;
parameter ACCESS = 3'b100;


//-- current state and next state
reg [2:0] cur_state;
reg [2:0] nxt_state;


//-- data buf
reg                      start_flag     ;
reg [CMD_WIDTH-1:0]      cmd_in_buf     ;
reg [CMD_DATA_WIDTH-1:0] cmd_rd_data_buf;




/*-----------------------------------------------
 --             update cmd_in_buf              --
-----------------------------------------------*/
always @ (posedge pclk_i or negedge prst_n_i) begin
  if (!prst_n_i) begin
    cmd_in_buf <= {(CMD_WIDTH){1'b0}};
  end
  else if (cmd_vld_i && pready_i) begin
    cmd_in_buf <= cmd_i;
  end
end


/*-----------------------------------------------
 --             start flag of transfer         --
-----------------------------------------------*/
always @ (posedge pclk_i or negedge prst_n_i) begin
  if (!prst_n_i) begin
    start_flag <= 1'b0;
  end
  else if (cmd_vld_i && pready_i) begin
    start_flag <= 1'b1;
  end
  else begin
    start_flag <= 1'b0;
  end
end


/*-----------------------------------------------
 --           update current state             --
-----------------------------------------------*/
always @ (posedge pclk_i or negedge prst_n_i) begin
  if (!prst_n_i) begin
    cur_state <= IDLE;
  end
  else begin
    cur_state <= nxt_state;
  end
end


/*-----------------------------------------------
 --               update next state            --
-----------------------------------------------*/
always @ (*) begin
  case(cur_state)
    IDLE  :if(start_flag)begin
             nxt_state = SETUP;
           end
           else begin
             nxt_state = IDLE;
           end


    SETUP :nxt_state = ACCESS;
          
    ACCESS:if (!pready_i)begin
             nxt_state = ACCESS;
           end
           else if(start_flag)begin
             nxt_state = SETUP;
           end
           else if(!cmd_vld_i && pready_i)begin
             nxt_state = IDLE;
           end
  endcase
end


/*-----------------------------------------------
 --         update signal of output            --
-----------------------------------------------*/
always @ (posedge pclk_i or negedge prst_n_i) begin
  if (!prst_n_i) begin
    pwrite_o  <= 1'b0;
    psel_o    <= 1'b0;
    penable_o <= 1'b0;
    paddr_o   <= {(CMD_ADDR_WIDTH){1'b0}};
    pwdata_o  <= {(CMD_DATA_WIDTH){1'b0}};
  end
  
  else if (nxt_state == IDLE) begin
    psel_o    <= 1'b0;
    penable_o <= 1'b0;
  end


  else if(nxt_state == SETUP)begin
    psel_o    <= 1'b1;
    penable_o <= 1'b0;
    paddr_o   <= cmd_in_buf[CMD_WIDTH-CMD_RW_WIDTH-1:CMD_DATA_WIDTH];
    //-- read
    if(cmd_in_buf[CMD_WIDTH-1:CMD_WIDTH-8] == RD_FLAG)begin
      pwrite_o <= 1'b0;
    end
    //-- write
    else begin
      pwrite_o  <= 1'b1;
      pwdata_o  <= cmd_in_buf[CMD_DATA_WIDTH-1:0];
    end
  end


  else if(nxt_state == ACCESS)begin
    penable_o <= 1'b1;
  end
end


/*-----------------------------------------------
 --            update cmd_rd_data_buf          --
-----------------------------------------------*/
always @ (posedge pclk_i or negedge prst_n_i) begin
  if (!prst_n_i) begin
    cmd_rd_data_buf <= {(CMD_DATA_WIDTH){1'b0}};
  end
  else if (pready_i && psel_o && penable_o) begin
    cmd_rd_data_buf <= prdata_i;
  end
end


/*-----------------------------------------------
 --            update cmd_rd_data_o            --
-----------------------------------------------*/
always @ (posedge pclk_i or negedge prst_n_i) begin
  if (!prst_n_i) begin
    cmd_rd_data_o <= {(CMD_DATA_WIDTH){1'b0}};
  end
  else begin
    cmd_rd_data_o <= cmd_rd_data_buf;
  end
end


endmodule

模塊設計的比較簡單,只是實現APB的基本功能。下面講一下設計重點:

·一定要做好功課在開始coding。

·Flow control,APB的上級模塊,需要給到流控信號,告知APB master什么時候開始傳輸,什么時候結束。

·FSM,必須完全遵循AMBA的datasheet。

·時序對齊,和FSM一樣,接口時序要和APB協議對齊。

·重點中的重點,pready的反壓一定要逐級反壓,不能直接送到APB master的上次模塊,這樣會丟數據。

testbench如下

`timescale 1ns/1ns
module tb_apb;
  reg         pclk_i       ;
  reg         prst_n_i     ;
                          
  reg  [55:0] cmd_i        ;
  reg         cmd_vld_i    ;
  wire [31:0] cmd_rd_data_o;
                          
  wire [15:0] paddr_o      ;
  wire        pwrite_o     ;
  wire        psel_o       ;
  wire        penable_o    ;
  wire [31:0] pwdata_o     ;
  reg  [31:0] prdata_i     ;
  reg         pready_i     ;
  reg         pslverr_i    ;


initial begin
 // rst; 
  pclk_i   = 0;
  prst_n_i = 1;
  pslverr_i = 0;
  cmd_i = 56'b0;
  cmd_vld_i = 0;
  prdata_i = 32'b0;
  pready_i = 1;
  #20 prst_n_i = 0;
  #20 prst_n_i = 1;


 // cmd_in_wr(cmd_i,56'h01_FF_EE_DD_CC_BB_AA);
    cmd_i     = 56'h01_FF_EE_DD_CC_BB_AA;
    cmd_vld_i = 1   ;
    #20 cmd_vld_i = 0;
    #31 pready_i = 0;
    #80 pready_i = 1;


  #90;
  //cmd_in_rd(cmd_i,56'h00_AA_BB_CC_DD_EE_FF,prdata_i,32'h12_34_56_78);
    cmd_i = 56'h00_AA_BB_CC_DD_EE_FF;
    cmd_vld_i = 1;
    #20 cmd_vld_i = 0;
    #30 pready_i = 0;


    #60 pready_i = 1;
        prdata_i = 32'h12_34_56_78;


    cmd_i = 56'h00_AA_BB_CC_DD_EE_FF;
    cmd_vld_i = 1;
    #20 cmd_vld_i = 0;
    #30 pready_i = 0;


    #50 pready_i = 1;
        prdata_i = 32'h11_22_33_44;




end


always #10 pclk_i = ~pclk_i;


//-- RST
task rst;
  begin
    pclk_i   = 1;
    prst_n_i = 1;
    pslverr_i = 0;
    cmd_i = 56'b0;
    cmd_vld_i = 0;
    prdata_i = 32'b0;
    pready_i = 1;
    #20 prst_n_i = 0;
    #10 prst_n_i = 1;
    //cmd_i = 56'h01_FF_EE_DD_CC_BB_Ab;
  end
endtask


//-- write
task cmd_in_wr;
  output [55:0] cmd;
  input  [55:0] data;


  begin
    cmd     = data;
    cmd_vld_i = 1   ;
    #20 cmd_vld_i = 0;
    #20 pready_i = 0;
    #40 pready_i = 1;
  end
endtask


//-- read
task cmd_in_rd;
  output [55:0] cmd;
  input  [55:0] data ;
  output [31:0] prdata;
  input  [31:0] rd_data;


  begin
    cmd = data;
    cmd_vld_i = 1;
    #20 cmd_vld_i = 0;
    #20 pready_i = 0;
    #40 pready_i = 1;
        prdata = rd_data;
  end
endtask
initial begin
  #1000 $finish;
end
apb tb_apb(
            .pclk_i       (pclk_i       ),
            .prst_n_i     (prst_n_i     ),
            .cmd_i        (cmd_i        ),
            .cmd_vld_i    (cmd_vld_i    ),
            .cmd_rd_data_o(cmd_rd_data_o),
            .paddr_o      (paddr_o      ),
            .pwrite_o     (pwrite_o     ),
            .psel_o       (psel_o       ),
            .penable_o    (penable_o    ),
            .pwdata_o     (pwdata_o     ),
            .prdata_i     (prdata_i     ),
            .pready_i     (pready_i     ),
            .pslverr_i    (pslverr_i    )
          );




initial begin
  $fsdbDumpfile("apb.fsdb");
  $fsdbDumpvars            ;
  $fsdbDumpMDA             ;
end


endmodule

makefile如下:

LAB_DIR = /home/*/apb




DFILES = $(LAB_DIR)/*.v 


all:clean elab rung
elab:
  vcs -full64 -LDFLAGS -Wl,-no-as-needed -debug_acc+all -timescale=1ns/1ns 
  -fsdb -sverilog -l comp.log 
  ${DFILES}


run:
  ./simv -l run.log


rung:
  ./simv -gui -l run.log


verdi:
  verdi ${DFILES} 
  -ssf ./*.fsdb &


clean:
  rm -rf  AN.DB 
  rm -rf  DVEfiles 
  rm -rf  csrc 
  rm -rf  simv.* 
  rm -rf  *simv 
  rm -rf  inter.vpd 
  rm -rf  ucli.key 
  rm -rf  *.log 
  rm -rf  verdiLog 
  rm -rf  novas* 
rm-rf*.fsdb

下面是仿真結果

5e7808da-ba6e-11ee-8b88-92fbcf53809c.jpg

好了,今天講的主要就這么多,這個是基礎,但也是干貨,對以后設計AHB,AXI乃至NOC都非常有幫助。

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據傳輸
    +關注

    關注

    9

    文章

    1956

    瀏覽量

    64855
  • soc
    soc
    +關注

    關注

    38

    文章

    4204

    瀏覽量

    219103
  • 狀態機
    +關注

    關注

    2

    文章

    492

    瀏覽量

    27649

原文標題:SoC設計入門 - APB master設計(接口類基礎思維)

文章出處:【微信號:IP與SoC設計,微信公眾號:IP與SoC設計】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Modbus多問題

    ModbusRTU兩之間如何交互數據? 工業控制中,一般都是主從通訊方式居多,有時也會碰到兩個之間通訊。例如某工作站上位機(
    發表于 11-24 16:36

    PLC和從分享

    總站是主控制單元,含有CPU,從可以不加CPU,可以作為遠程,用控制。
    發表于 07-02 08:20

    CAN與從的功能是什么

    基于 STM32 和 CAN總線的溫度監控系統的設計,通過上位機與下位機的通信,實現對溫度數據的監控,并經初步實驗達到了設計的要求。1 系統總體方案概述系統總體框圖如圖 1 所示,本系統采用+從
    發表于 08-19 07:47

    PLC和從具有哪些功能

    PLC具有哪些功能?PLC從具有哪些功能?
    發表于 09-29 07:22

    通過Mbus給從發送信息,無法收到信息怎么解決?

    通過Mbus給從發送信息,無法收到信息怎么解決?
    發表于 01-20 06:42

    lightech mbus完整指令庫

    lightech mbus完整指令庫
    發表于 10-09 06:20

    Profibus-DP通信平臺的設計方案

    Profibus協議的結構以OSI為參考模型,DP使用第1層、第2層和用戶接口,第3層到第7層未加以描述。一個DP系統既可以是一個單結構,也可以是一個多結構,本文涉及的是多
    的頭像 發表于 12-30 10:04 ?6044次閱讀
    Profibus-DP<b class='flag-5'>主</b><b class='flag-5'>站</b>通信平臺的設計方案

    GitHub入門實踐

    GitHub入門實踐
    發表于 11-21 10:40 ?0次下載

    MELSEC iQ R CC Link系統/本地模塊用戶手冊(入門篇)

    MELSEC iQ-R CC-link系統/本地模塊用戶手冊(入門篇) 產品規格書
    發表于 08-25 09:30 ?0次下載
    MELSEC iQ R CC Link系統<b class='flag-5'>主</b><b class='flag-5'>站</b>/本地<b class='flag-5'>站</b>模塊用戶手冊(<b class='flag-5'>入門</b>篇)

    MELSEC iQ R AnyWireASlink模塊用戶手冊(入門篇)

    MELSEC iQ-R AnyWireASlink模塊用戶手冊(入門篇) 產品規格書
    發表于 08-26 15:26 ?0次下載
    MELSEC iQ R AnyWireASlink<b class='flag-5'>主</b><b class='flag-5'>站</b>模塊用戶手冊(<b class='flag-5'>入門</b>篇)

    MELSEC iQ R DeviceNet/從模塊用戶手冊(入門篇)

    MELSEC iQ-R DeviceNet /從模塊用戶手冊(入門篇) 產品規格書
    發表于 08-26 12:01 ?0次下載
    MELSEC iQ R DeviceNet<b class='flag-5'>主</b><b class='flag-5'>站</b>/從<b class='flag-5'>站</b>模塊用戶手冊(<b class='flag-5'>入門</b>篇)

    EtherCAT 方案橫向對比

    函數庫即可快速架構。 使用對象 強研發能力的團隊 ? 對成本考量不多,但對穩定性和售后服務看重的使用者。 ? 想快速入門EtherCAT的初學者; 驅動器廠商,想降低
    的頭像 發表于 04-25 16:01 ?2015次閱讀

    EtherCAT方案之橫向比較

    眾所周知,EtherCAT是開源協議,使用者可以根據倍福提供的相關資料做產品開發,而目前主流的EtherCAT解決方案包括:軟,系統型
    的頭像 發表于 05-29 09:38 ?4636次閱讀
    EtherCAT<b class='flag-5'>主</b><b class='flag-5'>站</b>方案之橫向比較

    linmodbus RTU程序

    linmodbus RTU 程序
    發表于 08-09 15:37 ?0次下載

    通過Profinet轉EtherCAT協議網關把profient從設備接入到EtherCAT設備中

    遠創智控YC-PNM-ECT,一款基于西門子1200PLC的PROFINET通訊網關。 遠創智控YC-PNM-ECT網關的主要功能是將ETHERCAT總線和PROFINET網絡連接起來。它
    的頭像 發表于 10-10 17:54 ?736次閱讀
    通過Profinet<b class='flag-5'>主</b><b class='flag-5'>站</b>轉EtherCAT協議網關把profient從<b class='flag-5'>站</b>設備接入到EtherCAT<b class='flag-5'>主</b><b class='flag-5'>站</b>設備中
    百家乐最保险的方法| 百家乐二人视频麻将| 百家乐隔一数打法| 功夫百家乐的玩法技巧和规则| 顶级赌场是真的吗| gt百家乐官网平台| 罗盘24山度数| 深圳太阳城酒店| 百家乐官网试玩活动| 大西洋百家乐官网的玩法技巧和规则 | 东阳市| 百家乐官网游戏| 大发888网上赌场官网| 百家乐官网算号软件| 百家乐官网破解版| 迪士尼百家乐的玩法技巧和规则| 定南县| 百家乐投注网站| 大发888游戏平台 df888ylcxz46 | 澳门玩百家乐00| 百家乐官网摇色子网站| 百家乐有不有作弊| 大发娱乐场下载| 机器百家乐官网作弊| 博彩百家乐字谜总汇| 浦江县| 百家乐视频聊天软件| 百家乐详解| 博狗百家乐真实| 沙龙国际网上| 我的做生意财位| 大连棋牌网| 盈得利百家乐官网娱乐城| 大发888娱乐充值| 百家乐官网噢门棋牌| 粤港澳百家乐娱乐网| 敖汉旗| 诚信百家乐平台| 上杭县| 新澳门百家乐娱乐城| 胜博国际娱乐城|