Pushing the bulk of UHD-3.7.0 code.

Original-commit: ff1546f8137f7f92bb250f685561b0c34cc0e053
This commit is contained in:
Ben Hilburn
2014-02-14 12:05:07 -08:00
parent 29086f9001
commit fbbc991a7d
2194 changed files with 1489297 additions and 1084 deletions
+538
View File
@@ -0,0 +1,538 @@
`include "axi_defs.v"
`define DEBUG if (1)
module axi_dma_master
(
input aclk, // Global AXI clock
input areset, // Global AXI reset
//
// AXI Write address channel
//
output [0 : 0] m_axi_awid, // Write address ID. This signal is the identification tag for the write address signals
output reg [31 : 0] m_axi_awaddr, // Write address. The write address gives the address of the first transfer in a write burst
output reg [7 : 0] m_axi_awlen, // Burst length. The burst length gives the exact number of transfers in a burst.
output [2 : 0] m_axi_awsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_awburst, // Burst type. The burst type and the size information, determine how the address is calculated
output [0 : 0] m_axi_awlock, // Lock type. Provides additional information about the atomic characteristics of the transfer.
output [3 : 0] m_axi_awcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_awprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_awqos, // Quality of Service, QoS. The QoS identifier sent for each write transaction
output [3 : 0] m_axi_awregion, // Region identifier. Permits a single physical interface on a slave to be re-used.
output [0 : 0] m_axi_awuser, // User signal. Optional User-defined signal in the write address channel.
output reg m_axi_awvalid, // Write address valid. This signal indicates that the channel is signaling valid write addr
input m_axi_awready, // Write address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Write data channel.
//
output [63 : 0] m_axi_wdata, // Write data
output [7 : 0] m_axi_wstrb, // Write strobes. This signal indicates which byte lanes hold valid data.
output reg m_axi_wlast, // Write last. This signal indicates the last transfer in a write burst
output [0 : 0] m_axi_wuser, // User signal. Optional User-defined signal in the write data channel.
output m_axi_wvalid, // Write valid. This signal indicates that valid write data and strobes are available.
input m_axi_wready, // Write ready. This signal indicates that the slave can accept the write data.
//
// AXI Write response channel signals
//
input [0 : 0] m_axi_bid, // Response ID tag. This signal is the ID tag of the write response.
input [1 : 0] m_axi_bresp, // Write response. This signal indicates the status of the write transaction.
input [0 : 0] m_axi_buser, // User signal. Optional User-defined signal in the write response channel.
input m_axi_bvalid, // Write response valid. This signal indicates that the channel is signaling a valid response
output reg m_axi_bready, // Response ready. This signal indicates that the master can accept a write response
//
// AXI Read address channel
//
output [0 : 0] m_axi_arid, // Read address ID. This signal is the identification tag for the read address group of signals
output reg [31 : 0] m_axi_araddr, // Read address. The read address gives the address of the first transfer in a read burst
output reg [7 : 0] m_axi_arlen, // Burst length. This signal indicates the exact number of transfers in a burst.
output [2 : 0] m_axi_arsize, // Burst size. This signal indicates the size of each transfer in the burst.
output [1 : 0] m_axi_arburst, // Burst type. The burst type and the size information determine how the address for each transfer
output [0 : 0] m_axi_arlock, // Lock type. This signal provides additional information about the atomic characteristics
output [3 : 0] m_axi_arcache, // Memory type. This signal indicates how transactions are required to progress
output [2 : 0] m_axi_arprot, // Protection type. This signal indicates the privilege and security level of the transaction
output [3 : 0] m_axi_arqos, // Quality of Service, QoS. QoS identifier sent for each read transaction.
output [3 : 0] m_axi_arregion, // Region identifier. Permits a single physical interface on a slave to be re-used
output [0 : 0] m_axi_aruser, // User signal. Optional User-defined signal in the read address channel.
output reg m_axi_arvalid, // Read address valid. This signal indicates that the channel is signaling valid read addr
input m_axi_arready, // Read address ready. This signal indicates that the slave is ready to accept an address
//
// AXI Read data channel
//
input [0 : 0] m_axi_rid, // Read ID tag. This signal is the identification tag for the read data group of signals
input [63 : 0] m_axi_rdata, // Read data.
input [1 : 0] m_axi_rresp, // Read response. This signal indicates the status of the read transfer
input m_axi_rlast, // Read last. This signal indicates the last transfer in a read burst.
input [0 : 0] m_axi_ruser, // User signal. Optional User-defined signal in the read data channel.
input m_axi_rvalid, // Read valid. This signal indicates that the channel is signaling the required read data.
output m_axi_rready, // Read ready. This signal indicates that the master can accept the read data and response
//
// DMA interface for Write transaction
//
input [31:0] write_addr, // Byte address for start of write transaction (should be 64bit alligned)
input [7:0] write_count, // Count of 64bit words to write. (minus one)
input write_ctrl_valid,
output reg write_ctrl_ready,
input [63:0] write_data,
input write_data_valid,
output write_data_ready,
//
// DMA interface for Read
//
input [31:0] read_addr, // Byte address for start of read transaction (should be 64bit alligned)
input [7:0] read_count, // Count of 64bit words to read.
input read_ctrl_valid,
output reg read_ctrl_ready,
output [63:0] read_data,
output read_data_valid,
input read_data_ready,
//
// Debug Bus
//
output [31:0] debug
);
localparam AW_IDLE = 0;
localparam WAIT_AWREADY = 1;
localparam WAIT_BVALID = 2;
localparam AW_ERROR = 3;
reg [1:0] write_addr_state;
reg [7:0] write_data_count; // Count write transfers.
reg enable_data_write;
localparam DW_IDLE = 0;
localparam DW_RUN = 1;
localparam DW_LAST = 2;
reg [1:0] write_data_state;
localparam AR_IDLE = 0;
localparam WAIT_ARREADY = 1;
localparam WAIT_READ_DONE = 2;
localparam AR_ERROR = 3;
reg [1:0] read_addr_state;
localparam DR_IDLE = 0;
localparam DR_RUN = 1;
localparam DR_WAIT_ERROR = 2;
localparam DR_ERROR = 3;
reg [1:0] read_data_state;
reg [7:0] read_data_count;
reg enable_data_read;
///////////////////////////
// DEBUG
///////////////////////////
assign debug= {24'h0,write_addr_state[1:0],write_data_state[1:0],read_addr_state[1:0],read_data_state[1:0]};
//
//
//
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Write address channel
//
/////////////////////////////////////////////////////////////////////////////////
assign m_axi_awid = 1'b0;
assign m_axi_awsize = 3'h3; // 8 bytes.
assign m_axi_awburst = `AXI4_BURST_INCR;
assign m_axi_awlock = `AXI4_LOCK_NORMAL;
assign m_axi_awcache = `AXI4_CACHE_ALLOCATE | `AXI4_CACHE_OTHER_ALLOCATE | `AXI4_CACHE_MODIFIABLE | `AXI4_CACHE_BUFFERABLE;
assign m_axi_awprot = `AXI4_PROT_NON_SECURE;
assign m_axi_awqos = 4'h0;
assign m_axi_awregion = 4'h0;
assign m_axi_awuser = 1'b0;
//
// AXI Write address state machine
//
always @(posedge aclk)
if (areset) begin
write_ctrl_ready <= 1'b0;
write_addr_state <= AW_IDLE;
m_axi_awaddr[31:0] <= 32'h0;
m_axi_awlen[7:0] <= 8'h0;
m_axi_awvalid <= 1'b0;
m_axi_bready <= 1'b0;
end else
case (write_addr_state)
//
// AW_IDLE
// We are ready to accept a new write transaction.
//
AW_IDLE: begin
// Premptively accept new write transaction since we are idle.
write_ctrl_ready <= 1'b1;
// No need to be waiting for a response while idle.
m_axi_bready <= 1'b0;
// If we are offered a new transaction then.....
if (write_ctrl_valid) begin
// Drive all the relevent AXI4 write address channel signals next cycle.
m_axi_awaddr[31:0] <= write_addr[31:0];
m_axi_awlen[7:0] <= {write_count};
m_axi_awvalid <= 1'b1;
// If the AXI4 write channel is pre-emptively accepting the transaction...
if (m_axi_awready == 1'b1) begin
// ...go straight to looking for a transaction response...
`DEBUG $display("WRITE TRANSACTION: ADDR: %x LEN: %x @ time %d",write_addr[31:0],write_count,$time);
write_addr_state <= WAIT_BVALID;
m_axi_bready <= 1'b1;
end else begin
// ...otherwise wait to get the transaction accepted.
write_addr_state <= WAIT_AWREADY;
end
end
end
//
// WAIT_AWREADY
// Waiting for AXI4 slave to accept new write transaction.
//
WAIT_AWREADY: begin
write_ctrl_ready <= 1'b0;
// If the AXI4 write channel is accepting the transaction...
if (m_axi_awready == 1'b1) begin
// ...go to looking for a transaction response...
write_addr_state <= WAIT_BVALID;
m_axi_bready <= 1'b1;
`DEBUG $display("WRITE TRANSACTION: ADDR: %x LEN: %x @ time %d",m_axi_awaddr[31:0],m_axi_awlen[7:0],$time);
end else begin
// ...otherwise wait to get the trasaction accepted.
write_addr_state <= WAIT_AWREADY;
end
end // case: WAIT_AWREADY
//
// WAIT_BVALID
// Write transaction has been accepted, now waiting for a response to signal it's sucsesful.
// Ignoring ID tag for the moment
//
WAIT_BVALID: begin
write_ctrl_ready <= 1'b0;
m_axi_awvalid <= 1'b0;
// Wait for response channel to signal how write transaction went down....
if (m_axi_bvalid == 1'b1) begin
if ((m_axi_bresp == `AXI4_RESP_OKAY) || (m_axi_bresp == `AXI4_RESP_EXOKAY)) begin
// ....it went well, we are ready to start something new.
write_addr_state <= AW_IDLE;
m_axi_bready <= 1'b0;
write_ctrl_ready <= 1'b1; // Ready to run again as soon as we hit idle.
end else if ((m_axi_bresp == `AXI4_RESP_SLVERR) || (m_axi_bresp == `AXI4_RESP_DECERR)) begin
// ....things got ugly, retreat to an error stat and wait for intervention.
write_addr_state <= AW_ERROR;
m_axi_bready <= 1'b0;
end
end else begin
write_addr_state <= WAIT_BVALID;
m_axi_bready <= 1'b1;
end
end // case: WAIT_BVALID
//
// AW_ERROR
// Something bad happened, going to need external intervention to restore a safe state.
//
AW_ERROR: begin
write_ctrl_ready <= 1'b0;
write_addr_state <= AW_ERROR;
m_axi_awaddr[31:0] <= 32'h0;
m_axi_awlen[7:0] <= 8'h0;
m_axi_awvalid <= 1'b0;
m_axi_bready <= 1'b0;
end
endcase // case(write_addr_state)
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Write data channel
//
/////////////////////////////////////////////////////////////////////////////////
assign m_axi_wstrb = 8'hff;
assign m_axi_wuser = 1'b0;
//
// AXI Write data state machine
//
always @(posedge aclk)
if (areset) begin
write_data_state <= AW_IDLE;
write_data_count <= 1;
enable_data_write <= 1'b0;
m_axi_wlast <= 1'b0;
end else
case (write_data_state)
//
// DW_IDLE
// Sit in this state until presented with the control details of a new write transaction.
//
DW_IDLE: begin
write_data_count <= 1;
m_axi_wlast <= 1'b0;
if (write_ctrl_valid && write_ctrl_ready) begin
enable_data_write <= 1'b1;
if (write_count[7:0] == 8'h0) begin
// Single transfer transaction
write_data_state <= DW_LAST;
m_axi_wlast <= 1'b1;
end else begin
write_data_state <= DW_RUN;
end
end else begin
write_data_state <= DW_IDLE;
end
end
//
// DW_RUN
//
DW_RUN : begin
enable_data_write <= 1'b1;
m_axi_wlast <= 1'b0;
if (write_data_valid && m_axi_wready) begin
// Single write transfer
write_data_count <= write_data_count + 1;
if (write_data_count == m_axi_awlen[7:0]) begin
write_data_state <= DW_LAST;
m_axi_wlast <= 1'b1;
end else begin
write_data_state <= DW_RUN;
end
end else begin
write_data_state <= DW_RUN;
end
end
//
// DW_LAST
//
DW_LAST: begin
if (write_data_valid && m_axi_wready) begin
enable_data_write <= 1'b0;
write_data_state <= DW_IDLE;
m_axi_wlast <= 1'b0;
end else begin
enable_data_write <= 1'b1;
write_data_state <= DW_LAST;
m_axi_wlast <= 1'b1;
end
end // case: DW_LAST
//
default:
write_data_state <= DW_IDLE;
endcase // case(write_data_state)
assign m_axi_wdata = write_data;
assign m_axi_wvalid = enable_data_write && write_data_valid;
assign write_data_ready = enable_data_write && m_axi_wready;
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Read address channel
//
/////////////////////////////////////////////////////////////////////////////////
assign m_axi_arid = 1'b0;
assign m_axi_arsize = 3'h3; // 8 bytes
assign m_axi_arburst = `AXI4_BURST_INCR;
assign m_axi_arlock = `AXI4_LOCK_NORMAL;
assign m_axi_arcache = `AXI4_CACHE_ALLOCATE | `AXI4_CACHE_OTHER_ALLOCATE | `AXI4_CACHE_MODIFIABLE | `AXI4_CACHE_BUFFERABLE;
assign m_axi_arprot = `AXI4_PROT_NON_SECURE;
assign m_axi_arqos = 4'h0;
assign m_axi_arregion = 4'h0;
assign m_axi_aruser = 1'b0;
//
// AXI Read address state machine
//
always @(posedge aclk)
if (areset) begin
read_ctrl_ready <= 1'b0;
read_addr_state <= AR_IDLE;
m_axi_araddr[31:0] <= 32'h0;
m_axi_arlen[7:0] <= 8'h0;
m_axi_arvalid <= 1'b0;
end else
case (read_addr_state)
//
// AR_IDLE
// We are ready to accept a new read transaction.
//
AR_IDLE: begin
// Premptively accept new read transaction since we are idle.
read_ctrl_ready <= 1'b1;
// If we are offered a new transaction then.....
if (read_ctrl_valid) begin
// Drive all the relevent AXI4 read address channel signals next cycle.
m_axi_araddr[31:0] <= read_addr[31:0];
m_axi_arlen[7:0] <= {read_count};
m_axi_arvalid <= 1'b1;
// If the AXI4 read channel is pre-emptively accepting the transaction...
if (m_axi_arready == 1'b1) begin
// ...go straight to looking for the transaction to complete
`DEBUG $display("READ TRANSACTION: ADDR: %x LEN: %x @ time %d",read_addr[31:0],read_count,$time);
read_addr_state <= WAIT_READ_DONE;
end else begin
// ...otherwise wait to get the transaction accepted.
read_addr_state <= WAIT_ARREADY;
end
end
end
//
// WAIT_ARREADY
// Waiting for AXI4 slave to accept new read transaction.
//
WAIT_ARREADY: begin
read_ctrl_ready <= 1'b0;
// If the AXI4 read channel is accepting the transaction...
if (m_axi_arready == 1'b1) begin
// ...go to looking for the transaction to complete...
read_addr_state <= WAIT_READ_DONE;
`DEBUG $display("READ TRANSACTION: ADDR: %x LEN: %x @ time %d",m_axi_araddr[31:0],m_axi_arlen[7:0],$time);
end else begin
// ...otherwise wait to get the trasaction accepted.
read_addr_state <= WAIT_ARREADY;
end
end // case: WAIT_ARREADY
//
// WAIT_READ_DONE
// Read transaction has been accepted, now waiting for the data transfer to complete
// Ignoring ID tag for the moment
//
WAIT_READ_DONE: begin
read_ctrl_ready <= 1'b0;
m_axi_arvalid <= 1'b0;
// Wait for read transaction to complete
if (read_data_state == DR_IDLE) begin
// ....it went well, we are ready to start something new.
read_addr_state <= AR_IDLE;
read_ctrl_ready <= 1'b1; // Ready to run again as soon as we hit idle.
end else if (read_data_state == DR_ERROR) begin
// ....things got ugly, retreat to an error stat and wait for intervention.
read_addr_state <= AR_ERROR;
end else begin
read_addr_state <= WAIT_READ_DONE;
end
end // case: WAIT_BVALID
//
// AR_ERROR
// Something bad happened, going to need external intervention to restore a safe state.
//
AR_ERROR: begin
read_ctrl_ready <= 1'b0;
read_addr_state <= AR_ERROR;
m_axi_araddr[31:0] <= 32'h0;
m_axi_arlen[7:0] <= 8'h0;
m_axi_arvalid <= 1'b0;
end
endcase // case(read_addr_state)
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Read data channel
//
/////////////////////////////////////////////////////////////////////////////////
//
// AXI Read data state machine
//
always @(posedge aclk)
if (areset) begin
read_data_state <= AR_IDLE;
read_data_count <= 0;
enable_data_read <= 1'b0;
end else
case (read_data_state)
//
// DR_IDLE
// Sit in this state until presented with the control details of a new read transaction.
//
DR_IDLE: begin
read_data_count <= 0;
if (read_ctrl_valid && read_ctrl_ready) begin
enable_data_read <= 1'b1;
read_data_state <= DR_RUN;
end else begin
read_data_state <= DR_IDLE;
end
end
//
// DR_RUN
// Sit here counting read transfers. If any have error's shift to error state.
//
DR_RUN : begin
enable_data_read <= 1'b1;
if (read_data_ready && m_axi_rvalid) begin
// Single read transfer
read_data_count <= read_data_count + 1;
if ((m_axi_rresp == `AXI4_RESP_SLVERR) || (m_axi_rresp == `AXI4_RESP_DECERR)) begin
if (m_axi_rlast) begin
read_data_state <= DR_ERROR;
end else begin
read_data_state <= DR_WAIT_ERROR;
end
end else if (m_axi_rlast) begin // Implicitly good response signalled this transfer.
if (read_data_count == m_axi_arlen[7:0]) begin
read_data_state <= DR_IDLE;
end else begin
read_data_state <= DR_ERROR;
end
end else begin
read_data_state <= DR_RUN;
end
end else begin
read_data_state <= DR_RUN;
end
end
//
// DR_WAIT_ERROR
// Something bad happened, wait for last signalled in this burst
//
DR_WAIT_ERROR: begin
if (read_data_ready && m_axi_rvalid && m_axi_rlast) begin
enable_data_read <= 1'b0;
read_data_state <= DR_ERROR;
end else begin
enable_data_read <= 1'b1;
read_data_state <= DR_WAIT_ERROR;
end
end // case: DR_WAIT_ERROR
//
// DR_ERROR
// Something bad happened, going to need external intervention to restore a safe state.
//
DR_ERROR: begin
enable_data_read <= 1'b0;
read_data_state <= DR_ERROR;
end // case: DR_ERROR
endcase // case(read_data_state)
assign read_data = m_axi_rdata;
assign m_axi_rready = enable_data_read && read_data_ready;
assign read_data_valid = enable_data_read && m_axi_rvalid;
endmodule // axi_dma_master