AXI4的主机协议代码分析
一、模块分析
(1)端口列表
input wire INIT_AXI_TXN, // Asserts when ERROR is detected output reg ERROR, // Asserts when AXI transactions is complete output wire TXN_DONE, // AXI clock signal input wire M_AXI_ACLK, // AXI active low reset signal input wire M_AXI_ARESETN, // Master Interface Write Address Channel ports. Write address (issued by master) output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_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. output wire [2 : 0] M_AXI_AWPROT, // Write address valid. // This signal indicates that the master signaling valid write address and control information. output wire M_AXI_AWVALID, // Write address ready. // This signal indicates that the slave is ready to accept an address and associated control signals. input wire M_AXI_AWREADY, // Master Interface Write Data Channel ports. Write data (issued by master) output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_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. output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB, // Write valid. This signal indicates that valid write data and strobes are available. output wire M_AXI_WVALID, // Write ready. This signal indicates that the slave can accept the write data. input wire M_AXI_WREADY, // Master Interface Write Response Channel ports. // This signal indicates the status of the write transaction. input wire [1 : 0] M_AXI_BRESP, // Write response valid. // This signal indicates that the channel is signaling a valid write response input wire M_AXI_BVALID, // Response ready. This signal indicates that the master can accept a write response. output wire M_AXI_BREADY, // Master Interface Read Address Channel ports. Read address (issued by master) output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_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. output wire [2 : 0] M_AXI_ARPROT, // Read address valid. // This signal indicates that the channel is signaling valid read address and control information. output wire M_AXI_ARVALID, // Read address ready. // This signal indicates that the slave is ready to accept an address and associated control signals. input wire M_AXI_ARREADY, // Master Interface Read Data Channel ports. Read data (issued by slave) input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA, // Read response. This signal indicates the status of the read transfer. input wire [1 : 0] M_AXI_RRESP, // Read valid. This signal indicates that the channel is signaling the required read data. input wire M_AXI_RVALID, // Read ready. This signal indicates that the master can accept the read data and response information. output wire M_AXI_RREADY
识别方法:M_AXI作为前缀,表明是主机的AXI协议变量。AR开头的是读地址,AW开头的是写地址,R开头的是读数据,W开头的是写数据,B开头的是写响应。这是五个通道的基本判断(前面是后面的必要条件,但不是充分条件,即AR不一定是读地址,例如ARESETN是低电平复位信号,具体的看英文注释即可判断)。
(2)clogb2函数
function integer clogb2 (input integer bit_depth); begin for(clogb2=0; bit_depth>0; clogb2=clogb2+1) bit_depth = bit_depth >> 1; end endfunction
这个函数的功能就是返回一个整型变量的位宽深度(也就是二进制的有效数据,排除前面的多余0所剩下的位宽)。
(3)内部信号声明
xilinx的IP中端口信号一定是大写的,内部使用信号则是小写,方便阅读时判断信号是否为端口列表中的信号。端口信号需要考虑和其他模块连接的问题,二内部信号则没有这么多的考虑。
(4)初始化信号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
采用两级reg延时将INIT_AXI_TXN初始化信号接收过来。
(5)写地址通道的实现
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) 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) begin axi_awvalid <= 1'b0; end 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; end end
(6)写数据通道的实现
由于前面在从机的时候就详细地介绍了如何区分每个信号的作用。这里不再列举代码,对源码感兴趣的可以在vivado的工程中寻找。这里关注如何理解这些信号的变化,为理解时序图打下基础。
axi_wvalid受start_single_write控制拉高,由其他信号拉低。这个实际上需要对整个数据传输的流程有所认识,这里不做解释。
(7)写响应通道
axi_bready:等待握手信号,等待从机发送写完成后握手信号。
(8)读地址通道
read_index:读初始化信号
axi_arvalid:读地址通道的握手信号。
(9)读数据通道
axi_rready:读数据等待握手信号。
read_resp_error:读数据错误信号。
这里的基本功能和从机的lite形似,但是,作为主机,其还有重要的逻辑需要实现。在基本的通道构建完成后,还需要对其作为主机的协调和链接选择的功能实现。
二、系统功能
(1)写入地址
axi_awaddr在M_AXI_AWREADY和axi_awvalid握手成功后即写入地址32'h0000_0004的地址位。
//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
(2)写入数据
axi_wdata在写入数据握手成功后即可将初始化的数据write_index写入数据通道。具体实现和前面的写入地址是一致的。
(3)读地址
将axi_araddr通道加上想要读的地址即可实现。和前面的实现方式一样,都是等待握手成功后完成地址操作。由expected_rdata实现地址的接收。
(4)指令连接状态机
IDLE负责实现所有信号初始化。INIT_WRITE负责将初始化写信号。INIT_READ负责初始化读信号。INIT_COMPARE负责处理读写冲突信号。具有报错的作用。具体实现方法在代码中可以一一看到。
(5)终端写入统计
通过一个last_write信号表明写入数据的结束。可以切入时钟刻度得到数据写入的数量。
(6)最后写入校对
writes_done可以完成用于和last_write比较,校对写入的数据是否有正确的写响应信号。
(7)终端读取统计
last_read可以判断最后一位数据的读取完成。
(8)最后读取校对
reads_done可以在last_read基础上加上读握手判断,用于判断读数据是否成功。
(9)报错机制
read_mismatch用于数据的判断读信号是否匹配。error_reg用于判断存储的数据和传输的数据是否匹配。判断方法就是是否有错误的信号。
三、总结反思
相对于AXI4从机的协议,主机需要的内容显然更多,抽象的层次也不一样。从机可以直接得到通道的信号得到数据,而主机则需要更多的判断机制。需要使用线路判断逻辑和错误信号判断逻辑来支持数据的传输。这些额外的逻辑需要认真学习。事实上,其他的传输逻辑也是需要这些部分的辅助的。这个学会了,其他的也就触类旁通了。