`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
// 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 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
: 마스터가 읽기 데이터와 응답 정보를 수락할 수 있음을 나타냅니다.
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
)에서 래치되거나 저장됩니다. 이는 시스템이 마스터에 의해 제공된 새로운 쓰기 주소를 받아들였으며 해당 주소에서 쓰기 작업을 수행할 준비가 되었다는 것을 의미합니다.
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_BREADY
와axi_bvalid
가 모두 활성화된 경우를 확인합니다. 이 경우,aw_en
은 1로 설정되고,axi_awready
는 0으로 설정됩니다.위의 두 조건문 모두 참이 아닌 경우,
axi_awready
는 0으로 설정됩니다.
이러한 방식으로,axi_awready
신호는 AXI4-Lite 인터페이스에서 쓰기 작업의 준비 상태를 나타내는 역할을 합니다.
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으로 설정됩니다.
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_BREADY
와axi_bvalid
가 모두 활성화된 경우를 확인합니다.
이 경우, 슬레이브는 마스터가 쓰기 응답을 받아들일 준비가 되어 있음을 나타냅니다. 이 경우,axi_bvalid
는 0으로 설정됩니다.이러한 방식으로,
axi_bvalid
와axi_bresp
신호는 쓰기 트랜잭션의 상태를 나타내는 역할을 합니다.
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_araddr
는S_AXI_ARADDR
로 설정됩니다.위의 조건이 참이 아닌 경우,
axi_arready
는 0으로 설정됩니다.이러한 방식으로,
axi_arready
와axi_araddr
레지스터는 읽기 트랜잭션의 준비 상태와 주소를 나타내는 역할을 합니다.
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_rdata
는reg_data_out
로 설정됩니다.이러한 방식으로,
axi_rdata
레지스터는 읽기 트랜잭션의 데이터를 나타내는 역할을 합니다.
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_arready
와S_AXI_ARVALID
가 모두 활성화되어 있고,axi_rvalid
가 비활성화된 경우를 확인합니다.
이 경우, 슬레이브는 유효한 읽기 주소가 존재하고, 슬레이브가 읽기 주소를 받아들일 준비가 되어 있음을 나타냅니다. 이 경우,axi_rvalid
는 1로 설정되고,axi_rresp
는 'OKAY' 응답(2'b0
)으로 설정됩니다.
axi_rvalid
가 활성화되어 있고,S_AXI_RREADY
가 활성화된 경우를 확인합니다. 이 경우, 마스터가 읽기 데이터를 받아들였음을 나타냅니다. 이 경우,axi_rvalid
는 0으로 설정됩니다.
이러한 방식으로,axi_rvalid
와axi_rresp
레지스터는 읽기 트랜잭션의 유효 상태와 응답 상태를 나타내는 역할을 합니다.
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 인터페이스를 통해 슬레이브 레지스터에 데이터를 쓰는 데 필요한 로직을 구현합니다.
slv_reg_rden
, reg_data_out
slv_reg_rden
는 슬레이브 레지스터 읽기 활성화 신호를 나타냅니다.
slv_reg_rden
이 활성화되면, 슬레이브 레지스터에서 데이터를 읽을 수 있습니다. 이 와이어는 AXI 인터페이스를 통해 데이터를 읽는 데 필요한 로직에서 사용됩니다.
따라서slv_reg_rden
와이어는 슬레이브 레지스터에서 데이터를 읽는 데 필요한 제어 신호를 제공하는 중요한 역할을 합니다.
reg_data_out
는C_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_arready
와S_AXI_ARVALID
가 모두 활성화되고axi_rvalid
가 비활성화된 경우에만 활성화됩니다.이 블록 내에서는 주소(
axi_araddr
) 디코딩을 통해 읽을 레지스터를 선택합니다.
case 문을 사용하여 주소에 따라reg_data_out
에 저장할 데이터를 선택합니다. 주소 값에 따라slv_reg0
,slv_reg1
,slv_reg2
,slv_reg3
중 하나가 선택되거나, 주소 값이 이들 중 어느 것에도 해당하지 않는 경우reg_data_out
은 0으로 설정됩니다.
따라서 이 코드는 AXI 인터페이스를 통해 슬레이브 레지스터에서 데이터를 읽는 데 필요한 로직을 구현합니다.