根据个人理解对原工程代码进行位置上的重排和解析,更加清晰易懂
assign init_txn_pulse = (!init_txn_ff2) && init_txn_ff;
//当有INIT_AXI_TXN电平跳变时,使用两个寄存器init_txn_ff和init_txn_ff2相与
//得到一个时钟周期长度的脉冲信号
//Generate a pulse to initiate AXI transaction.
always @(posedge M_AXI_ACLK)
begin
// Initiates AXI transaction delay
if (M_AXI_ARESETN == 0 )
begin
init_txn_ff <= 1'b0;
init_txn_ff2 <= 1'b0;
end
else
begin
init_txn_ff <= INIT_AXI_TXN;
init_txn_ff2 <= init_txn_ff;
end
end
parameter [1:0] IDLE = 2'b00, // This state initiates AXI4Lite transaction
// after the state machine changes state to INIT_WRITE
// when there is 0 to 1 transition on INIT_AXI_TXN
INIT_WRITE = 2'b01, // This state initializes write transaction,
// once writes are done, the state machine
// changes state to INIT_READ
INIT_READ = 2'b10, // This state initializes read transaction
// once reads are done, the state machine
// changes state to INIT_COMPARE
INIT_COMPARE = 2'b11; // This state issues the status of comparison
// of the written data with the read data
always @ ( posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 1'b0)
begin
// reset condition
// All the signals are assigned default values under reset condition
mst_exec_state <= IDLE;
start_single_write <= 1'b0;
write_issued <= 1'b0;
start_single_read <= 1'b0;
read_issued <= 1'b0;
compare_done <= 1'b0;
ERROR <= 1'b0;
end
else
begin
// state transition
case (mst_exec_state)
IDLE:
// This state is responsible to initiate
// AXI transaction when init_txn_pulse is asserted
if ( init_txn_pulse == 1'b1 ) //当有事务启动时,转换至INIT_WRITE状态
begin
mst_exec_state <= INIT_WRITE;
ERROR <= 1'b0;
compare_done <= 1'b0;
end
else
begin
mst_exec_state <= IDLE;
end
INIT_WRITE:
// This state is responsible to issue start_single_write pulse to
// initiate a write transaction. Write transactions will be
// issued until last_write signal is asserted.
// write controller
if (writes_done) //如果写入了C_M_TRANSACTIONS_NUM个数据,进入读取状态
begin
mst_exec_state <= INIT_READ;//
end
else
begin
mst_exec_state <= INIT_WRITE;
if (~axi_awvalid && ~axi_wvalid && ~M_AXI_BVALID && ~last_write && ~start_single_write && ~write_issued)
//当均无效时 可以发起一次写入
begin
start_single_write <= 1'b1;
write_issued <= 1'b1;
end
else if (axi_bready)
//当完成写入响应后 write_issued 失效,表示可以准备下次发起
begin
write_issued <= 1'b0;
end
else
begin
start_single_write <= 1'b0; //Negate to generate a pulse
end
end
INIT_READ:
// This state is responsible to issue start_single_read pulse to
// initiate a read transaction. Read transactions will be
// issued until last_read signal is asserted.
// read controller
if (reads_done)
begin
mst_exec_state <= INIT_COMPARE;
end
else
begin
mst_exec_state <= INIT_READ;
if (~axi_arvalid && ~M_AXI_RVALID && ~last_read && ~start_single_read && ~read_issued)
begin
start_single_read <= 1'b1;
read_issued <= 1'b1;
end
else if (axi_rready)
begin
read_issued <= 1'b0;
end
else
begin
start_single_read <= 1'b0; //Negate to generate a pulse
end
end
INIT_COMPARE:
begin
// This state is responsible to issue the state of comparison
// of written data with the read data. If no error flags are set,
// compare_done signal will be asseted to indicate success.
ERROR <= error_reg;
mst_exec_state <= IDLE;
compare_done <= 1'b1;
end
default :
begin
mst_exec_state <= IDLE;
end
endcase
end
end //MASTER_EXECUTION_PROC
当 start_single_write 有效,开始一次写传输,设置 axi_awvalid 有效
always @(posedge M_AXI_ACLK)
begin
//Only VALID signals must be deasserted during reset per AXI spec
//Consider inverting then registering active-low reset for higher fmax
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
//复位或者初始化信号激活时,axi_awvalid复位
begin
axi_awvalid <= 1'b0;
end
//Signal a new address/data command is available by user logic
else
begin
if (start_single_write)
begin
axi_awvalid <= 1'b1;
end
//Address accepted by interconnect/slave (issue of M_AXI_AWREADY by slave)
else if (M_AXI_AWREADY && axi_awvalid)
//M_AXI_AWREADY为来自从机的输入信号
//This signal indicates that the slave is ready to accept an address and associated control signals.
begin
axi_awvalid <= 1'b0;
end
end
end
assign M_AXI_AWADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;
//Adding the offset address to the base addr of the slave
//output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,主机输出的地址信号
//Master Interface Write Address Channel ports. Write address (issued by master)
//Write Addresses
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_awaddr <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (M_AXI_AWREADY && axi_awvalid)
begin
axi_awaddr <= axi_awaddr + 32'h00000004;
end
end
综合来看,在start_single_write有效时,写地址axi_awvalid 有效,主机输出M_AXI_AWVALID有效信号给从机,表示写地址有效,并且在从机输入M_AXI_AWREADY 有效时,axi_awaddr 地址自增
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_wvalid <= 1'b0;
end
//Signal a new address/data command is available by user logic
else if (start_single_write)
begin
axi_wvalid <= 1'b1;
end
//Data accepted by interconnect/slave (issue of M_AXI_WREADY by slave)
else if (M_AXI_WREADY && axi_wvalid)
begin
axi_wvalid <= 1'b0;
end
end
可见 在start_single_write有效时,axi_awvalid 和 axi_wvalid 同时有效
当 M_AXI_WREADY && axi_wvalid 同 时 有 效 的 时 候 , 数 据 才 是 有 效 的 ,
对 于 axi-lite_master 接 口 ,M_AXI_WREADY && axi_wvalid 同时有效的时间窗口是一个时钟周期。
assign M_AXI_WDATA = axi_wdata;//输出
// Write data generation
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )
begin
axi_wdata <= C_M_START_DATA_VALUE;
end
// Signals a new write address/ write data is
// available by user logic
else if (M_AXI_WREADY && axi_wvalid)
begin
axi_wdata <= C_M_START_DATA_VALUE + write_index;
end
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
write_index <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (start_single_write)
begin
write_index <= write_index + 1; //写数据计数器
//当写数据达到C_M_TRANSACTIONS_NUM数目时, last_write 有效
end
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
last_write <= 1'b0;
//The last write should be associated with a write address ready response
else if ((write_index == C_M_TRANSACTIONS_NUM) && M_AXI_AWREADY)
last_write <= 1'b1;
else
last_write <= last_write;
end
当收到写通道的 axi-lite-slave 发回的 M_AXI_BVALDI 应答信号,设置 axi_bready 为 1,BRESP 返回 AXI 写操作是否有错误。
// This signal indicates the status of the write transaction.
input wire [1 : 0] M_AXI_BRESP
// 从机输入响应信号,若为00,则接收无误
// BRESP 是一个两位的信号,表示写事务的响应
// 一些常见的 BRESP 值可能包括:
// 2'b00: 正常的响应,表示写事务被成功接收并处理。
// 2'b01: DECERR,表示写事务的地址字段解码出错。
// 2'b10: SLVERR,表示写事务被从设备拒绝。
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_bready <= 1'b0;
end
// accept/acknowledge bresp with axi_bready by the master
// when M_AXI_BVALID is asserted by slave
else if (M_AXI_BVALID && ~axi_bready)
begin
axi_bready <= 1'b1;
end
// deassert after one clock cycle
else if (axi_bready)
begin
axi_bready <= 1'b0;
end
// retain the previous value
else
axi_bready <= axi_bready;
end
//Flag write errors 表示write response error
assign write_resp_error = (axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]);
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_arvalid <= 1'b0;
end
//Signal a new read address command is available by user logic
else if (start_single_read)
begin
axi_arvalid <= 1'b1;
end
//RAddress accepted by interconnect/slave (issue of M_AXI_ARREADY by slave)
else if (M_AXI_ARREADY && axi_arvalid)
begin
axi_arvalid <= 1'b0;
end
// retain the previous value
end
//Read Addresses
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_araddr <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else if (M_AXI_ARREADY && axi_arvalid)
begin
axi_araddr <= axi_araddr + 32'h00000004;
end
end
当M_AXI_RVALID && axi_rready同时有效的时候,数据才是有效的,对于axi-lite_master接口,M_AXI_RVALID && ~axi_rready==1 的时候设置 axi_rready=1,当 axi_rready==1,再设置 axi_rready=0
assign M_AXI_RREADY = axi_rready;
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_rready <= 1'b0;
end
// accept/acknowledge rdata/rresp with axi_rready by the master
// when M_AXI_RVALID is asserted by slave
else if (M_AXI_RVALID && ~axi_rready)
begin
axi_rready <= 1'b1;
end
// deassert after one clock cycle
else if (axi_rready)
begin
axi_rready <= 1'b0;
end
// retain the previous value
end
//Flag write errors 表示read response error
assign read_resp_error = (axi_rready & M_AXI_RVALID & M_AXI_RRESP[1]);
//RRESP 是 AXI 总线的读响应通道(Read Response Channel)的信号,用于指示读事务的响应状态
//RRESP[1] 位表示响应状态,其中 0 表示正常响应,而 1 表示出现了错误
数据 expected_rdata 用于和读出的 M_AXI_RDATA 进行对比以此验证数据的正确性。
//Data Comparison
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
read_mismatch <= 1'b0;
//The read data when available (on axi_rready) is compared with the expected data
else if ((M_AXI_RVALID && axi_rready) && (M_AXI_RDATA != expected_rdata))
read_mismatch <= 1'b1; // 每一次读取响应完成后均会进行比较
else
read_mismatch <= read_mismatch;
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
expected_rdata <= C_M_START_DATA_VALUE;
end
// Signals a new write address/ write data is
// available by user logic
else if (M_AXI_RVALID && axi_rready)
begin
expected_rdata <= C_M_START_DATA_VALUE + read_index;
end
end