// Master AXI Address Channel // This module performs a minimal AxADDR handshake, with the minimum number of // parameters and settings possible (no LOCK, CACHE, PROT, REGION, ID, etc...). // All transfers are AXI word-wide. // There are two interfaces: System and Control. // The System interface is where the host system sets the parameters for the // transaction. The address, burst length, and burst type are all set by // pulsing their _wren signal for one cycle. These parameters are persistent. // Then system_start must be pulsed high for one cycle. The system_ready flag // will go high when the transaction is done and stay high until a new // transaction is started. // The Control interface is internal to the AXI transactor and is controlled // by another AXI sequencer, which allows the channel to begin operating by // raising and holding control_enable high, until control_done also goes high // to signal completion, then both go low. It functions just like // a valid/ready handshake, thus it is an error to drop control_enable before // control_done is asserted. // Once both the System and Control interfaces are active, the address // transaction begins and any signaling on the system interface is ignored // until system_ready is raised. Thus, system_ready must be initialized high // before the first system transaction to avoid a special case. `default_nettype none module Master_AXI_Address_Channel #( parameter ADDR_WIDTH = 0, parameter AXSIZE = 0, // Do not alter at instantiation. Set by AXI4 spec. parameter AXLEN_WIDTH = 8, parameter AXSIZE_WIDTH = 3, parameter AXBURST_WIDTH = 2 ) ( input wire clock, // System interface input wire [ADDR_WIDTH-1:0] system_address, input wire system_address_wren, input wire [AXLEN_WIDTH-1:0] system_count, input wire system_count_wren, input wire [AXBURST_WIDTH-1:0] system_type, input wire system_type_wren, input wire system_start, output reg system_ready, // Control interface input wire control_enable, output reg control_done, // AXI interface output reg [ADDR_WIDTH-1:0] axaddr, output reg [AXLEN_WIDTH-1:0] axlen, output reg [AXSIZE_WIDTH-1:0] axsize, output reg [AXBURST_WIDTH-1:0] axburst, output reg axvalid, input wire axready ); // -------------------------------------------------------------------------- localparam AXADDR_ZERO = {ADDR_WIDTH{1'b0}}; localparam AXLEN_ZERO = {AXLEN_WIDTH{1'b0}}; localparam AXBURST_ZERO = {AXBURST_WIDTH{1'b0}}; // AXI word-wide transfers, so this never changes. localparam [AXSIZE_WIDTH-1:0] AXSIZE_INIT = AXSIZE [AXSIZE_WIDTH-1:0]; initial begin system_ready = 1'b0; control_done = 1'b0; axaddr = AXADDR_ZERO; axlen = AXLEN_ZERO; axsize = AXSIZE_INIT; axburst = AXBURST_ZERO; axvalid = 1'b0; end // -------------------------------------------------------------------------- reg transaction_complete = 1'b0; always @(*) begin transaction_complete = (axvalid == 1'b1) && (axready == 1'b1); control_done = transaction_complete; end // -------------------------------------------------------------------------- // Latch activation of system interface. Hold until transaction complete. wire system_start_set; pulse_to_level system_enable ( .clock (clock), .clear (transaction_complete), .pulse_in (system_start), .level_out (system_start_set) ); always @(*) begin system_ready = (system_start_set == 1'b0); end // -------------------------------------------------------------------------- // Once both interfaces are set, start the transaction. always @(*) begin axvalid = (control_enable == 1'b1) && (system_start_set == 1'b1); end // -------------------------------------------------------------------------- // If the system interface has not signaled to start a transaction, update the // AXI ports on a system write. always @(posedge clock) begin axaddr <= (system_address_wren == 1'b1) && (system_start_set == 1'b0) ? system_address : axaddr; axlen <= (system_count_wren == 1'b1) && (system_start_set == 1'b0) ? system_count : axlen; axburst <= (system_type_wren == 1'b1) && (system_start_set == 1'b0) ? system_type : axburst; end endmodule