AXI-Lite Verilog code 해석

SungchulCHA·2024년 4월 25일
0

Vivado

목록 보기
5/6

Verilog code


`timescale 1 ns / 1 ps

	module my_multiplier_v1_0_S00_AXI #
	(
		// Users to add parameters here

		// User parameters ends
		// Do not modify the parameters beyond this line

		// Width of S_AXI data bus
		parameter integer C_S_AXI_DATA_WIDTH	= 32,
		// Width of S_AXI address bus
		parameter integer C_S_AXI_ADDR_WIDTH	= 4
	)
	(
		// Users to add ports here

		// User ports ends
		// Do not modify the ports beyond this line

		// Global Clock Signal
		input wire  S_AXI_ACLK,
		// Global Reset Signal. This Signal is Active LOW
		input wire  S_AXI_ARESETN,
		// Write address (issued by master, acceped by Slave)
		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
		// Write channel Protection type. This signal indicates the
    		// privilege and security level of the transaction, and whether
    		// the transaction is a data access or an instruction access.
		input wire [2 : 0] S_AXI_AWPROT,
		// Write address valid. This signal indicates that the master signaling
    		// valid write address and control information.
		input wire  S_AXI_AWVALID,
		// Write address ready. This signal indicates that the slave is ready
    		// to accept an address and associated control signals.
		output wire  S_AXI_AWREADY,
		// Write data (issued by master, acceped by Slave) 
		input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
		// Write strobes. This signal indicates which byte lanes hold
    		// valid data. There is one write strobe bit for each eight
    		// bits of the write data bus.    
		input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
		// Write valid. This signal indicates that valid write
    		// data and strobes are available.
		input wire  S_AXI_WVALID,
		// Write ready. This signal indicates that the slave
    		// can accept the write data.
		output wire  S_AXI_WREADY,
		// Write response. This signal indicates the status
    		// of the write transaction.
		output wire [1 : 0] S_AXI_BRESP,
		// Write response valid. This signal indicates that the channel
    		// is signaling a valid write response.
		output wire  S_AXI_BVALID,
		// Response ready. This signal indicates that the master
    		// can accept a write response.
		input wire  S_AXI_BREADY,
		// Read address (issued by master, acceped by Slave)
		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
		// Protection type. This signal indicates the privilege
    		// and security level of the transaction, and whether the
    		// transaction is a data access or an instruction access.
		input wire [2 : 0] S_AXI_ARPROT,
		// Read address valid. This signal indicates that the channel
    		// is signaling valid read address and control information.
		input wire  S_AXI_ARVALID,
		// Read address ready. This signal indicates that the slave is
    		// ready to accept an address and associated control signals.
		output wire  S_AXI_ARREADY,
		// Read data (issued by slave)
		output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
		// Read response. This signal indicates the status of the
    		// read transfer.
		output wire [1 : 0] S_AXI_RRESP,
		// Read valid. This signal indicates that the channel is
    		// signaling the required read data.
		output wire  S_AXI_RVALID,
		// Read ready. This signal indicates that the master can
    		// accept the read data and response information.
		input wire  S_AXI_RREADY
	);

	// AXI4LITE signals
	reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr;
	reg  	axi_awready;
	reg  	axi_wready;
	reg [1 : 0] 	axi_bresp;
	reg  	axi_bvalid;
	reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr;
	reg  	axi_arready;
	reg [C_S_AXI_DATA_WIDTH-1 : 0] 	axi_rdata;
	reg [1 : 0] 	axi_rresp;
	reg  	axi_rvalid;

	// Example-specific design signals
	// local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
	// ADDR_LSB is used for addressing 32/64 bit registers/memories
	// ADDR_LSB = 2 for 32 bits (n downto 2)
	// ADDR_LSB = 3 for 64 bits (n downto 3)
	localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
	localparam integer OPT_MEM_ADDR_BITS = 1;
	//----------------------------------------------
	//-- Signals for user logic register space example
	//------------------------------------------------
	//-- Number of Slave Registers 4
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg0;
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg1;
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg2;
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg3;
	wire	 slv_reg_rden;
	wire	 slv_reg_wren;
	reg [C_S_AXI_DATA_WIDTH-1:0]	 reg_data_out;
	integer	 byte_index;
	reg	 aw_en;

	// I/O Connections assignments

	assign S_AXI_AWREADY	= axi_awready;
	assign S_AXI_WREADY	= axi_wready;
	assign S_AXI_BRESP	= axi_bresp;
	assign S_AXI_BVALID	= axi_bvalid;
	assign S_AXI_ARREADY	= axi_arready;
	assign S_AXI_RDATA	= axi_rdata;
	assign S_AXI_RRESP	= axi_rresp;
	assign S_AXI_RVALID	= axi_rvalid;
	// Implement axi_awready generation
	// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
	// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
	// de-asserted when reset is low.

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_awready <= 1'b0;
	      aw_en <= 1'b1;
	    end 
	  else
	    begin    
	      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
	        begin
	          // slave is ready to accept write address when 
	          // there is a valid write address and write data
	          // on the write address and data bus. This design 
	          // expects no outstanding transactions. 
	          axi_awready <= 1'b1;
	          aw_en <= 1'b0;
	        end
	        else if (S_AXI_BREADY && axi_bvalid)
	            begin
	              aw_en <= 1'b1;
	              axi_awready <= 1'b0;
	            end
	      else           
	        begin
	          axi_awready <= 1'b0;
	        end
	    end 
	end       

	// Implement axi_awaddr latching
	// This process is used to latch the address when both 
	// S_AXI_AWVALID and S_AXI_WVALID are valid. 

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_awaddr <= 0;
	    end 
	  else
	    begin    
	      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
	        begin
	          // Write Address latching 
	          axi_awaddr <= S_AXI_AWADDR;
	        end
	    end 
	end       

	// Implement axi_wready generation
	// axi_wready is asserted for one S_AXI_ACLK clock cycle when both
	// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is 
	// de-asserted when reset is low. 

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_wready <= 1'b0;
	    end 
	  else
	    begin    
	      if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
	        begin
	          // slave is ready to accept write data when 
	          // there is a valid write address and write data
	          // on the write address and data bus. This design 
	          // expects no outstanding transactions. 
	          axi_wready <= 1'b1;
	        end
	      else
	        begin
	          axi_wready <= 1'b0;
	        end
	    end 
	end       

	// Implement memory mapped register select and write logic generation
	// The write data is accepted and written to memory mapped registers when
	// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
	// select byte enables of slave registers while writing.
	// These registers are cleared when reset (active low) is applied.
	// Slave register write enable is asserted when valid address and data are available
	// and the slave is ready to accept the write address and write data.
	assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      slv_reg0 <= 0;
	      slv_reg1 <= 0;
	      slv_reg2 <= 0;
	      slv_reg3 <= 0;
	    end 
	  else begin
	    if (slv_reg_wren)
	      begin
	        case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	          2'h0:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 0
	                slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          2'h1:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 1
	                slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          2'h2:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 2
	                slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          2'h3:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 3
	                slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          default : begin
	                      slv_reg0 <= slv_reg0;
	                      slv_reg1 <= slv_reg1;
	                      slv_reg2 <= slv_reg2;
	                      slv_reg3 <= slv_reg3;
	                    end
	        endcase
	      end
	  end
	end    

	// Implement write response logic generation
	// The write response and response valid signals are asserted by the slave 
	// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.  
	// This marks the acceptance of address and indicates the status of 
	// write transaction.

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_bvalid  <= 0;
	      axi_bresp   <= 2'b0;
	    end 
	  else
	    begin    
	      if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
	        begin
	          // indicates a valid write response is available
	          axi_bvalid <= 1'b1;
	          axi_bresp  <= 2'b0; // 'OKAY' response 
	        end                   // work error responses in future
	      else
	        begin
	          if (S_AXI_BREADY && axi_bvalid) 
	            //check if bready is asserted while bvalid is high) 
	            //(there is a possibility that bready is always asserted high)   
	            begin
	              axi_bvalid <= 1'b0; 
	            end  
	        end
	    end
	end   

	// Implement axi_arready generation
	// axi_arready is asserted for one S_AXI_ACLK clock cycle when
	// S_AXI_ARVALID is asserted. axi_awready is 
	// de-asserted when reset (active low) is asserted. 
	// The read address is also latched when S_AXI_ARVALID is 
	// asserted. axi_araddr is reset to zero on reset assertion.

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_arready <= 1'b0;
	      axi_araddr  <= 32'b0;
	    end 
	  else
	    begin    
	      if (~axi_arready && S_AXI_ARVALID)
	        begin
	          // indicates that the slave has acceped the valid read address
	          axi_arready <= 1'b1;
	          // Read address latching
	          axi_araddr  <= S_AXI_ARADDR;
	        end
	      else
	        begin
	          axi_arready <= 1'b0;
	        end
	    end 
	end       

	// Implement axi_arvalid generation
	// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both 
	// S_AXI_ARVALID and axi_arready are asserted. The slave registers 
	// data are available on the axi_rdata bus at this instance. The 
	// assertion of axi_rvalid marks the validity of read data on the 
	// bus and axi_rresp indicates the status of read transaction.axi_rvalid 
	// is deasserted on reset (active low). axi_rresp and axi_rdata are 
	// cleared to zero on reset (active low).  
	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_rvalid <= 0;
	      axi_rresp  <= 0;
	    end 
	  else
	    begin    
	      if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
	        begin
	          // Valid read data is available at the read data bus
	          axi_rvalid <= 1'b1;
	          axi_rresp  <= 2'b0; // 'OKAY' response
	        end   
	      else if (axi_rvalid && S_AXI_RREADY)
	        begin
	          // Read data is accepted by the master
	          axi_rvalid <= 1'b0;
	        end                
	    end
	end    

	// Implement memory mapped register select and read logic generation
	// Slave register read enable is asserted when valid address is available
	// and the slave is ready to accept the read address.
	assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
	always @(*)
	begin
	      // Address decoding for reading registers
	      case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	        2'h0   : reg_data_out <= slv_reg0;
	        2'h1   : reg_data_out <= multiplier_out;
	        2'h2   : reg_data_out <= slv_reg2;
	        2'h3   : reg_data_out <= slv_reg3;
	        default : reg_data_out <= 0;
	      endcase
	end

	// Output register or memory read data
	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_rdata  <= 0;
	    end 
	  else
	    begin    
	      // When there is a valid read address (S_AXI_ARVALID) with 
	      // acceptance of read address by the slave (axi_arready), 
	      // output the read dada 
	      if (slv_reg_rden)
	        begin
	          axi_rdata <= reg_data_out;     // register read data
	        end   
	    end
	end    

	// Add user logic here
    reg [31:0] multiplier_out;
    always @ (posedge S_AXI_ACLK)
    begin
        if ( S_AXI_ARESETN == 1'b0 )
	      multiplier_out  <= 0;
	    else
	      multiplier_out <= slv_reg0[31:16] * slv_reg0[15:0];
    end
	// User logic ends

	endmodule

localparam

// Example-specific design signals
// local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
// ADDR_LSB is used for addressing 32/64 bit registers/memories
// ADDR_LSB = 2 for 32 bits (n downto 2)
// ADDR_LSB = 3 for 64 bits (n downto 3)
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer OPT_MEM_ADDR_BITS = 1;

ADDR_LSB는 AXI4-Lite 인터페이스에서 32비트 또는 64비트 레지스터/메모리를 주소 지정하는 데 사용됩니다.

ADDR_LSB의 값은 C_S_AXI_DATA_WIDTH/32에 1을 더한 값으로 설정됩니다.
C_S_AXI_DATA_WIDTH는 데이터의 너비를 정의하는 매개변수입니다. 따라서 ADDR_LSB의 값은 데이터 너비가 32비트인 경우 2, 64비트인 경우 3이 됩니다.

이렇게 설정된 ADDR_LSB 값은 주소 지정 시 사용되며, 주소의 하위 비트(n downto ADDR_LSB)를 지정하는 데 사용됩니다.
이는 AXI4-Lite 인터페이스에서 데이터 전송 시, 32비트 또는 64비트 단위로 데이터를 주소 지정하고 전송하는 데 필요한 정보를 제공합니다.

OPT_MEM_ADDR_BITS는 메모리 주소 지정에 사용되는 비트 수를 정의합니다.

이 파라미터의 값이 1로 설정되어 있습니다. 이는 메모리 주소를 지정하는 데 1비트가 사용된다는 것을 의미합니다. 이 값은 메모리의 크기나 구조에 따라 변경될 수 있습니다.
따라서 OPT_MEM_ADDR_BITS 파라미터는 메모리 주소 지정에 필요한 비트 수를 정의하는 중요한 역할을 합니다. 이 파라미터를 통해 메모리 주소 지정 방식을 쉽게 변경할 수 있습니다.


input, output signals

  • input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR : 마스터에 의해 발행되고 슬레이브에 의해 수락되는 쓰기 주소를 나타냅니다.

  • input wire [2 : 0] S_AXI_AWPROT : 트랜잭션의 권한 및 보안 수준을 나타내며, 트랜잭션이 데이터 액세스인지 명령 액세스인지를 나타냅니다.

  • input wire S_AXI_AWVALID : 마스터가 유효한 쓰기 주소와 제어 정보를 신호화하고 있음을 나타냅니다.

  • output wire S_AXI_AWREADY : 슬레이브가 주소 및 관련 제어 신호를 수락할 준비가 되었음을 나타냅니다.

  • input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA : 마스터에 의해 발행되고 슬레이브에 의해 수락되는 쓰기 데이터를 나타냅니다.

  • input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB : 어떤 바이트 레인이 유효한 데이터를 가지고 있는지를 나타냅니다. 쓰기 데이터 버스의 각 8비트에 대해 하나의 쓰기 스트로브 비트가 있습니다.

  • input wire S_AXI_WVALID : 유효한 쓰기 데이터와 스트로브가 사용 가능함을 나타냅니다.

  • output wire S_AXI_WREADY : 슬레이브가 쓰기 데이터를 수락할 수 있음을 나타냅니다.

  • output wire [1 : 0] S_AXI_BRESP : 쓰기 트랜잭션의 상태를 나타냅니다. 이는 2비트 신호로, 다음과 같은 값을 가질 수 있습니다:

    • 00 : OKAY - 트랜잭션이 성공적으로 완료되었습니다.
    • 01 : EXOKAY - 트랜잭션은 성공적으로 완료되었지만, 정보가 더 있을 수 있습니다.
    • 10 : SLVERR - 슬레이브 에러가 발생했습니다.
    • 11 : DECERR - 주소가 잘못되었거나, 슬레이브가 트랜잭션을 지원하지 않습니다.
  • output wire S_AXI_BVALID : 슬레이브가 유효한 쓰기 응답을 신호화하고 있음을 나타냅니다.

  • input wire S_AXI_BREADY : 마스터가 쓰기 응답을 수락할 수 있음을 나타냅니다.

  • input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR : 마스터에 의해 발행되고 슬레이브에 의해 수락되는 읽기 주소를 나타냅니다.

  • input wire [2 : 0] S_AXI_ARPROT : 트랜잭션의 권한 및 보안 수준을 나타내며, 트랜잭션이 데이터 액세스인지 명령 액세스인지를 나타냅니다.

  • input wire S_AXI_ARVALID : 채널이 유효한 읽기 주소와 제어 정보를 신호화하고 있음을 나타냅니다.

  • output wire S_AXI_ARREADY : 슬레이브가 주소 및 관련 제어 신호를 수락할 준비가 되었음을 나타냅니다.

  • output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA : 슬레이브에 의해 발행되는 읽기 데이터를 나타냅니다.

  • output wire [1 : 0] S_AXI_RRESP : 읽기 전송의 상태를 나타냅니다.

  • output wire S_AXI_RVALID : 채널이 필요한 읽기 데이터를 신호화하고 있음을 나타냅니다.

  • input wire S_AXI_RREADY : 마스터가 읽기 데이터와 응답 정보를 수락할 수 있음을 나타냅니다.


AXI4-Lite signals

  1. axi_awaddr

    axi_awaddr는 AXI4-Lite 인터페이스에서 쓰기 주소를 저장하는 데 사용됩니다.
    레지스터의 크기는 C_S_AXI_ADDR_WIDTH 비트로, 이는 AXI 주소 버스의 너비를 나타냅니다.

    마스터 디바이스가 데이터를 슬레이브 디바이스에 쓰기를 원할 때, 마스터는 axi_awaddr 레지스터에 쓰기를 원하는 주소를 설정합니다. 그런 다음 슬레이브 디바이스는 이 주소를 사용하여 적절한 위치에 데이터를 쓸 수 있습니다.

reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr;
// Implement axi_awaddr latching
// This process is used to latch the address when both 
// S_AXI_AWVALID and S_AXI_WVALID are valid. 

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_awaddr <= 0;
    end 
  else
    begin    
      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
        begin
          // Write Address latching 
          axi_awaddr <= S_AXI_AWADDR;
        end
    end 
end       

쓰기 주소(axi_awaddr)의 래치를 처리합니다.

~axi_awready : 이는 시스템이 새로운 쓰기 주소를 받아들일 준비가 되지 않았음을 확인합니다.
S_AXI_AWVALID : 이는 마스터가 유효한 쓰기 주소를 제공했음을 확인합니다.
S_AXI_WVALID : 이는 마스터가 유효한 쓰기 데이터를 제공했음을 확인합니다.
aw_en : 이는 주소 쓰기 작업을 활성화하는 제어 신호일 가능성이 있습니다.

이 모든 조건이 참인 경우, 쓰기 주소(axi_awaddr)는 입력 쓰기 주소 신호(S_AXI_AWADDR)에서 래치되거나 저장됩니다. 이는 시스템이 마스터에 의해 제공된 새로운 쓰기 주소를 받아들였으며 해당 주소에서 쓰기 작업을 수행할 준비가 되었다는 것을 의미합니다.

  1. axi_awready, aw_en

    axi_awready는 AXI4-Lite 인터페이스에서 쓰기 주소를 받아들일 준비가 되었음을 나타냅니다.

    axi_awready 신호가 활성화되면(즉, '1'로 설정되면), 슬레이브는 마스터로부터 쓰기 주소를 받아들일 준비가 되었음을 나타냅니다. 이는 마스터가 쓰기 주소(axi_awaddr)와 쓰기 유효 신호(S_AXI_AWVALID)를 제공할 수 있음을 의미합니다.

    반대로, axi_awready 신호가 비활성화되면(즉, '0'로 설정되면), 슬레이브는 쓰기 주소를 받아들일 준비가 되지 않았음을 나타냅니다. 이는 마스터가 쓰기 주소와 쓰기 유효 신호를 제공하는 것을 지연해야 함을 의미합니다.
    따라서 axi_awready 신호는 쓰기 주소의 준비 상태를 제어하는 데 중요한 역할을 합니다.

    aw_en는 주소 쓰기 작업을 활성화하는 데 사용되는 제어 레지스터

    aw_en 레지스터가 활성화되면(즉, '1'로 설정되면), 쓰기 주소(axi_awaddr)가 래치되고, axi_awready 신호가 '0'으로 설정됩니다. 이는 쓰기 주소가 유효하고 데이터가 준비되었음을 나타냅니다.

    반대로, aw_en 레지스터가 비활성화되면(즉, '0'로 설정되면), axi_awready 신호가 '1'으로 설정됩니다. 이는 쓰기 주소가 더 이상 유효하지 않음을 나타냅니다.
    따라서 aw_en 레지스터는 쓰기 주소의 유효성 및 준비 상태를 제어하는 데 중요한 역할을 합니다.

reg  	axi_awready;
reg aw_en;
assign S_AXI_AWREADY	= axi_awready;

// Implement axi_awready generation
// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
// de-asserted when reset is low.

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_awready <= 1'b0;
      aw_en <= 1'b1;
    end 
  else
    begin    
      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
        begin
          // slave is ready to accept write address when 
          // there is a valid write address and write data
          // on the write address and data bus. This design 
          // expects no outstanding transactions. 
          axi_awready <= 1'b1;
          aw_en <= 1'b0;
        end
        else if (S_AXI_BREADY && axi_bvalid)
            begin
              aw_en <= 1'b1;
              axi_awready <= 1'b0;
            end
      else           
        begin
          axi_awready <= 1'b0;
        end
    end 
end       

첫 번째 조건문은 axi_awready가 비활성화되어 있고, S_AXI_AWVALID, S_AXI_WVALID, aw_en 모두 활성화된 경우를 확인합니다. 이 경우, 슬레이브는 유효한 쓰기 주소와 쓰기 데이터가 존재할 때 쓰기 주소를 받아들일 준비가 되어 있다는 것을 나타냅니다. 이 디자인은 미해결 트랜잭션이 없다고 가정합니다. 이 경우, axi_awready는 1로 설정되고, aw_en은 0으로 설정됩니다.

두 번째 조건문은 S_AXI_BREADYaxi_bvalid가 모두 활성화된 경우를 확인합니다. 이 경우, aw_en은 1로 설정되고, axi_awready는 0으로 설정됩니다.

위의 두 조건문 모두 참이 아닌 경우, axi_awready는 0으로 설정됩니다.
이러한 방식으로, axi_awready 신호는 AXI4-Lite 인터페이스에서 쓰기 작업의 준비 상태를 나타내는 역할을 합니다.

  1. axi_wready

    axi_wready는 AXI4-Lite 인터페이스에서 쓰기 데이터를 받아들일 준비가 되었음을 나타냅니다.

    axi_wready 신호가 활성화되면(즉, '1'로 설정되면), 슬레이브는 마스터로부터 쓰기 데이터를 받아들일 준비가 되었음을 나타냅니다. 이는 마스터가 쓰기 데이터(S_AXI_WDATA)와 쓰기 유효 신호(S_AXI_WVALID)를 제공할 수 있음을 의미합니다.

    반대로, axi_wready 신호가 비활성화되면(즉, '0'로 설정되면), 슬레이브는 쓰기 데이터를 받아들일 준비가 되지 않았음을 나타냅니다. 이는 마스터가 쓰기 데이터와 쓰기 유효 신호를 제공하는 것을 지연해야 함을 의미합니다.
    따라서 axi_wready 신호는 쓰기 데이터의 준비 상태를 제어하는 데 중요한 역할을 합니다.

reg  	axi_wready;
assign S_AXI_WREADY	= axi_wready;

// Implement axi_wready generation
// axi_wready is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is 
// de-asserted when reset is low. 

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_wready <= 1'b0;
    end 
  else
    begin    
      if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
        begin
          // slave is ready to accept write data when 
          // there is a valid write address and write data
          // on the write address and data bus. This design 
          // expects no outstanding transactions. 
          axi_wready <= 1'b1;
        end
      else
        begin
          axi_wready <= 1'b0;
        end
    end 
end      

axi_wready가 비활성화되어 있고, S_AXI_WVALID, S_AXI_AWVALID, aw_en 모두 활성화된 경우를 확인합니다. 이 경우, 슬레이브는 유효한 쓰기 주소와 쓰기 데이터가 존재할 때 쓰기 데이터를 받아들일 준비가 되어 있다는 것을 나타냅니다. 이 디자인은 미해결 트랜잭션이 없다고 가정합니다. 이 경우, axi_wready는 1로 설정됩니다.

위의 조건이 참이 아닌 경우, axi_wready는 0으로 설정됩니다.

  1. axi_bresp, axi_bvalid

    axi_bresp는 AXI4-Lite 인터페이스에서 쓰기 응답 상태를 나타냅니다.
    axi_bresp 레지스터는 2비트 크기로, 다음의 4가지 상태를 나타낼 수 있습니다:

    2'b00: OKAY - 쓰기 트랜잭션이 성공적으로 완료되었음을 나타냅니다.
    2'b01: EXOKAY - 쓰기 트랜잭션이 성공적으로 완료되었지만, 일부 정보가 누락되었을 수 있음을 나타냅니다.
    2'b10: SLVERR - 슬레이브 에러가 발생했음을 나타냅니다. 이는 일반적으로 슬레이브가 요청을 처리할 수 없을 때 발생합니다.
    2'b11: DECERR - 주소 해석 에러가 발생했음을 나타냅니다. 이는 일반적으로 주소가 유효하지 않을 때 발생합니다.

    따라서 axi_bresp 레지스터는 쓰기 트랜잭션의 상태를 나타내는 중요한 역할을 합니다.

    axi_bvalid는 AXI4-Lite 인터페이스에서 쓰기 응답이 유효함을 나타냅니다.

    axi_bvalid 신호가 활성화되면(즉, '1'로 설정되면), 슬레이브는 마스터에게 쓰기 트랜잭션이 성공적으로 완료되었음을 알립니다. 이는 마스터가 쓰기 응답(axi_bresp)를 받아들일 수 있음을 의미합니다.

    반대로, axi_bvalid 신호가 비활성화되면(즉, '0'로 설정되면), 슬레이브는 쓰기 응답이 더 이상 유효하지 않음을 나타냅니다. 이는 마스터가 쓰기 응답을 받아들이는 것을 지연해야 함을 의미합니다.
    따라서 axi_bvalid 신호는 쓰기 응답의 유효성을 제어하는 데 중요한 역할을 합니다.

reg [1 : 0] 	axi_bresp;
assign S_AXI_BRESP	= axi_bresp;

// Implement write response logic generation
// The write response and response valid signals are asserted by the slave 
// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.  
// This marks the acceptance of address and indicates the status of 
// write transaction.

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_bvalid  <= 0;
      axi_bresp   <= 2'b0;
    end 
  else
    begin    
      if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
        begin
          // indicates a valid write response is available
          axi_bvalid <= 1'b1;
          axi_bresp  <= 2'b0; // 'OKAY' response 
        end                   // work error responses in future
      else
        begin
          if (S_AXI_BREADY && axi_bvalid) 
            //check if bready is asserted while bvalid is high) 
            //(there is a possibility that bready is always asserted high)   
            begin
              axi_bvalid <= 1'b0; 
            end  
        end
    end
end   

axi_awready, S_AXI_AWVALID, axi_wready, S_AXI_WVALID가 모두 활성화되어 있고, axi_bvalid가 비활성화된 경우를 확인합니다.
이 경우, 슬레이브는 유효한 쓰기 주소와 쓰기 데이터가 존재할 때 쓰기 응답이 유효하다는 것을 나타냅니다. 이 경우, axi_bvalid는 1로 설정되고, axi_bresp는 'OKAY' 응답인 0으로 설정됩니다.

위의 조건이 참이 아닌 경우, S_AXI_BREADYaxi_bvalid가 모두 활성화된 경우를 확인합니다.
이 경우, 슬레이브는 마스터가 쓰기 응답을 받아들일 준비가 되어 있음을 나타냅니다. 이 경우, axi_bvalid는 0으로 설정됩니다.

이러한 방식으로, axi_bvalidaxi_bresp 신호는 쓰기 트랜잭션의 상태를 나타내는 역할을 합니다.

  1. axi_araddr, axi_arready

    axi_araddr는 AXI4-Lite 인터페이스에서 읽기 주소를 나타냅니다.
    C_S_AXI_ADDR_WIDTH-1 : 0 비트 크기로, 이는 주소 버스의 너비를 나타냅니다.

    마스터는 axi_araddr 레지스터를 사용하여 슬레이브에게 읽기 작업을 수행할 메모리 위치를 알립니다.
    따라서 axi_araddr 레지스터는 읽기 트랜잭션의 주소를 나타내는 중요한 역할을 합니다.

    axi_arready는 AXI4-Lite 인터페이스에서 슬레이브가 읽기 주소와 관련된 제어 신호를 받을 준비가 되었음을 나타냅니다.

    axi_arready 레지스터가 활성화되면(즉, '1'로 설정되면), 슬레이브는 마스터로부터 읽기 주소(axi_araddr)를 받을 준비가 되었음을 나타냅니다.

    반대로, axi_arready 레지스터가 비활성화되면(즉, '0'로 설정되면), 슬레이브는 읽기 주소를 받는 것을 지연해야 함을 나타냅니다.
    따라서 axi_arready 레지스터는 읽기 트랜잭션의 준비 상태를 나타내는 중요한 역할을 합니다.

reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr;
reg  	axi_arready;
assign S_AXI_ARREADY	= axi_arready;

// Implement axi_arready generation
// axi_arready is asserted for one S_AXI_ACLK clock cycle when
// S_AXI_ARVALID is asserted. axi_awready is 
// de-asserted when reset (active low) is asserted. 
// The read address is also latched when S_AXI_ARVALID is 
// asserted. axi_araddr is reset to zero on reset assertion.

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_arready <= 1'b0;
      axi_araddr  <= 32'b0;
    end 
  else
    begin    
      if (~axi_arready && S_AXI_ARVALID)
        begin
          // indicates that the slave has acceped the valid read address
          axi_arready <= 1'b1;
          // Read address latching
          axi_araddr  <= S_AXI_ARADDR;
        end
      else
        begin
          axi_arready <= 1'b0;
        end
    end 
end       

axi_arready가 비활성화되어 있고, S_AXI_ARVALID가 활성화된 경우를 확인합니다.
이 경우, 슬레이브는 유효한 읽기 주소가 존재할 때 읽기 주소를 받아들일 준비가 되어 있다는 것을 나타냅니다. 이 경우, axi_arready는 1로 설정되고, axi_araddrS_AXI_ARADDR로 설정됩니다.

위의 조건이 참이 아닌 경우, axi_arready는 0으로 설정됩니다.

이러한 방식으로, axi_arreadyaxi_araddr 레지스터는 읽기 트랜잭션의 준비 상태와 주소를 나타내는 역할을 합니다.

  1. axi_rdata

    axi_rdata는 AXI4-Lite 인터페이스에서 슬레이브가 마스터에게 전송하는 읽기 데이터를 나타냅니다.
    C_S_AXI_DATA_WIDTH-1 : 0 비트 크기로, 이는 데이터 버스의 너비를 나타냅니다.

    마스터는 axi_rdata 레지스터를 통해 슬레이브로부터 읽기 데이터를 받습니다.
    따라서 axi_rdata 레지스터는 읽기 트랜잭션의 데이터를 나타내는 중요한 역할을 합니다.

reg [C_S_AXI_DATA_WIDTH-1 : 0] 	axi_rdata;
assign S_AXI_RDATA	= axi_rdata;

// Output register or memory read data
always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_rdata  <= 0;
    end 
  else
    begin    
      // When there is a valid read address (S_AXI_ARVALID) with 
      // acceptance of read address by the slave (axi_arready), 
      // output the read dada 
      if (slv_reg_rden)
        begin
          axi_rdata <= reg_data_out;     // register read data
        end   
    end
end    

slv_reg_rden이 활성화된 경우를 확인합니다.
이 경우, 슬레이브는 유효한 읽기 주소가 존재하고, 슬레이브가 읽기 주소를 받아들일 준비가 되어 있음을 나타냅니다. 이 경우, axi_rdatareg_data_out로 설정됩니다.

이러한 방식으로, axi_rdata 레지스터는 읽기 트랜잭션의 데이터를 나타내는 역할을 합니다.

  1. axi_rresp, axi_rvalid

    axi_rresp는 AXI4-Lite 인터페이스에서 슬레이브가 마스터에게 전송하는 읽기 응답을 나타냅니다.
    axi_rresp 레지스터는 1 : 0 비트 크기로, 이는 읽기 응답의 상태를 나타냅니다. 이 레지스터는 2비트 크기로, 다음의 값들을 가질 수 있습니다:

    2'b00: OKAY - 읽기 데이터는 정상입니다.
    2'b01: EXOKAY - 읽기 데이터는 정상이지만, 추가적인 정보가 있을 수 있습니다.
    2'b10: SLVERR - 슬레이브 에러가 발생했습니다.
    2'b11: DECERR - 주소 에러가 발생했습니다.

    마스터는 axi_rresp 레지스터를 통해 슬레이브로부터 읽기 응답의 상태를 받습니다.
    따라서 axi_rresp 레지스터는 읽기 트랜잭션의 응답 상태를 나타내는 중요한 역할을 합니다.

    axi_rvalid는 AXI4-Lite 인터페이스에서 슬레이브가 마스터에게 읽기 데이터가 유효함을 나타냅니다.

    axi_rvalid 레지스터가 활성화되면(즉, '1'로 설정되면), 슬레이브는 마스터에게 읽기 데이터(axi_rdata)와 읽기 응답(axi_rresp)이 유효함을 나타냅니다.

    반대로, axi_rvalid 레지스터가 비활성화되면(즉, '0'로 설정되면), 슬레이브는 읽기 데이터와 읽기 응답이 아직 준비되지 않았음을 나타냅니다.
    따라서 axi_rvalid 레지스터는 읽기 트랜잭션의 유효 상태를 나타내는 중요한 역할을 합니다.

reg [1 : 0] 	axi_rresp;
reg  	axi_rvalid;
assign S_AXI_RRESP	= axi_rresp;
assign S_AXI_RVALID	= axi_rvalid;
   
// Implement axi_arvalid generation
// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both 
// S_AXI_ARVALID and axi_arready are asserted. The slave registers 
// data are available on the axi_rdata bus at this instance. The 
// assertion of axi_rvalid marks the validity of read data on the 
// bus and axi_rresp indicates the status of read transaction.axi_rvalid 
// is deasserted on reset (active low). axi_rresp and axi_rdata are 
// cleared to zero on reset (active low).  
always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_rvalid <= 0;
      axi_rresp  <= 0;
    end 
  else
    begin    
      if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
        begin
          // Valid read data is available at the read data bus
          axi_rvalid <= 1'b1;
          axi_rresp  <= 2'b0; // 'OKAY' response
        end   
      else if (axi_rvalid && S_AXI_RREADY)
        begin
          // Read data is accepted by the master
          axi_rvalid <= 1'b0;
        end                
    end
end    

axi_arreadyS_AXI_ARVALID가 모두 활성화되어 있고, axi_rvalid가 비활성화된 경우를 확인합니다.
이 경우, 슬레이브는 유효한 읽기 주소가 존재하고, 슬레이브가 읽기 주소를 받아들일 준비가 되어 있음을 나타냅니다. 이 경우, axi_rvalid는 1로 설정되고, axi_rresp는 'OKAY' 응답(2'b0)으로 설정됩니다.

axi_rvalid가 활성화되어 있고, S_AXI_RREADY가 활성화된 경우를 확인합니다. 이 경우, 마스터가 읽기 데이터를 받아들였음을 나타냅니다. 이 경우, axi_rvalid는 0으로 설정됩니다.
이러한 방식으로, axi_rvalidaxi_rresp 레지스터는 읽기 트랜잭션의 유효 상태와 응답 상태를 나타내는 역할을 합니다.


User Logic Register Space

  1. slv_reg0, slv_reg1, slv_reg2, slv_reg3, slv_reg_wren

    slv_reg0, slv_reg1, slv_reg2, slv_reg3들은 슬레이브 레지스터를 나타내며, 각각의 레지스터는 C_S_AXI_DATA_WIDTH-1:0 비트의 너비를 가집니다.

    C_S_AXI_DATA_WIDTH는 AXI 데이터 버스의 너비를 정의하는 매개변수입니다. 따라서 slv_reg0부터 slv_reg3까지의 레지스터는 AXI 데이터 버스의 너비와 동일한 너비를 가집니다.

    이 레지스터들은 AXI 인터페이스를 통해 데이터를 읽고 쓰는 데 사용됩니다. 마스터는 이 레지스터들을 통해 슬레이브에 데이터를 쓰거나 슬레이브로부터 데이터를 읽을 수 있습니다.
    따라서 slv_reg0부터 slv_reg3까지의 레지스터는 AXI 인터페이스를 통한 데이터 전송을 위한 중요한 역할을 합니다.

    slv_reg_wren는 슬레이브 레지스터 쓰기 활성화 신호를 나타냅니다.

    slv_reg_wren이 활성화되면, 슬레이브 레지스터에 데이터를 쓸 수 있습니다. 이 와이어는 AXI 인터페이스를 통해 데이터를 쓰는 데 필요한 로직에서 사용됩니다.
    따라서 slv_reg_wren 와이어는 슬레이브 레지스터에 데이터를 쓰는 데 필요한 제어 신호를 제공하는 중요한 역할을 합니다.

//-- Number of Slave Registers 4
reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg0;
reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg1;
reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg2;
reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg3;
wire	 slv_reg_wren;
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
    
// Implement memory mapped register select and write logic generation
// The write data is accepted and written to memory mapped registers when
// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
// select byte enables of slave registers while writing.
// These registers are cleared when reset (active low) is applied.
// Slave register write enable is asserted when valid address and data are available
// and the slave is ready to accept the write address and write data.
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      slv_reg0 <= 0;
      slv_reg1 <= 0;
      slv_reg2 <= 0;
      slv_reg3 <= 0;
    end 
  else begin
    if (slv_reg_wren)
      begin
        case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
          2'h0:
            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 0
                slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          2'h1:
            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 1
                slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          2'h2:
            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 2
                slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          2'h3:
            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
                // Respective byte enables are asserted as per write strobes 
                // Slave register 3
                slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
              end  
          default : begin
                      slv_reg0 <= slv_reg0;
                      slv_reg1 <= slv_reg1;
                      slv_reg2 <= slv_reg2;
                      slv_reg3 <= slv_reg3;
                    end
        endcase
      end
  end
end    

이 Verilog 코드는 AXI 인터페이스를 통해 슬레이브 레지스터(slv_reg0, slv_reg1, slv_reg2, slv_reg3)에 데이터를 쓰는 로직을 구현합니다.

slv_reg_wren은 슬레이브 레지스터 쓰기 활성화 신호로, axi_wready, S_AXI_WVALID, axi_awready, S_AXI_AWVALID가 모두 활성화되면 활성화됩니다. 이는 유효한 쓰기 주소와 데이터가 준비되어 있고, 슬레이브가 쓰기 주소와 데이터를 받아들일 준비가 되어 있음을 나타냅니다.

리셋 신호가 활성화되지 않은 경우, slv_reg_wren이 활성화되었는지 확인하고,
활성화되었다면 주소(axi_awaddr)에 따라 적절한 슬레이브 레지스터에 데이터(S_AXI_WDATA)를 씁니다. 이 때, 쓰기 스트로브(S_AXI_WSTRB)는 슬레이브 레지스터의 바이트 활성화를 선택하는 데 사용됩니다.
따라서 이 코드는 AXI 인터페이스를 통해 슬레이브 레지스터에 데이터를 쓰는 데 필요한 로직을 구현합니다.

  1. slv_reg_rden, reg_data_out

    slv_reg_rden는 슬레이브 레지스터 읽기 활성화 신호를 나타냅니다.

    slv_reg_rden이 활성화되면, 슬레이브 레지스터에서 데이터를 읽을 수 있습니다. 이 와이어는 AXI 인터페이스를 통해 데이터를 읽는 데 필요한 로직에서 사용됩니다.
    따라서 slv_reg_rden 와이어는 슬레이브 레지스터에서 데이터를 읽는 데 필요한 제어 신호를 제공하는 중요한 역할을 합니다.

    reg_data_outC_S_AXI_DATA_WIDTH-1:0 비트의 너비를 가집니다.

    C_S_AXI_DATA_WIDTH는 AXI 데이터 버스의 너비를 정의하는 매개변수입니다.
    따라서 reg_data_out 레지스터는 AXI 데이터 버스의 너비와 동일한 너비를 가집니다.

    이 레지스터는 일반적으로 AXI 인터페이스를 통해 데이터를 읽을 때 사용됩니다. 슬레이브 레지스터에서 읽은 데이터는 reg_data_out에 저장되고, 이 데이터는 AXI 인터페이스를 통해 마스터에게 전송됩니다.
    따라서 reg_data_out 레지스터는 AXI 인터페이스를 통한 데이터 읽기를 위한 중요한 역할을 합니다.

wire	 slv_reg_rden;
reg [C_S_AXI_DATA_WIDTH-1:0]	 reg_data_out;

// Implement memory mapped register select and read logic generation
	// Slave register read enable is asserted when valid address is available
	// and the slave is ready to accept the read address.
	assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
	always @(*)
	begin
	      // Address decoding for reading registers
	      case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	        2'h0   : reg_data_out <= slv_reg0;
	        2'h1   : reg_data_out <= slv_reg1;
	        2'h2   : reg_data_out <= slv_reg2;
	        2'h3   : reg_data_out <= slv_reg3;
	        default : reg_data_out <= 0;
	      endcase
	end

이 Verilog 코드는 메모리 맵핑된 레지스터 선택 및 읽기 로직을 구현합니다.

slv_reg_rden은 슬레이브 레지스터 읽기 활성화 신호로, 유효한 주소가 있고 슬레이브가 읽기 주소를 받아들일 준비가 되었을 때 활성화됩니다. 이 신호는 axi_arreadyS_AXI_ARVALID가 모두 활성화되고 axi_rvalid가 비활성화된 경우에만 활성화됩니다.

이 블록 내에서는 주소(axi_araddr) 디코딩을 통해 읽을 레지스터를 선택합니다.
case 문을 사용하여 주소에 따라 reg_data_out에 저장할 데이터를 선택합니다. 주소 값에 따라 slv_reg0, slv_reg1, slv_reg2, slv_reg3 중 하나가 선택되거나, 주소 값이 이들 중 어느 것에도 해당하지 않는 경우 reg_data_out은 0으로 설정됩니다.
따라서 이 코드는 AXI 인터페이스를 통해 슬레이브 레지스터에서 데이터를 읽는 데 필요한 로직을 구현합니다.

profile
Myongji UNIV. B.S. in Electronic Engineering

0개의 댓글

관련 채용 정보