1
0
mirror of https://github.com/bmartini/zynq-axis.git synced 2024-09-05 19:19:27 +08:00
zynq-axis/hdl/ctrl/axi4lite_cfg.v
2015-01-02 17:31:35 -05:00

182 lines
5.1 KiB
Verilog

`ifndef _axi4lite_cfg_ `define _axi4lite_cfg_
`timescale 1 ns / 1 ps
module axi4lite_cfg
#(parameter
integer AXI_WIDTH = 32,
integer CFG_AWIDTH = 5)
(input clk,
input rst,
output reg [AXI_WIDTH-1:0] cfg_wr_data,
output reg [CFG_AWIDTH-1:0] cfg_wr_addr,
output reg cfg_wr_en,
input [AXI_WIDTH-1:0] cfg_rd_data,
output reg [CFG_AWIDTH-1:0] cfg_rd_addr,
output reg cfg_rd_en,
input [AXI_WIDTH-1:0] axi_awaddr, // Write Address
input [2:0] axi_awprot, // Write Address Protection
input axi_awvalid, // Write Address Valid
output axi_awready, // Write Address Ready
input [AXI_WIDTH-1:0] axi_wdata, // Write Data
input [(AXI_WIDTH/8)-1:0] axi_wstrb, // Write Data Strobe
input axi_wvalid, // Write Data Valid
output axi_wready, // Write Data Ready
output [1:0] axi_bresp, // Write Response
output axi_bvalid, // Write Response Valid
input axi_bready, // Write Response Ready
input [AXI_WIDTH-1:0] axi_araddr, // Read Address
input [2:0] axi_arprot, // Read Address Protection
input axi_arvalid, // Read Address Valid
output reg axi_arready, // Read Address Ready
output [AXI_WIDTH-1:0] axi_rdata, // Read Data
output [1:0] axi_rresp, // Read Data Response
output reg axi_rvalid, // Read Data Valid
input axi_rready // Read Data Ready
);
/**
* Internal signals
*/
reg [AXI_WIDTH-1:0] axi_wr_addr;
wire axi_wr_valid;
reg axi_wr_ready;
/**
* Implementation Write Path
*/
// write response is always 'OKAY'
assign axi_bresp = 2'b0;
assign axi_bvalid = 1'b1;
// simplify write ready by making axi_awready be in sync with axi_wready
assign axi_awready = axi_wr_ready;
assign axi_wready = axi_wr_ready;
// write data and addresses are valid together
assign axi_wr_valid = axi_wr_ready && axi_wvalid && axi_awvalid;
// latch the address when both axi_awvalid and axi_wvalid are active
always @(posedge clk)
if (rst) begin
axi_wr_addr <= 'b0;
end
else if ( ~axi_wr_ready && axi_awvalid && axi_wvalid) begin
axi_wr_addr <= axi_awaddr;
end
// axi_wr_ready is only asserted for one clk clock cycle
always @(posedge clk) begin
if (rst) begin
axi_wr_ready <= 1'b0;
end
else begin
axi_wr_ready <= 1'b0;
if ( ~axi_wr_ready && axi_wvalid && axi_awvalid) begin
axi_wr_ready <= 1'b1;
end
end
end
// pass write data, address etc out of module
always @(posedge clk)
if (axi_wr_valid) cfg_wr_data <= axi_wdata;
always @(posedge clk) begin
cfg_wr_addr <= 'b0;
if (axi_wr_valid) begin
cfg_wr_addr <= axi_wr_addr[$clog2(AXI_WIDTH/8) +: CFG_AWIDTH];
end
end
always @(posedge clk)
if (rst) cfg_wr_en <= 1'b0;
else cfg_wr_en <= axi_wr_valid;
/**
* Implementation Read Path
*/
// axi_rresp indicates the status of read transaction.
assign axi_rresp = 2'b0; // 'OKAY' response
// The external code give cfg_rd_data a cycle after the valid read address and
// ready signals
assign axi_rdata = cfg_rd_data;
// Convert axi_araddr
always @(posedge clk) begin
cfg_rd_addr <= 'b0;
if ( ~axi_arready & axi_arvalid) begin
cfg_rd_addr <= axi_araddr[$clog2(AXI_WIDTH/8) +: CFG_AWIDTH];
end
end
always @(posedge clk)
if (rst) cfg_rd_en <= 1'b0;
else cfg_rd_en <= ~axi_arready & axi_arvalid;
// axi_arready is only asserted for one clk clock cycle
always @(posedge clk) begin
if (rst) begin
axi_arready <= 1'b0;
end
else begin
axi_arready <= 1'b0;
if ( ~axi_arready && axi_arvalid) begin
axi_arready <= 1'b1;
end
end
end
// axi_rvalid is only asserted for one clk clock cycle
always @(posedge clk) begin
if (rst) begin
axi_rvalid <= 1'b0;
end
else begin
if (axi_arready && axi_arvalid && ~axi_rvalid) begin
// Valid read data is available at the read data bus
axi_rvalid <= 1'b1;
end
else if (axi_rvalid && axi_rready) begin
// Read data is accepted by the master
axi_rvalid <= 1'b0;
end
end
end
endmodule
`endif // `ifndef _axi4lite_cfg_