오늘은 AXI Read 동작과 Handshake 동작에 대한 부분을 알아보겠습니다.
먼저 Simulation Pulse를 확인하고 Read Operation과 Handshake에 대해 알아보도록 하겠습니다.
Valid-Ready Handshake
Valid와 Ready는 Handshake Signal입니다.
Valid-Read Handshake는 Data를 보내고 받는 Source와 Destination사이에서 Data 이동 준비를 확인하는 작업입니다.
위처럼 Valid와 Ready가 모두 1이 될 때, Slave는 Read 할 Data를 Master에게 전달합니다.
Write동작일 때는 Master가 Source, Slave가 Destination이기 때문에 동작이 반대로 일어납니다.
AXI Read Operation
Read Operation을 살펴보겠습니다.
1) Read ADDR 신호를 전송하기위해 Handshake 준비
2) AValid-ARead로 Handshake를 하고 ADDR(주소)를 전송한다.
3) Data를 보내기 위해서 Valid를 보내 Handshake를 준비한다.
4) Ready 신호를 보내 HandShake를 완료하고 Read할 Data를 전송한다.
+) Read Data의 마지막을 알리는 신호RLAST가 존재한다.
AXI Read Slave
`timescale 1ns / 1ps
module axi_slave(
input RST,
input CLK,
input [4:0] AXI_ADDR,
input AXI_AVALID,
output reg AXI_AREADY,
output [7:0] AXI_DATA,
output reg AXI_VALID,
input AXI_READY
);
parameter [1:0] sidle = 2'b00,
saddr = 2'b01,
srom = 2'b10,
sdata = 2'b11;
reg [1:0] cstate, nstate;
wire [4:0] rom_addr;
wire [7:0] rom_data;
rom32x8 rom_0 (
.clka (CLK), // input wire clka
.addra (rom_addr), // input wire [4 : 0] addra
.douta (rom_data) // output wire [7 : 0] douta
);
assign rom_addr = AXI_ADDR;
assign AXI_DATA = rom_data;
//fsm
always @(posedge CLK)
if(RST)
cstate <= sidle;
else
cstate <= nstate;
always @(cstate, AXI_AVALID, AXI_READY)
begin
AXI_AREADY = 1'b0;
AXI_VALID = 1'b0;
case (cstate)
sidle : begin
if(AXI_AVALID)
nstate = saddr;
else
nstate = sidle;
end
saddr : begin
nstate = srom;
AXI_AREADY = 1'b1;
end
srom : nstate = sdata;
sdata : begin
AXI_VALID = 1'b1;
if(AXI_READY) begin
AXI_VALID = 1'b1;
nstate = sidle;
end else
nstate = sdata;
end
default : nstate = sidle;
endcase
end //always
endmodule
AXI Read Master
`timescale 1ns / 1ps
module my_axi_master(
input RST,
input CLK,
input [4:0] ADDR,
input START,
output [4:0] AXI_ADDR,
output reg AXI_AVALID,
input AXI_AREADY,
input [7:0] AXI_DATA,
input AXI_VALID,
output reg AXI_READY
);
parameter [1:0] sidle = 2'b00,
saddr = 2'b01,
sdata = 2'b10;
reg [1:0] cstate, nstate;
assign AXI_ADDR = ADDR;
always @(posedge CLK)
if(RST)
cstate <= sidle;
else
cstate <= nstate;
always @(cstate, START,AXI_AREADY,AXI_VALID)
begin
AXI_AVALID = 1'b0;
AXI_READY = 1'b0;
case (cstate)
sidle : begin
if(START)
nstate = saddr;
else
nstate = sidle;
end
saddr : begin
AXI_AVALID = 1'b1;
if(AXI_AREADY)
nstate = sdata;
else
nstate = saddr;
end
sdata : begin
AXI_READY = 1'b1;
if(AXI_VALID)
nstate = sidle;
else
nstate = sdata;
end
default : nstate = sidle;
endcase
end //always
endmodule
Testbench Of AXI Read Operation
`timescale 1ns / 1ps
module axi_tb();
parameter CLK_PD = 10.0;
reg rst, clk;
reg start;
reg [4:0] addr;
wire [4:0] axi_addr;
wire [7:0] axi_data;
wire axi_avalid, axi_aready;
wire axi_valid, axi_ready;
// uut instantiation
my_axi_master master_0 (
.RST (rst),
.CLK (clk),
.ADDR (addr),
.START (start),
.AXI_ADDR (axi_addr),
.AXI_AVALID (axi_avalid),
.AXI_AREADY (axi_aready),
.AXI_DATA (axi_data),
.AXI_VALID (axi_valid),
.AXI_READY (axi_ready)
);
axi_slave slave_0 (
.RST (rst),
.CLK (clk),
.AXI_ADDR (axi_addr),
.AXI_AVALID (axi_avalid),
.AXI_AREADY (axi_aready),
.AXI_DATA (axi_data),
.AXI_VALID (axi_valid),
.AXI_READY (axi_ready)
);
// rst, clk gen
initial begin
rst = 1'b1;
#(CLK_PD*10);
rst = 1'b0;
end
initial clk = 1'b0;
always #(CLK_PD/2) clk = ~clk;
// stimulus for start, addr
integer i;
initial begin
start = 1'b0;
addr = 5'd0;
#(CLK_PD/2);
wait (rst == 1'b0);
// repeat(2) @(posedge clk);
#(CLK_PD*10);
for (i=0; i<32; i = i+1)
begin
start = 1'b1;
wait (axi_aready == 1'b1);
start = 1'b0;
wait (axi_valid);
#(CLK_PD*5);
addr = addr + 1;
end
#100;
$finish;
end //always
endmodule
Testbench Pulse는 상단 첫번째 그림이니 생략하겠습니다.
다음 포스팅은 Write Opertaion으로 돌아오겠습니다.
감사합니다.
'Circuit Design > 🔥HDL' 카테고리의 다른 글
[Vitis] 1. AXI (0) | 2024.06.27 |
---|---|
[Verilog] 15. AXI Write (0) | 2024.06.27 |
[Verilog] 13. AXI(Advanced eXtensible Interface) (0) | 2024.06.25 |
[Vitis] 0. Preview(Hello World) (0) | 2024.06.24 |
[Verilog] Vivado Setting [Dark Theme(Vivado 다크모드)] (0) | 2024.06.10 |