본문 바로가기
Digital Design/SoC

[AMBA] AXI Protocol 설계(Verilog) - ① Signal Descriptions

by 스테고사우르스 2023. 2. 24.

이번에는 Verilog로 AXI Protocol의 동작을 확인해보려고 합니다.

ARM사의 AMBA AXI datasheet를 참고했습니다.

 


AXI는 말 그대로 Interface이기 때문에 실체라고 할게 딱히 없습니다.

 

Master와 Slave를 연결하는 Bus의 규격을 ARM에서 정해놓은 것인데요,

저와 같은 학부생들은 Master와 Slave를 구하기 어렵습니다.

 

BFM(Bus Functional Model)을 짜서 Bus의 동작을 시뮬레이션해도 되지만

그건 조금 어려워서 아직 공부 중 입니다.

그래서 제멋대로 AXI Slave를 Verilog로 짜보겠습니다.

목적은 오로지 AMBA를 복습하고 기능을 직접 확인해보기 위함입니다!

 

오늘은 Master가 전송하는 신호를 Testbench에서 직접 넣어주도록 하겠습니다.

Slave는 임의로 delay를 주는 방식을 이용해 간단하게 만들어보겠습니다.

물론 합성은 불가능합니다.

 

I/O Signal이 담긴 Block Diagram 입니다.

 


Block Diagram

  • Write Address Channel

 

  • Write Data Channel

 

  • Write Response Channel

 

  • Read Address Channel

 

  • Read Response Channel

 

AXI는 5개의 독립된 channel을 가지고 있습니다.

그래서 5개를 나눠서 표시하였습니다.

 

Slave 안에 memory를 할당해주어서 데이터를 읽고 쓰도록 설계할 예정입니다.

 


Verilog Code

Clock

    input i_clk,
    input i_resetn,

 

Write Address Channel

    input                   [3:0]           i_awid,
    input                   [7:0]           i_awaddr,
    input                   [3:0]           i_awlen,
    input                   [2:0]           i_awsize,
    input                   [1:0]           i_awburst,
    input                                   i_awvalid,
    
    output   reg                            o_awready,

 

Write Data Channel

    input                   [3:0]           i_wid,
    input                  [15:0]           i_wdata,
    input                                   i_wlast,
    input                                   i_wvalid,
    
    output   reg                            o_wready,

 

Write Response Channel

    input                                   i_bready,
    
    output   reg            [3:0]           o_bid,
    output   reg            [1:0]           o_bresp,
    output   reg                            o_bvalid,

 

Read Address Channel

    input                   [3:0]           i_arid,
    input                   [7:0]           i_araddr,
    input                   [3:0]           i_arlen,
    input                   [2:0]           i_arsize,
    input                   [1:0]           i_arburst,
    input                                   i_arvalid,
    
    output   reg                            o_arready,

 

Read Data Channel

    input                                   i_rready,
    
    output   reg            [3:0]           o_rid,
    output   reg           [15:0]           o_rdata,
    output   reg                            o_rlast,
    output   reg                            o_rvalid,
    output   reg            [1:0]           o_rresp,

 

Test용 Signal

    input                                   test_awready,
    input                                   test_wready,
    input                    [1:0]          test_bresp,
    input                                   test_arready

여기 신호들은 Slave의 동작을 위한 것 입니다.

임의로 만든 Slave는 별 다른 기능을 하지 않기 때문에 항상 ready 상태입니다.

handshake를 확인하기 위해 ready와 busy 상태를 번갈아가며 사용하였습니다.

 

 

Register

    reg                     [7:0]           r_waddr;
    reg                     [3:0]           r_wburstn;
    reg                    [15:0]           r_wdata;
    reg                                     r_wlast;
    
    reg                                     r_waddr_on;
    reg                                     r_wdata_on;
    reg                     [4:0]           awlen_cnt;
    
    reg [15:0] mem [0:15];

여기 보이는 레지스터들은 handshake가 되었을 때,

Master에서 받은 신호를 저장할 곳 입니다.

지금은 하나씩만 만들었는데 FIFO 등을 이용해 여러 값을 보관할 수 있습니다.

메모리는 시뮬레이션을 편하게 보려고 작게 만들었습니다.

 

 

Wire

    wire      aw_handshake  =  i_awvalid && o_awready;
    wire       w_handshake  =  i_wvalid && o_wready;
    wire       b_handshake  =  i_bready && o_bvalid;
    wire      ar_handshake  =  i_arvalid && o_arready;
    wire       r_handshake  =  i_rready && o_rvalid;

wire로 handshake 구간을 표시해두면 waveform에서 더 빠르게 찾아 볼 수 있습니다.

 


 

댓글