mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-17 20:02:53 +08:00
Removing unecessary levels of hiearchy
This commit is contained in:
parent
239ca128c2
commit
d4d1cd3500
@ -1,551 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2014 Adapteva, Inc.
|
||||
Contributed by Fred Huettig <fred@adapteva.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program (see the file COPYING). If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*
|
||||
########################################################################
|
||||
Epiphany eLink AXI Master Module
|
||||
########################################################################
|
||||
|
||||
*/
|
||||
|
||||
`define WRITE_BIT 102
|
||||
`define DATAMODE_RANGE 101:100
|
||||
`define CTRLMODE_RANGE 99:96
|
||||
`define DSTADDR_RANGE 95:64
|
||||
`define DSTADDR_LSB 64
|
||||
`define SRCADDR_RANGE 63:32
|
||||
`define SRCADDR_LSB 32
|
||||
`define DATA_RANGE 31:0
|
||||
`define DATA_LSB 0
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
module emaxi_v1_0_M00_AXI #
|
||||
(
|
||||
// Users to add parameters here
|
||||
|
||||
// User parameters ends
|
||||
// Do not modify the parameters beyond this line
|
||||
|
||||
// Base address of targeted slave
|
||||
parameter C_M_TARGET_SLAVE_BASE_ADDR = 32'h40000000,
|
||||
// Burst Length. Supports 1, 2, 4, 8, 16, 32, 64, 128, 256 burst lengths
|
||||
parameter integer C_M_AXI_BURST_LEN = 16,
|
||||
// Thread ID Width
|
||||
parameter integer C_M_AXI_ID_WIDTH = 1,
|
||||
// Width of Address Bus
|
||||
parameter integer C_M_AXI_ADDR_WIDTH = 32,
|
||||
// Width of Data Bus
|
||||
parameter integer C_M_AXI_DATA_WIDTH = 64,
|
||||
// Width of User Write Address Bus
|
||||
parameter integer C_M_AXI_AWUSER_WIDTH = 0,
|
||||
// Width of User Read Address Bus
|
||||
parameter integer C_M_AXI_ARUSER_WIDTH = 0,
|
||||
// Width of User Write Data Bus
|
||||
parameter integer C_M_AXI_WUSER_WIDTH = 0,
|
||||
// Width of User Read Data Bus
|
||||
parameter integer C_M_AXI_RUSER_WIDTH = 0,
|
||||
// Width of User Response Bus
|
||||
parameter integer C_M_AXI_BUSER_WIDTH = 0
|
||||
)
|
||||
(
|
||||
// Users to add ports here
|
||||
// FIFO read-master port, writes from RX channel
|
||||
input wire [102:0] emwr_rd_data,
|
||||
output wire emwr_rd_en,
|
||||
input wire emwr_empty,
|
||||
|
||||
// FIFO read-master port, read requests from RX channel
|
||||
input wire [102:0] emrq_rd_data,
|
||||
output wire emrq_rd_en,
|
||||
input wire emrq_empty,
|
||||
|
||||
// FIFO write-master port, read responses to TX channel
|
||||
output reg [102:0] emrr_wr_data,
|
||||
output reg emrr_wr_en,
|
||||
input wire emrr_full,
|
||||
input wire emrr_prog_full,
|
||||
|
||||
// User ports ends
|
||||
// Do not modify the ports beyond this line
|
||||
|
||||
// Global Clock Signal.
|
||||
input wire M_AXI_ACLK,
|
||||
// Global Reset Singal. This Signal is Active Low
|
||||
input wire M_AXI_ARESETN,
|
||||
// Master Interface Write Address ID
|
||||
output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_AWID,
|
||||
// Master Interface Write Address
|
||||
output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,
|
||||
// Burst length. The burst length gives the exact number of transfers in a burst
|
||||
output wire [7 : 0] M_AXI_AWLEN,
|
||||
// Burst size. This signal indicates the size of each transfer in the burst
|
||||
output wire [2 : 0] M_AXI_AWSIZE,
|
||||
// Burst type. The burst type and the size information,
|
||||
// determine how the address for each transfer within the burst is calculated.
|
||||
output wire [1 : 0] M_AXI_AWBURST,
|
||||
// Lock type. Provides additional information about the
|
||||
// atomic characteristics of the transfer.
|
||||
output wire M_AXI_AWLOCK,
|
||||
// Memory type. This signal indicates how transactions
|
||||
// are required to progress through a system.
|
||||
output wire [3 : 0] M_AXI_AWCACHE,
|
||||
// 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,
|
||||
// Quality of Service, QoS identifier sent for each write transaction.
|
||||
output wire [3 : 0] M_AXI_AWQOS,
|
||||
// Optional User-defined signal in the write address channel.
|
||||
output wire [C_M_AXI_AWUSER_WIDTH-1 : 0] M_AXI_AWUSER,
|
||||
// Write address valid. This signal indicates that
|
||||
// the channel is 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.
|
||||
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 last. This signal indicates the last transfer in a write burst.
|
||||
output wire M_AXI_WLAST,
|
||||
// Optional User-defined signal in the write data channel.
|
||||
output wire [C_M_AXI_WUSER_WIDTH-1 : 0] M_AXI_WUSER,
|
||||
// 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.
|
||||
input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_BID,
|
||||
// Write response. This signal indicates the status of the write transaction.
|
||||
input wire [1 : 0] M_AXI_BRESP,
|
||||
// Optional User-defined signal in the write response channel
|
||||
input wire [C_M_AXI_BUSER_WIDTH-1 : 0] M_AXI_BUSER,
|
||||
// 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.
|
||||
output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_ARID,
|
||||
// Read address. This signal indicates the initial
|
||||
// address of a read burst transaction.
|
||||
output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR,
|
||||
// Burst length. The burst length gives the exact number of transfers in a burst
|
||||
output wire [7 : 0] M_AXI_ARLEN,
|
||||
// Burst size. This signal indicates the size of each transfer in the burst
|
||||
output wire [2 : 0] M_AXI_ARSIZE,
|
||||
// Burst type. The burst type and the size information,
|
||||
// determine how the address for each transfer within the burst is calculated.
|
||||
output wire [1 : 0] M_AXI_ARBURST,
|
||||
// Lock type. Provides additional information about the
|
||||
// atomic characteristics of the transfer.
|
||||
output wire M_AXI_ARLOCK,
|
||||
// Memory type. This signal indicates how transactions
|
||||
// are required to progress through a system.
|
||||
output wire [3 : 0] M_AXI_ARCACHE,
|
||||
// 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,
|
||||
// Quality of Service, QoS identifier sent for each read transaction
|
||||
output wire [3 : 0] M_AXI_ARQOS,
|
||||
// Optional User-defined signal in the read address channel.
|
||||
output wire [C_M_AXI_ARUSER_WIDTH-1 : 0] M_AXI_ARUSER,
|
||||
// Write 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,
|
||||
// Read ID tag. This signal is the identification tag
|
||||
// for the read data group of signals generated by the slave.
|
||||
input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_RID,
|
||||
// Master Read Data
|
||||
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 last. This signal indicates the last transfer in a read burst
|
||||
input wire M_AXI_RLAST,
|
||||
// Optional User-defined signal in the read address channel.
|
||||
input wire [C_M_AXI_RUSER_WIDTH-1 : 0] M_AXI_RUSER,
|
||||
// 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
|
||||
);
|
||||
|
||||
|
||||
// function called clogb2 that returns an integer which has the
|
||||
//value of the ceiling of the log base 2
|
||||
|
||||
// function called clogb2 that returns an integer which has the
|
||||
// value of the ceiling of the log base 2.
|
||||
function integer clogb2 (input integer bit_depth);
|
||||
begin
|
||||
for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
|
||||
bit_depth = bit_depth >> 1;
|
||||
end
|
||||
endfunction // clogb2
|
||||
|
||||
// AXI4LITE signals
|
||||
//AXI4 internal temp signals
|
||||
reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
|
||||
reg [7:0] axi_awlen;
|
||||
reg [2:0] axi_awsize;
|
||||
reg axi_awvalid;
|
||||
|
||||
reg [C_M_AXI_DATA_WIDTH-1 : 0] axi_wdata;
|
||||
reg [C_M_AXI_DATA_WIDTH/8-1 : 0] axi_wstrb;
|
||||
reg axi_wlast;
|
||||
reg axi_wvalid;
|
||||
|
||||
//reg axi_bready;
|
||||
|
||||
wire [C_M_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
|
||||
wire [7:0] axi_arlen;
|
||||
wire [2:0] axi_arsize;
|
||||
wire axi_arvalid;
|
||||
|
||||
wire axi_rready;
|
||||
|
||||
// I/O Connections assignments
|
||||
|
||||
//I/O Connections. Write Address (AW)
|
||||
assign M_AXI_AWID = 'b0;
|
||||
//The AXI address is a concatenation of the target base address + active offset range
|
||||
assign M_AXI_AWADDR = axi_awaddr;
|
||||
//Burst LENgth is number of transaction beats, minus 1
|
||||
assign M_AXI_AWLEN = axi_awlen;
|
||||
//Size should be C_M_AXI_DATA_WIDTH, in 2^SIZE bytes, otherwise narrow bursts are used
|
||||
assign M_AXI_AWSIZE = axi_awsize;
|
||||
//INCR burst type is usually used, except for keyhole bursts
|
||||
assign M_AXI_AWBURST = 2'b01;
|
||||
assign M_AXI_AWLOCK = 1'b0;
|
||||
//Update value to 4'b0011 if coherent accesses to be used via the Zynq ACP port. Not Allocated, Modifiable, not Bufferable. Not Bufferable since this example is meant to test memory, not intermediate cache.
|
||||
assign M_AXI_AWCACHE = 4'b0010;
|
||||
assign M_AXI_AWPROT = 3'h0;
|
||||
assign M_AXI_AWQOS = 4'h0;
|
||||
assign M_AXI_AWUSER = 'b1;
|
||||
assign M_AXI_AWVALID = axi_awvalid;
|
||||
//Write Data(W)
|
||||
assign M_AXI_WDATA = axi_wdata;
|
||||
//All bursts are complete and aligned in this example
|
||||
assign M_AXI_WSTRB = axi_wstrb;
|
||||
assign M_AXI_WLAST = axi_wlast;
|
||||
assign M_AXI_WUSER = 'b0;
|
||||
assign M_AXI_WVALID = axi_wvalid;
|
||||
//Write Response (B)
|
||||
assign M_AXI_BREADY = 1'b1; // axi_bready;
|
||||
//Read Address (AR)
|
||||
assign M_AXI_ARID = 'b0;
|
||||
assign M_AXI_ARADDR = axi_araddr;
|
||||
//Burst LENgth is number of transaction beats, minus 1
|
||||
assign M_AXI_ARLEN = axi_arlen;
|
||||
//Size should be C_M_AXI_DATA_WIDTH, in 2^n bytes, otherwise narrow bursts are used
|
||||
assign M_AXI_ARSIZE = axi_arsize;
|
||||
//INCR burst type is usually used, except for keyhole bursts
|
||||
assign M_AXI_ARBURST = 2'b01;
|
||||
assign M_AXI_ARLOCK = 1'b0;
|
||||
//Update value to 4'b0011 if coherent accesses to be used via the Zynq ACP port. Not Allocated, Modifiable, not Bufferable. Not Bufferable since this example is meant to test memory, not intermediate cache.
|
||||
assign M_AXI_ARCACHE = 4'b0010;
|
||||
assign M_AXI_ARPROT = 3'h0;
|
||||
assign M_AXI_ARQOS = 4'h0;
|
||||
assign M_AXI_ARUSER = 'b1;
|
||||
assign M_AXI_ARVALID = axi_arvalid;
|
||||
//Read and Read Response (R)
|
||||
assign M_AXI_RREADY = axi_rready;
|
||||
|
||||
//--------------------
|
||||
//Write Address Channel
|
||||
//--------------------
|
||||
|
||||
// Holding buffers for AW and W channels
|
||||
reg awvalid_b;
|
||||
reg [C_M_AXI_ADDR_WIDTH-1 : 0] awaddr_b;
|
||||
reg [2:0] awsize_b;
|
||||
reg [7:0] awlen_b;
|
||||
|
||||
reg wvalid_b;
|
||||
reg [C_M_AXI_DATA_WIDTH-1 : 0] wdata_b;
|
||||
reg [C_M_AXI_DATA_WIDTH/8-1 : 0] wstrb_b;
|
||||
|
||||
wire aw_go = axi_awvalid & M_AXI_AWREADY;
|
||||
wire w_go = axi_wvalid & M_AXI_WREADY;
|
||||
|
||||
assign emwr_rd_en = ( ~emwr_empty & ~awvalid_b & ~wvalid_b);
|
||||
|
||||
// Generate write-address signals
|
||||
always @( posedge M_AXI_ACLK ) begin
|
||||
if( M_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_awvalid <= 1'b0;
|
||||
axi_awaddr <= 'd0;
|
||||
axi_awlen <= 'd0;
|
||||
axi_awsize <= 'd0;
|
||||
|
||||
awvalid_b <= 1'b0;
|
||||
awaddr_b <= 'd0;
|
||||
awlen_b <= 'd0;
|
||||
awsize_b <= 'd0;
|
||||
|
||||
end else begin
|
||||
|
||||
if( ~axi_awvalid | aw_go ) begin
|
||||
if( awvalid_b ) begin
|
||||
axi_awvalid <= 1'b1;
|
||||
axi_awaddr <= awaddr_b;
|
||||
axi_awlen <= awlen_b;
|
||||
axi_awsize <= awsize_b;
|
||||
end else begin
|
||||
axi_awvalid <= emwr_rd_en;
|
||||
axi_awaddr <= emwr_rd_data[`DSTADDR_RANGE];
|
||||
axi_awlen <= 'd0;
|
||||
axi_awsize <= { 1'b0, emwr_rd_data[`DATAMODE_RANGE] };
|
||||
end // else: !if(awvalid_b)
|
||||
end // if (~axi_awvalid | aw_go)
|
||||
|
||||
if( emwr_rd_en & axi_awvalid & ~aw_go )
|
||||
awvalid_b <= 1'b1;
|
||||
else if( aw_go )
|
||||
awvalid_b <= 1'b0;
|
||||
|
||||
if( emwr_rd_en ) begin
|
||||
awaddr_b <= emwr_rd_data[`DSTADDR_RANGE];
|
||||
awlen_b <= 'd0;
|
||||
awsize_b <= { 1'b0, emwr_rd_data[`DATAMODE_RANGE] };
|
||||
end
|
||||
|
||||
end // else: !if( M_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge M_AXI_ACLK )
|
||||
|
||||
reg [C_M_AXI_DATA_WIDTH-1 : 0] wdata_aligned;
|
||||
reg [C_M_AXI_DATA_WIDTH/8-1 : 0] wstrb_aligned;
|
||||
|
||||
always @ ( emwr_rd_data ) begin
|
||||
|
||||
// Place data of stated size in all legal positions
|
||||
case( emwr_rd_data[`DATAMODE_RANGE] )
|
||||
|
||||
2'd0: wdata_aligned = { 8{emwr_rd_data[`DATA_LSB+7 -: 8]}};
|
||||
2'd1: wdata_aligned = { 4{emwr_rd_data[`DATA_LSB+15 -: 16]}};
|
||||
2'd2: wdata_aligned = { 2{emwr_rd_data[`DATA_LSB+31 -: 32]}};
|
||||
default: wdata_aligned = { emwr_rd_data[`SRCADDR_RANGE],
|
||||
emwr_rd_data[`DATA_RANGE]};
|
||||
endcase // case ( emwr_rd_data[`DATAMODE_RANGE] )
|
||||
|
||||
// Create write strobes
|
||||
case( emwr_rd_data[`DATAMODE_RANGE] )
|
||||
2'd0: // BYTE
|
||||
case( emwr_rd_data[`DSTADDR_LSB+2 -: 3] )
|
||||
3'd0: wstrb_aligned = 8'h01;
|
||||
3'd1: wstrb_aligned = 8'h02;
|
||||
3'd2: wstrb_aligned = 8'h04;
|
||||
3'd3: wstrb_aligned = 8'h08;
|
||||
3'd4: wstrb_aligned = 8'h10;
|
||||
3'd5: wstrb_aligned = 8'h20;
|
||||
3'd6: wstrb_aligned = 8'h40;
|
||||
default: wstrb_aligned = 8'h80;
|
||||
endcase
|
||||
|
||||
2'd1: // 16b HWORD
|
||||
case( emwr_rd_data[`DSTADDR_LSB+2 -: 2] )
|
||||
2'd0: wstrb_aligned = 8'h03;
|
||||
2'd1: wstrb_aligned = 8'h0C;
|
||||
2'd2: wstrb_aligned = 8'h30;
|
||||
default: wstrb_aligned = 8'hC0;
|
||||
endcase
|
||||
|
||||
2'd2: // 32b WORD
|
||||
if( emwr_rd_data[`DSTADDR_LSB+2] )
|
||||
wstrb_aligned = 8'hF0;
|
||||
else
|
||||
wstrb_aligned = 8'h0F;
|
||||
|
||||
default: // 64b DWORD
|
||||
wstrb_aligned = 8'hFF;
|
||||
|
||||
endcase // case ( emwr_rd_data[`DATAMODE_RANGE] )
|
||||
end // always @ (...
|
||||
|
||||
// Generate the write-data signals
|
||||
always @( posedge M_AXI_ACLK ) begin
|
||||
if( M_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_wvalid <= 1'b0;
|
||||
axi_wdata <= 'd0;
|
||||
axi_wstrb <= 'd0;
|
||||
axi_wlast <= 1'b1; // TODO: no bursts for now
|
||||
|
||||
wvalid_b <= 1'b0;
|
||||
wdata_b <= 'd0;
|
||||
wstrb_b <= 'd0;
|
||||
|
||||
end else begin // if ( M_AXI_ARESETN == 1'b0 )
|
||||
|
||||
if( ~axi_wvalid | w_go ) begin
|
||||
if( wvalid_b ) begin
|
||||
axi_wvalid <= 1'b1;
|
||||
axi_wdata <= wdata_b;
|
||||
axi_wstrb <= wstrb_b;
|
||||
end else begin
|
||||
axi_wvalid <= emwr_rd_en;
|
||||
axi_wdata <= wdata_aligned;
|
||||
axi_wstrb <= wstrb_aligned;
|
||||
end
|
||||
end // if ( ~axi_wvalid | w_go )
|
||||
|
||||
if( emwr_rd_en & axi_wvalid & ~w_go )
|
||||
wvalid_b <= 1'b1;
|
||||
else if( w_go )
|
||||
wvalid_b <= 1'b0;
|
||||
|
||||
if( emwr_rd_en ) begin
|
||||
wdata_b <= wdata_aligned;
|
||||
wstrb_b <= wstrb_aligned;
|
||||
end
|
||||
|
||||
end // else: !if( M_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge M_AXI_ACLK )
|
||||
|
||||
//----------------------------
|
||||
// Read Handler
|
||||
// eLink read requests generate a transaction on the AR channel,
|
||||
// buffer the src info to generate an eLink write when the
|
||||
// read data comes back.
|
||||
//----------------------------
|
||||
|
||||
`define RI_DSTADDR_RANGE 40:38
|
||||
`define RI_DSTADDR_LSB 38
|
||||
`define RI_DATAMODE_RANGE 37:36
|
||||
`define RI_CTRLMODE_RANGE 35:32
|
||||
`define RI_SRCADDR_RANGE 31:0
|
||||
|
||||
wire readinfo_wren;
|
||||
wire readinfo_rden;
|
||||
wire readinfo_full;
|
||||
wire [40:0] readinfo_out;
|
||||
wire [40:0] readinfo_in =
|
||||
{
|
||||
emrq_rd_data[`DSTADDR_LSB+2 -: 3],
|
||||
emrq_rd_data[`DATAMODE_RANGE],
|
||||
emrq_rd_data[`CTRLMODE_RANGE],
|
||||
emrq_rd_data[`SRCADDR_RANGE]
|
||||
};
|
||||
|
||||
fifo_sync
|
||||
#(
|
||||
// Parameters
|
||||
.AW (5),
|
||||
.DW (41))
|
||||
fifo_readinfo_i
|
||||
(
|
||||
// Outputs
|
||||
.rd_data (readinfo_out),
|
||||
.rd_empty (),
|
||||
.wr_full (readinfo_full),
|
||||
// Inputs
|
||||
.clk (M_AXI_ACLK),
|
||||
.reset (~M_AXI_ARESETN),
|
||||
.wr_data (readinfo_in),
|
||||
.wr_en (readinfo_wren),
|
||||
.rd_en (readinfo_rden));
|
||||
|
||||
//----------------------------
|
||||
// Read Address Channel
|
||||
//----------------------------
|
||||
|
||||
assign axi_araddr = emrq_rd_data[`DSTADDR_RANGE];
|
||||
assign axi_arsize = {1'b0, emrq_rd_data[`DATAMODE_RANGE]};
|
||||
assign axi_arlen = 8'd0;
|
||||
assign axi_arvalid = ~emrq_empty & ~readinfo_full;
|
||||
assign emrq_rd_en = axi_arvalid & M_AXI_ARREADY;
|
||||
assign readinfo_wren = emrq_rd_en;
|
||||
|
||||
//--------------------------------
|
||||
// Read Data (and Response) Channel
|
||||
//--------------------------------
|
||||
|
||||
assign axi_rready = ~emrr_prog_full;
|
||||
assign readinfo_rden = axi_rready & M_AXI_RVALID;
|
||||
|
||||
always @( posedge M_AXI_ACLK ) begin
|
||||
if( ~M_AXI_ARESETN ) begin
|
||||
|
||||
emrr_wr_data <= 'd0;
|
||||
emrr_wr_en <= 1'b0;
|
||||
|
||||
end else begin
|
||||
|
||||
emrr_wr_en <= axi_rready & M_AXI_RVALID;
|
||||
|
||||
emrr_wr_data[`WRITE_BIT] <= 1'b1;
|
||||
emrr_wr_data[`DATAMODE_RANGE] <= readinfo_out[`RI_DATAMODE_RANGE];
|
||||
emrr_wr_data[`CTRLMODE_RANGE] <= readinfo_out[`RI_CTRLMODE_RANGE];
|
||||
emrr_wr_data[`DSTADDR_RANGE] <= readinfo_out[`RI_SRCADDR_RANGE];
|
||||
emrr_wr_data[`SRCADDR_RANGE] <= 32'd0;
|
||||
emrr_wr_data[`DATA_RANGE] <= 32'd0;
|
||||
|
||||
// Steer read data according to size & host address lsbs
|
||||
case( readinfo_out[`RI_DATAMODE_RANGE] )
|
||||
|
||||
2'd0: // BYTE read
|
||||
case( readinfo_out[`RI_DSTADDR_RANGE] )
|
||||
3'd0: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[7:0];
|
||||
3'd1: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[15:8];
|
||||
3'd2: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[23:16];
|
||||
3'd3: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[31:24];
|
||||
3'd4: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[39:32];
|
||||
3'd5: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[47:40];
|
||||
3'd6: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[55:48];
|
||||
default: emrr_wr_data[`DATA_LSB+7 -: 8] <= M_AXI_RDATA[63:56];
|
||||
endcase
|
||||
|
||||
2'd1: // 16b HWORD
|
||||
case( readinfo_out[`RI_DSTADDR_LSB+2 -: 2] )
|
||||
2'd0: emrr_wr_data[`DATA_LSB+15 -: 16] <= M_AXI_RDATA[15:0];
|
||||
2'd1: emrr_wr_data[`DATA_LSB+15 -: 16] <= M_AXI_RDATA[31:16];
|
||||
2'd2: emrr_wr_data[`DATA_LSB+15 -: 16] <= M_AXI_RDATA[47:32];
|
||||
default: emrr_wr_data[`DATA_LSB+15 -: 16] <= M_AXI_RDATA[63:48];
|
||||
endcase
|
||||
|
||||
2'd2: // 32b WORD
|
||||
if( readinfo_out[`RI_DSTADDR_LSB+2] )
|
||||
emrr_wr_data[`DATA_RANGE] <= M_AXI_RDATA[63:32];
|
||||
else
|
||||
emrr_wr_data[`DATA_RANGE] <= M_AXI_RDATA[31:0];
|
||||
|
||||
// 64b word already defined by defaults above
|
||||
2'd3: begin // 64b DWORD
|
||||
emrr_wr_data[`DATA_RANGE] <= M_AXI_RDATA[31:0];
|
||||
emrr_wr_data[`SRCADDR_RANGE] <= M_AXI_RDATA[63:32];
|
||||
end
|
||||
endcase
|
||||
|
||||
end // else: !if( ~M_AXI_ARESETN )
|
||||
end // always @ ( posedge M_AXI_ACLK )
|
||||
|
||||
endmodule
|
@ -1,565 +0,0 @@
|
||||
|
||||
`timescale 1 ns / 1 ps
|
||||
|
||||
module esaxi_v1_0_S00_AXI #
|
||||
(
|
||||
// Users to add parameters here
|
||||
parameter [11:0] C_READ_TAG_ADDR = 12'h810,
|
||||
// User parameters ends
|
||||
// Do not modify the parameters beyond this line
|
||||
|
||||
// Width of ID for for write address, write data, read address and read data
|
||||
parameter integer C_S_AXI_ID_WIDTH = 1,
|
||||
// Width of S_AXI data bus
|
||||
parameter integer C_S_AXI_DATA_WIDTH = 32,
|
||||
// Width of S_AXI address bus
|
||||
parameter integer C_S_AXI_ADDR_WIDTH = 30,
|
||||
// Width of optional user defined signal in write address channel
|
||||
parameter integer C_S_AXI_AWUSER_WIDTH = 0,
|
||||
// Width of optional user defined signal in read address channel
|
||||
parameter integer C_S_AXI_ARUSER_WIDTH = 0,
|
||||
// Width of optional user defined signal in write data channel
|
||||
parameter integer C_S_AXI_WUSER_WIDTH = 0,
|
||||
// Width of optional user defined signal in read data channel
|
||||
parameter integer C_S_AXI_RUSER_WIDTH = 0,
|
||||
// Width of optional user defined signal in write response channel
|
||||
parameter integer C_S_AXI_BUSER_WIDTH = 0
|
||||
)
|
||||
(
|
||||
// Users to add ports here
|
||||
// FIFO write port, write requests
|
||||
output reg [102:0] emwr_wr_data,
|
||||
output reg emwr_wr_en,
|
||||
input wire emwr_full,
|
||||
input wire emwr_prog_full,
|
||||
|
||||
// FIFO write port, read requests
|
||||
output reg [102:0] emrq_wr_data,
|
||||
output reg emrq_wr_en,
|
||||
input wire emrq_full,
|
||||
input wire emrq_prog_full,
|
||||
|
||||
// FIFO read port, read responses
|
||||
input wire [102:0] emrr_rd_data,
|
||||
output wire emrr_rd_en,
|
||||
input wire emrr_empty,
|
||||
|
||||
// Control bits from eConfig
|
||||
input wire [3:0] ecfg_tx_ctrl_mode,
|
||||
input wire [11:0] ecfg_coreid,
|
||||
|
||||
// User ports ends
|
||||
// Do not modify the ports beyond this line
|
||||
|
||||
// Global Clock Signal
|
||||
input wire S_AXI_ACLK,
|
||||
// Global Reset Signal. This Signal is Active LOW
|
||||
input wire S_AXI_ARESETN,
|
||||
// Write Address ID
|
||||
input wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_AWID,
|
||||
// Write address
|
||||
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
|
||||
// Burst length. The burst length gives the exact number of transfers in a burst
|
||||
input wire [7 : 0] S_AXI_AWLEN,
|
||||
// Burst size. This signal indicates the size of each transfer in the burst
|
||||
input wire [2 : 0] S_AXI_AWSIZE,
|
||||
// Burst type. The burst type and the size information,
|
||||
// determine how the address for each transfer within the burst is calculated.
|
||||
input wire [1 : 0] S_AXI_AWBURST,
|
||||
// Lock type. Provides additional information about the
|
||||
// atomic characteristics of the transfer.
|
||||
input wire S_AXI_AWLOCK,
|
||||
// Memory type. This signal indicates how transactions
|
||||
// are required to progress through a system.
|
||||
input wire [3 : 0] S_AXI_AWCACHE,
|
||||
// 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.
|
||||
input wire [2 : 0] S_AXI_AWPROT,
|
||||
// Quality of Service, QoS identifier sent for each
|
||||
// write transaction.
|
||||
input wire [3 : 0] S_AXI_AWQOS,
|
||||
// Region identifier. Permits a single physical interface
|
||||
// on a slave to be used for multiple logical interfaces.
|
||||
input wire [3 : 0] S_AXI_AWREGION,
|
||||
// Optional User-defined signal in the write address channel.
|
||||
input wire [C_S_AXI_AWUSER_WIDTH-1 : 0] S_AXI_AWUSER,
|
||||
// Write address valid. This signal indicates that
|
||||
// the channel is signaling valid write address and
|
||||
// control information.
|
||||
input wire S_AXI_AWVALID,
|
||||
// Write address ready. This signal indicates that
|
||||
// the slave is ready to accept an address and associated
|
||||
// control signals.
|
||||
output wire S_AXI_AWREADY,
|
||||
// Write Data
|
||||
input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_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.
|
||||
input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
|
||||
// Write last. This signal indicates the last transfer
|
||||
// in a write burst.
|
||||
input wire S_AXI_WLAST,
|
||||
// Optional User-defined signal in the write data channel.
|
||||
input wire [C_S_AXI_WUSER_WIDTH-1 : 0] S_AXI_WUSER,
|
||||
// Write valid. This signal indicates that valid write
|
||||
// data and strobes are available.
|
||||
input wire S_AXI_WVALID,
|
||||
// Write ready. This signal indicates that the slave
|
||||
// can accept the write data.
|
||||
output wire S_AXI_WREADY,
|
||||
// Response ID tag. This signal is the ID tag of the
|
||||
// write response.
|
||||
output wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_BID,
|
||||
// Write response. This signal indicates the status
|
||||
// of the write transaction.
|
||||
output wire [1 : 0] S_AXI_BRESP,
|
||||
// Optional User-defined signal in the write response channel.
|
||||
output wire [C_S_AXI_BUSER_WIDTH-1 : 0] S_AXI_BUSER,
|
||||
// Write response valid. This signal indicates that the
|
||||
// channel is signaling a valid write response.
|
||||
output wire S_AXI_BVALID,
|
||||
// Response ready. This signal indicates that the master
|
||||
// can accept a write response.
|
||||
input wire S_AXI_BREADY,
|
||||
// Read address ID. This signal is the identification
|
||||
// tag for the read address group of signals.
|
||||
input wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_ARID,
|
||||
// Read address. This signal indicates the initial
|
||||
// address of a read burst transaction.
|
||||
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
|
||||
// Burst length. The burst length gives the exact number of transfers in a burst
|
||||
input wire [7 : 0] S_AXI_ARLEN,
|
||||
// Burst size. This signal indicates the size of each transfer in the burst
|
||||
input wire [2 : 0] S_AXI_ARSIZE,
|
||||
// Burst type. The burst type and the size information,
|
||||
// determine how the address for each transfer within the burst is calculated.
|
||||
input wire [1 : 0] S_AXI_ARBURST,
|
||||
// Lock type. Provides additional information about the
|
||||
// atomic characteristics of the transfer.
|
||||
input wire S_AXI_ARLOCK,
|
||||
// Memory type. This signal indicates how transactions
|
||||
// are required to progress through a system.
|
||||
input wire [3 : 0] S_AXI_ARCACHE,
|
||||
// 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.
|
||||
input wire [2 : 0] S_AXI_ARPROT,
|
||||
// Quality of Service, QoS identifier sent for each
|
||||
// read transaction.
|
||||
input wire [3 : 0] S_AXI_ARQOS,
|
||||
// Region identifier. Permits a single physical interface
|
||||
// on a slave to be used for multiple logical interfaces.
|
||||
input wire [3 : 0] S_AXI_ARREGION,
|
||||
// Optional User-defined signal in the read address channel.
|
||||
input wire [C_S_AXI_ARUSER_WIDTH-1 : 0] S_AXI_ARUSER,
|
||||
// Write address valid. This signal indicates that
|
||||
// the channel is signaling valid read address and
|
||||
// control information.
|
||||
input wire S_AXI_ARVALID,
|
||||
// Read address ready. This signal indicates that
|
||||
// the slave is ready to accept an address and associated
|
||||
// control signals.
|
||||
output wire S_AXI_ARREADY,
|
||||
// Read ID tag. This signal is the identification tag
|
||||
// for the read data group of signals generated by the slave.
|
||||
output wire [C_S_AXI_ID_WIDTH-1 : 0] S_AXI_RID,
|
||||
// Read Data
|
||||
output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
|
||||
// Read response. This signal indicates the status of
|
||||
// the read transfer.
|
||||
output wire [1 : 0] S_AXI_RRESP,
|
||||
// Read last. This signal indicates the last transfer
|
||||
// in a read burst.
|
||||
output wire S_AXI_RLAST,
|
||||
// Optional User-defined signal in the read address channel.
|
||||
output wire [C_S_AXI_RUSER_WIDTH-1 : 0] S_AXI_RUSER,
|
||||
// Read valid. This signal indicates that the channel
|
||||
// is signaling the required read data.
|
||||
output wire S_AXI_RVALID,
|
||||
// Read ready. This signal indicates that the master can
|
||||
// accept the read data and response information.
|
||||
input wire S_AXI_RREADY
|
||||
);
|
||||
|
||||
// AXI4FULL signals
|
||||
reg [31:0] axi_awaddr; // 32b for Epiphany addr
|
||||
reg [1:0] axi_awburst;
|
||||
reg [2:0] axi_awsize;
|
||||
reg axi_awready;
|
||||
|
||||
reg axi_wready;
|
||||
|
||||
reg [C_S_AXI_ID_WIDTH-1:0] axi_bid;
|
||||
reg [1:0] axi_bresp;
|
||||
reg axi_bvalid;
|
||||
|
||||
reg [31:0] axi_araddr; // 32b for Epiphany addr
|
||||
reg [7:0] axi_arlen;
|
||||
reg [1:0] axi_arburst;
|
||||
reg [2:0] axi_arsize;
|
||||
reg axi_arready;
|
||||
|
||||
reg [C_S_AXI_ID_WIDTH-1:0] axi_rid;
|
||||
reg [C_S_AXI_DATA_WIDTH-1:0] axi_rdata;
|
||||
reg [1:0] axi_rresp;
|
||||
reg axi_rlast;
|
||||
reg axi_rvalid;
|
||||
|
||||
//local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
|
||||
//ADDR_LSB is used for addressing 32/64 bit registers/memories
|
||||
//ADDR_LSB = 2 for 32 bits (n downto 2)
|
||||
//ADDR_LSB = 3 for 64 bits (n downto 3)
|
||||
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32)+ 1;
|
||||
|
||||
// I/O Connections assignments
|
||||
|
||||
assign S_AXI_AWREADY = axi_awready;
|
||||
assign S_AXI_WREADY = axi_wready;
|
||||
assign S_AXI_BRESP = axi_bresp;
|
||||
assign S_AXI_BID = axi_bid;
|
||||
assign S_AXI_BVALID = axi_bvalid;
|
||||
assign S_AXI_ARREADY = axi_arready;
|
||||
assign S_AXI_RDATA = axi_rdata;
|
||||
assign S_AXI_RRESP = axi_rresp;
|
||||
assign S_AXI_RLAST = axi_rlast;
|
||||
assign S_AXI_RVALID = axi_rvalid;
|
||||
assign S_AXI_RID = axi_rid;
|
||||
assign S_AXI_BUSER = 'd0;
|
||||
assign S_AXI_BUSER = 'd0;
|
||||
assign S_AXI_RUSER = 'd0;
|
||||
|
||||
// Implement write address channel
|
||||
reg write_active;
|
||||
reg b_wait; // Waiting to issue write response (unlikely?)
|
||||
|
||||
wire last_wr_beat = axi_wready & S_AXI_WVALID & S_AXI_WLAST;
|
||||
|
||||
// axi_awready is asserted when there is no write transfer in progress
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_awready <= 1'b0;
|
||||
write_active <= 1'b0;
|
||||
|
||||
end else begin
|
||||
|
||||
// We're always ready for an address cycle if we're not doing something else
|
||||
// NOTE: Might make this faster by going ready on last beat instead of after,
|
||||
// but if we want the very best each channel should be FIFO'd.
|
||||
if( ~axi_awready & ~write_active & ~b_wait )
|
||||
axi_awready <= 1'b1;
|
||||
else if( S_AXI_AWVALID )
|
||||
axi_awready <= 1'b0;
|
||||
|
||||
// The write cycle is "active" as soon as we capture an address, it
|
||||
// ends on the last beat.
|
||||
if( axi_awready & S_AXI_AWVALID )
|
||||
write_active <= 1'b1;
|
||||
else if( last_wr_beat )
|
||||
write_active <= 1'b0;
|
||||
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
// Capture address & other AW info, update address during cycle
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if ( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_bid <= 'd0; // capture for write response
|
||||
axi_awaddr <= 'd0;
|
||||
axi_awsize <= 3'd0;
|
||||
axi_awburst <= 2'd0;
|
||||
|
||||
end else begin
|
||||
|
||||
if( axi_awready & S_AXI_AWVALID ) begin
|
||||
|
||||
axi_bid <= S_AXI_AWID;
|
||||
axi_awaddr <= { ecfg_coreid[11:C_S_AXI_ADDR_WIDTH-20],
|
||||
S_AXI_AWADDR };
|
||||
axi_awsize <= S_AXI_AWSIZE; // 0=byte, 1=16b, 2=32b
|
||||
axi_awburst <= S_AXI_AWBURST; // type, 0=fixed, 1=incr, 2=wrap
|
||||
|
||||
end else if( S_AXI_WVALID & axi_wready ) begin
|
||||
|
||||
if( axi_awburst == 2'b01 ) begin //incremental burst
|
||||
// The write address for all the beats in the transaction are increments by the data width.
|
||||
// NOTE: This should be based on awsize instead to support narrow bursts, I think.
|
||||
|
||||
axi_awaddr[31:ADDR_LSB] <= axi_awaddr[31:ADDR_LSB] + 32'd1;
|
||||
//awaddr aligned to data width
|
||||
axi_awaddr[ADDR_LSB-1:0] <= {ADDR_LSB{1'b0}};
|
||||
|
||||
end // Both FIXED & WRAPPING types are treated as FIXED, no update.
|
||||
|
||||
end // if ( S_AXI_WVALID & axi_wready )
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
// Write Channel Implementation
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_wready <= 1'b0;
|
||||
|
||||
end else begin
|
||||
|
||||
if( last_wr_beat )
|
||||
axi_wready <= 1'b0;
|
||||
else if( write_active )
|
||||
axi_wready <= ~emwr_prog_full;
|
||||
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
// Implement write response logic generation
|
||||
// The write response and response valid signals are asserted by the slave
|
||||
// at the end of each transaction, burst or single.
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if ( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_bvalid <= 1'b0;
|
||||
axi_bresp <= 2'b0;
|
||||
b_wait <= 1'b0;
|
||||
|
||||
end else begin
|
||||
|
||||
if( last_wr_beat ) begin
|
||||
|
||||
axi_bvalid <= 1'b1;
|
||||
axi_bresp <= 2'b0; // 'OKAY' response
|
||||
b_wait <= ~S_AXI_BREADY; // NOTE: Assumes bready will not drop without valid?
|
||||
|
||||
end else if (S_AXI_BREADY & axi_bvalid) begin
|
||||
|
||||
axi_bvalid <= 1'b0;
|
||||
b_wait <= 1'b0;
|
||||
|
||||
end
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
|
||||
// Read registers
|
||||
reg read_active;
|
||||
reg [31:0] read_addr;
|
||||
|
||||
wire last_rd_beat = axi_rvalid & axi_rlast & S_AXI_RREADY;
|
||||
|
||||
// Read request channel
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if ( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_arready <= 1'b0;
|
||||
read_active <= 1'b0;
|
||||
|
||||
end else begin
|
||||
|
||||
if( ~axi_arready & ~read_active )
|
||||
axi_arready <= 1'b1;
|
||||
else if( S_AXI_ARVALID )
|
||||
axi_arready <= 1'b0;
|
||||
|
||||
if( axi_arready & S_AXI_ARVALID )
|
||||
read_active <= 1'b1;
|
||||
else if( last_rd_beat )
|
||||
read_active <= 1'b0;
|
||||
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
// Implement axi_araddr, etc. latching & counting
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if ( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_araddr <= 0;
|
||||
axi_arlen <= 8'd0;
|
||||
axi_arburst <= 2'd0;
|
||||
axi_arsize <= 2'b0;
|
||||
axi_rlast <= 1'b0;
|
||||
axi_rid <= 'd0;
|
||||
|
||||
end else begin
|
||||
|
||||
if( axi_arready & S_AXI_ARVALID ) begin
|
||||
|
||||
axi_araddr <= { ecfg_coreid[11:C_S_AXI_ADDR_WIDTH-20],
|
||||
S_AXI_ARADDR }; // start address of transfer
|
||||
axi_arlen <= S_AXI_ARLEN;
|
||||
axi_arburst <= S_AXI_ARBURST;
|
||||
axi_arsize <= S_AXI_ARSIZE;
|
||||
axi_rlast <= ~(|S_AXI_ARLEN);
|
||||
axi_rid <= S_AXI_ARID;
|
||||
|
||||
end else if(axi_rvalid & S_AXI_RREADY) begin
|
||||
|
||||
axi_arlen <= axi_arlen - 1;
|
||||
|
||||
if(axi_arlen == 8'd1)
|
||||
axi_rlast <= 1'b1;
|
||||
|
||||
if( S_AXI_ARBURST == 2'b01) begin //incremental burst
|
||||
// The read address for all the beats in the transaction are increments by awsize
|
||||
// NOTE: This should be based on awsize instead to support narrow bursts, I think.
|
||||
|
||||
axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] <= axi_araddr[C_S_AXI_ADDR_WIDTH - 1:ADDR_LSB] + 1;
|
||||
//araddr aligned to 4 byte boundary
|
||||
axi_araddr[ADDR_LSB-1:0] <= {ADDR_LSB{1'b0}};
|
||||
//for awsize = 4 bytes (010)
|
||||
end
|
||||
|
||||
end // if (axi_rvalid & S_AXI_RREADY)
|
||||
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
// ------------------------------------------
|
||||
// -- Write Data Handler
|
||||
// ------------------------------------------
|
||||
|
||||
reg [31:0] aligned_data;
|
||||
reg [31:0] aligned_addr;
|
||||
reg [1:0] wsize;
|
||||
reg pre_wr_en; // delay for data alignment
|
||||
reg [3:0] ctrl_mode; // Sync'd from ecfg
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if ( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
aligned_data <= 'd0;
|
||||
aligned_addr <= 'd0;
|
||||
wsize <= 2'd0;
|
||||
emwr_wr_data <= 'd0;
|
||||
pre_wr_en <= 1'b0;
|
||||
emwr_wr_en <= 1'b0;
|
||||
ctrl_mode <= 'd0;
|
||||
|
||||
end else begin
|
||||
|
||||
ctrl_mode <= ecfg_tx_ctrl_mode; // No timing on this
|
||||
|
||||
// Set lsbs of address based on write strobes,
|
||||
// right-justify data.
|
||||
aligned_addr[31:2] <= axi_awaddr[31:2];
|
||||
|
||||
if( S_AXI_WSTRB[0] ) begin
|
||||
aligned_data <= S_AXI_WDATA[31:0];
|
||||
aligned_addr[1:0] <= 2'd0;
|
||||
end else if(S_AXI_WSTRB[1] ) begin
|
||||
aligned_data <= {8'd0, S_AXI_WDATA[31:8]};
|
||||
aligned_addr[1:0] <= 2'd1;
|
||||
end else if(S_AXI_WSTRB[2] ) begin
|
||||
aligned_data <= {16'd0, S_AXI_WDATA[31:16]};
|
||||
aligned_addr[1:0] <= 2'd2;
|
||||
end else begin
|
||||
aligned_data <= {24'd0, S_AXI_WDATA[31:24]};
|
||||
aligned_addr[1:0] <= 2'd3;
|
||||
end
|
||||
|
||||
wsize <= axi_awsize[1:0];
|
||||
pre_wr_en <= axi_wready & S_AXI_WVALID;
|
||||
emwr_wr_en <= pre_wr_en;
|
||||
|
||||
emwr_wr_data <=
|
||||
{ 1'b1, // write
|
||||
wsize, // only up to 32b
|
||||
ctrl_mode,
|
||||
aligned_addr, // dstaddr
|
||||
32'd0, // srcaddr ignored
|
||||
aligned_data};
|
||||
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
|
||||
// ------------------------------------------
|
||||
// -- Read Data Handler
|
||||
// -- Reads are performed by sending a read
|
||||
// -- request out the TX port and waiting for
|
||||
// -- data to come back through the RX port.
|
||||
// --
|
||||
// -- Because eLink reads are not generally
|
||||
// -- returned in order, we will only allow
|
||||
// -- one at a time. That's OK because reads
|
||||
// -- are to be avoided for speed anyway.
|
||||
// ------------------------------------------
|
||||
|
||||
// Process to issue eLink read requests
|
||||
|
||||
// Since we're only sending one req at a time we can ignore the FIFO flags
|
||||
|
||||
reg ractive_reg; // Need leading edge of active for 1st req
|
||||
reg rnext;
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if ( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
emrq_wr_en <= 1'b0;
|
||||
emrq_wr_data <= 'd0;
|
||||
ractive_reg <= 1'b0;
|
||||
rnext <= 1'b0;
|
||||
|
||||
end else begin
|
||||
|
||||
ractive_reg <= read_active;
|
||||
|
||||
rnext <= axi_rvalid & S_AXI_RREADY & ~axi_rlast;
|
||||
|
||||
emrq_wr_en <= ( ~ractive_reg & read_active ) | rnext;
|
||||
|
||||
emrq_wr_data <=
|
||||
{ 1'b0, // !write
|
||||
axi_arsize[1:0], // 32b max
|
||||
ctrl_mode,
|
||||
axi_araddr, // dstaddr (read from)
|
||||
{C_READ_TAG_ADDR, 20'd0}, // srcaddr (tag)
|
||||
32'd0 // no data
|
||||
};
|
||||
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
// Handle eLink response data
|
||||
|
||||
// always read response data immediately
|
||||
assign emrr_rd_en = ~emrr_empty;
|
||||
|
||||
always @( posedge S_AXI_ACLK ) begin
|
||||
if ( S_AXI_ARESETN == 1'b0 ) begin
|
||||
|
||||
axi_rvalid <= 1'b0;
|
||||
axi_rdata <= 'd0;
|
||||
axi_rresp <= 2'd0;
|
||||
|
||||
end else begin
|
||||
|
||||
if( ~emrr_empty ) begin
|
||||
|
||||
axi_rvalid <= 1'b1;
|
||||
axi_rresp <= 2'd0;
|
||||
|
||||
case( axi_arsize[1:0] )
|
||||
|
||||
2'b00: axi_rdata <= {4{emrr_rd_data[7:0]}};
|
||||
2'b01: axi_rdata <= {2{emrr_rd_data[15:0]}};
|
||||
default: axi_rdata <= emrr_rd_data;
|
||||
|
||||
endcase // case ( axi_araddr[1:0] }...
|
||||
|
||||
end else if( S_AXI_RREADY ) begin // if ( ~emrr_empty )
|
||||
|
||||
axi_rvalid <= 1'b0;
|
||||
|
||||
end
|
||||
end // else: !if( S_AXI_ARESETN == 1'b0 )
|
||||
end // always @ ( posedge S_AXI_ACLK )
|
||||
|
||||
endmodule
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2014 Adapteva, Inc.
|
||||
|
||||
Contributed by Fred Huettig <fred@adapteva.com>
|
||||
Contributed by Andreas Olofsson <andreas@adapteva.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.This program is distributed in the hope
|
||||
that it will be useful,but WITHOUT ANY WARRANTY; without even the implied
|
||||
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details. You should have received a copy
|
||||
of the GNU General Public License along with this program (see the file
|
||||
COPYING). If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
module esaxilite (/*AUTOARG*/
|
||||
// Outputs
|
||||
s_axi_arready, s_axi_awready, s_axi_bresp, s_axi_bvalid,
|
||||
s_axi_rdata, s_axi_rresp, s_axi_rvalid, s_axi_wready, mi_clk,
|
||||
mi_en, mi_we, mi_addr, mi_din,
|
||||
// Inputs
|
||||
s_axi_aclk, s_axi_aresetn, s_axi_araddr, s_axi_arprot,
|
||||
s_axi_arvalid, s_axi_awaddr, s_axi_awprot, s_axi_awvalid,
|
||||
s_axi_bready, s_axi_rready, s_axi_wdata, s_axi_wstrb, s_axi_wvalid,
|
||||
mi_rd_data
|
||||
);
|
||||
|
||||
parameter RFAW = 13;
|
||||
|
||||
/*****************************/
|
||||
/*AXI 32 bit lite interface */
|
||||
/*****************************/
|
||||
input s_axi_aclk;
|
||||
input s_axi_aresetn;
|
||||
|
||||
//read address channel
|
||||
input [RFAW-1:0] s_axi_araddr;
|
||||
input [2:0] s_axi_arprot;
|
||||
output s_axi_arready;
|
||||
input s_axi_arvalid;
|
||||
|
||||
//write address channel
|
||||
input [RFAW-1:0] s_axi_awaddr;
|
||||
input [2:0] s_axi_awprot;
|
||||
output s_axi_awready;
|
||||
input s_axi_awvalid;
|
||||
|
||||
//buffered read response channel
|
||||
input s_axi_bready;
|
||||
output [1:0] s_axi_bresp;
|
||||
output s_axi_bvalid;
|
||||
|
||||
//read channel
|
||||
output [31:0] s_axi_rdata;
|
||||
input s_axi_rready;
|
||||
output [1:0] s_axi_rresp;
|
||||
output s_axi_rvalid;
|
||||
|
||||
//write channel
|
||||
input [31:0] s_axi_wdata;
|
||||
output s_axi_wready;
|
||||
input [3:0] s_axi_wstrb;
|
||||
input s_axi_wvalid;
|
||||
|
||||
/*****************************/
|
||||
/*Simple memory interface */
|
||||
/*****************************/
|
||||
output mi_clk;
|
||||
output mi_en;
|
||||
output mi_we;
|
||||
output [RFAW-1:0] mi_addr;
|
||||
output [31:0] mi_din;
|
||||
input [31:0] mi_rd_data;
|
||||
|
||||
|
||||
//PUT BRAM CONTROLLER HERE
|
||||
assign mi_clk = s_axi_aclk;
|
||||
assign mi_en = 1'b0;
|
||||
assign mi_we = 1'b0;
|
||||
assign mi_addr[RFAW-1:0] = {(RFAW){1'b0}};
|
||||
assign mi_din[31:0] = 32'b0;
|
||||
|
||||
//TODO: Insert BRAM controller or similar interface here
|
||||
|
||||
endmodule // esaxilite
|
Loading…
x
Reference in New Issue
Block a user