본문 바로가기

FPGA/개발

[Simulation] AXI read write tasks

AXI (Advanced eXtensible Interface)란?

https://support.xilinx.com/s/article/1053914?language=en_US 

 

AXI Basics 1 - Introduction to AXI

Introduction These days, nearly every Xilinx IP uses an AXI Interface. Zynq® , Zynq MP, MicroBlaze™ and the new Versal™ Processors all use AXI interfaces. Thus AXI interfaces are part of nearly any new design on Xilinx devices. Understanding the basic

support.xilinx.com

 

 

Testbench 예제

Reference: JESD204C TX Example design testbench 내

 

s_axi와 연결

 

$display("Changing MB in EMB");
axi_write(TX_ADDR + CTRL_MB_IN_EMB , 32'd2);
axi_read(TX_ADDR + CTRL_MB_IN_EMB , register_val);

 

axi_write(RX_ADDR + CTRL_MB_IN_EMB , 32'd2);
axi_read(RX_ADDR + CTRL_MB_IN_EMB , register_val);

 

//---------------------------------------------------------------------------
  // AXI read write tasks
  //---------------------------------------------------------------------------
  // AXI-Lite Write task
  task axi_write;
    input [31:0] offset;
    input [31:0] data;
    reg   [31:0] addr;
    reg    [1:0] resp;
    begin
      // Use address as in datasheet
      addr = offset;
      // Drive Address & Data valid
      @(posedge SAXI_aclk);
      #1;
      SAXI_awaddr  = addr;
      SAXI_awvalid = 1;
      SAXI_wdata   = data;
      SAXI_wvalid  = 1;
      SAXI_bready  = 0;
      // Address Response Phase
      @(negedge SAXI_aclk);
      while (SAXI_awready == 1'b0)
        @(negedge SAXI_aclk);
      @(posedge SAXI_aclk);
      #1;
      SAXI_awaddr  = 0;
      SAXI_awvalid = 0;
      // Data Response Phase
      @(negedge SAXI_aclk);
      while (SAXI_wready == 1'b0)
        @(negedge SAXI_aclk);
      @(posedge SAXI_aclk);
      #1;
      SAXI_wdata   = 0;
      SAXI_wvalid  = 0;
      // BRESP phase
      @(negedge SAXI_aclk);
      while (SAXI_bvalid == 1'b0)
        @(negedge SAXI_aclk);
      @(posedge SAXI_aclk);
      resp = SAXI_bresp;
      if (resp != 0) $display ("Error AXI BRESP not equal 0");
      #1;
      SAXI_bready = 1;
      @(posedge SAXI_aclk);
      #1;
      SAXI_bready = 0;
    end
  endtask // axi_write

  // AXI-Lite Read task
  task axi_read;
    input  [31:0] offset;
    output [31:0] data;
    reg    [31:0] addr;
    reg     [1:0] resp;
    begin
      // Use address as in datasheet
      addr = offset;
      // Drive Address valid
      @(posedge SAXI_aclk);
      #1;
      SAXI_araddr  = addr;
      SAXI_arvalid = 1;
      SAXI_rready  = 0;
      // Address Response Phase
      @(negedge SAXI_aclk);
      while (SAXI_arready == 1'b0)
        @(negedge SAXI_aclk);
      @(posedge SAXI_aclk);
      #1;
      SAXI_araddr  = 0;
      SAXI_arvalid = 0;
      SAXI_rready  = 1;
      // Read Data Phase
      @(negedge SAXI_aclk);
      while (SAXI_rvalid == 1'b0)
        @(negedge SAXI_aclk);
      @(posedge SAXI_aclk);
      data = SAXI_rdata;
      resp = SAXI_rresp;
      if (resp != 0) $display ("Error AXI RRESP not equal 0");
      #1;
      SAXI_rready  = 0;
    end
  endtask // axi_read


[Task 사용 예]

 

//Base address assigned in IPI

localparam RX_ADDR               = 32'h44A10000 ;

 

initial begin

reg [31:0] register_val;

axi_read(RX_ADDR, register_val);
$display("* RX Core Version  = Major %d Minor %d Rev %d", register_val[31:24],  register_val[23:16],  register_val[15:8]);

end

[axi_read 동작]

모든 AXI의 동작은 aclk에 맞춰 진행이 된다.

// 주소를 쓰는 단계

1. aclk가 rising edge일 때 

SAXI_araddr에 값을 읽고자 하는 주소를 쓴다.

SAXI_arvalid = 1으로 만든다.

SAXI_rready = 0으로 만든다.

 

// 주소 응답 단계

2. aclk가 falling edge일 때

SAXI_arready가 1이될때까지 기다린다.

SAXI_arready가 1이 된다면 

 

 

3. aclk가 rising edge일 때

SAXI_araddr = 0으로 만든다.
SAXI_arvalid = 0으로 만든다.
SAXI_rready = 1으로 만든다.

 

// 데이터 읽기 단계

4. aclk가 falling edge일 때

SAXI_rvalidrk가 1이 될때까지 기다린다.

SAXI_rvalidrk가 1이 된다면 

 

5. aclk가 rising edge일 때

SAXI_rdata와 SAXI_rresp를 읽어가면 된다.