1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-01-30 02:32:53 +08:00

Cleaning up logic to fit new access/packet interface

(pre-debug)
This commit is contained in:
Andreas Olofsson 2015-05-09 08:56:51 -04:00
parent ab26378a99
commit eb3051ea93
2 changed files with 382 additions and 369 deletions

View File

@ -6,8 +6,7 @@
module emaxi(/*autoarg*/
// Outputs
emwr_rd_en, emrq_rd_en, emrr_access, emrr_write, emrr_datamode,
emrr_ctrlmode, emrr_dstaddr, emrr_data, emrr_srcaddr, m_axi_awid,
rxwr_wait, rxrd_wait, txrr_access, txrr_packet, m_axi_awid,
m_axi_awaddr, m_axi_awlen, m_axi_awsize, m_axi_awburst,
m_axi_awlock, m_axi_awcache, m_axi_awprot, m_axi_awqos,
m_axi_awvalid, m_axi_wid, m_axi_wdata, m_axi_wstrb, m_axi_wlast,
@ -15,52 +14,41 @@ module emaxi(/*autoarg*/
m_axi_arsize, m_axi_arburst, m_axi_arlock, m_axi_arcache,
m_axi_arprot, m_axi_arqos, m_axi_arvalid, m_axi_rready,
// Inputs
emwr_access, emwr_write, emwr_datamode, emwr_ctrlmode,
emwr_dstaddr, emwr_data, emwr_srcaddr, emrq_access, emrq_write,
emrq_datamode, emrq_ctrlmode, emrq_dstaddr, emrq_data,
emrq_srcaddr, emrr_progfull, m_axi_aclk, m_axi_aresetn,
m_axi_awready, m_axi_wready, m_axi_bid, m_axi_bresp, m_axi_bvalid,
m_axi_arready, m_axi_rid, m_axi_rdata, m_axi_rresp, m_axi_rlast,
m_axi_rvalid
rxwr_access, rxwr_packet, rxrd_access, rxrd_packet, txrr_wait,
m_axi_aclk, m_axi_aresetn, m_axi_awready, m_axi_wready, m_axi_bid,
m_axi_bresp, m_axi_bvalid, m_axi_arready, m_axi_rid, m_axi_rdata,
m_axi_rresp, m_axi_rlast, m_axi_rvalid
);
parameter IDW = 12;
// fifo read-master port, writes from rx
input emwr_access;
input emwr_write;
input [1:0] emwr_datamode;
input [3:0] emwr_ctrlmode;
input [31:0] emwr_dstaddr;
input [31:0] emwr_data;
input [31:0] emwr_srcaddr;
output emwr_rd_en; //read ptr update for fifo
parameter IDW = 12;
parameter PW = 104;
parameter AW = 32;
parameter DW = 32;
//########################
//ELINK INTERFACE
//########################
// fifo read-master port; read requests from rx
input emrq_access;
input emrq_write;
input [1:0] emrq_datamode;
input [3:0] emrq_ctrlmode;
input [31:0] emrq_dstaddr;
input [31:0] emrq_data;
input [31:0] emrq_srcaddr;
output emrq_rd_en; //read ptr update for fifo
//Write request from erx
input rxwr_access;
input [PW-1:0] rxwr_packet;
output rxwr_wait;
// fifo write-master port; read responses for etx
output emrr_access;
output emrr_write;
output [1:0] emrr_datamode;
output [3:0] emrr_ctrlmode;
output [31:0] emrr_dstaddr;
output [31:0] emrr_data;
output [31:0] emrr_srcaddr;
input emrr_progfull;
/*****************************/
/*axi */
/*****************************/
//Read request from erx
input rxrd_access;
input [PW-1:0] rxrd_packet;
output rxrd_wait;
//Read respoonse for etx
output txrr_access;
output [PW-1:0] txrr_packet;
input txrr_wait;
//########################
//AXI MASTER INTERFACE
//########################
input m_axi_aclk; // global clock signal.
input m_axi_aresetn; // global reset singal.
@ -112,58 +100,125 @@ module emaxi(/*autoarg*/
input m_axi_rvalid; // signaling the required read data
output m_axi_rready; // master can accept the readback data
//registers
reg [31 : 0] m_axi_awaddr;
reg [7:0] m_axi_awlen;
reg [2:0] m_axi_awsize;
reg m_axi_awvalid;
reg [63 : 0] m_axi_wdata;
reg [7 : 0] m_axi_wstrb;
reg m_axi_wlast;
reg m_axi_wvalid;
reg awvalid_b;
reg [31:0] awaddr_b;
reg [2:0] awsize_b;
reg [7:0] awlen_b;
reg wvalid_b;
reg [63:0] wdata_b;
reg [7:0] wstrb_b;
reg [63 : 0] wdata_aligned;
reg [7 : 0] wstrb_aligned;
reg emrr_access;
reg emrr_access_reg;
reg [31:0] emrr_data;
reg [31:0] emrr_srcaddr;
//#########################################################################
//REGISTER/WIRE DECLARATIONS
//#########################################################################
reg [31 : 0] m_axi_awaddr;
reg [7:0] m_axi_awlen;
reg [2:0] m_axi_awsize;
reg m_axi_awvalid;
reg [63 : 0] m_axi_wdata;
reg [7 : 0] m_axi_wstrb;
reg m_axi_wlast;
reg m_axi_wvalid;
reg awvalid_b;
reg [31:0] awaddr_b;
reg [2:0] awsize_b;
reg [7:0] awlen_b;
reg wvalid_b;
reg [63:0] wdata_b;
reg [7:0] wstrb_b;
reg [63 : 0] wdata_aligned;
reg [7 : 0] wstrb_aligned;
reg txrr_access;
reg txrr_access_reg;
reg [31:0] txrr_data;
reg [31:0] txrr_srcaddr;
//wires
wire aw_go;
wire w_go;
wire readinfo_wren;
wire readinfo_rden;
wire readinfo_full;
wire [47:0] readinfo_out;
wire [47:0] readinfo_in;
wire aw_go;
wire w_go;
wire readinfo_wren;
wire readinfo_rden;
wire readinfo_full;
wire [47:0] readinfo_out;
wire [47:0] readinfo_in;
//i/o connections. write address (aw)
assign m_axi_awburst[1:0] = 2'b01;
wire [1:0] rxwr_datamode;
wire [AW-1:0] rxwr_dstaddr;
wire [DW-1:0] rxwr_data;
wire [AW-1:0] rxwr_srcaddr;
wire [1:0] rxrd_datamode;
wire [3:0] rxrd_ctrlmode;
wire [AW-1:0] rxrd_dstaddr;
wire [AW-1:0] rxrd_srcaddr;
wire [1:0] txrr_datamode;
wire [3:0] txrr_ctrlmode;
wire [31:0] txrr_dstaddr;
//#########################################################################
//EMESH 2 PACKET CONVERSION
//#########################################################################
//RXWR
packet2emesh p2e_rxwr (
// Outputs
.access_out (),
.write_out (),
.datamode_out (rxwr_datamode[1:0]),
.ctrlmode_out (),
.dstaddr_out (rxwr_dstaddr[AW-1:0]),
.data_out (rxwr_data[DW-1:0]),
.srcaddr_out (rxwr_srcaddr[AW-1:0]),
// Inputs
.packet_in (rxwr_packet[PW-1:0])
);
//RXRD
packet2emesh p2e_rxrd (
// Outputs
.access_out (),
.write_out (),
.datamode_out (rxrd_datamode[1:0]),
.ctrlmode_out (rxrd_ctrlmode[3:0]),
.dstaddr_out (rxrd_dstaddr[AW-1:0]),
.data_out (),
.srcaddr_out (rxrd_srcaddr[AW-1:0]),
// Inputs
.packet_in (rxrd_packet[PW-1:0])
);
//TXRR
emesh2packet e2p (
// Outputs
.packet_out (txrr_packet[PW-1:0]),
// Inputs
.access_in (txrr_access),
.write_in (txrr_write),
.datamode_in (txrr_datamode[1:0]),
.ctrlmode_in (txrr_ctrlmode[3:0]),
.dstaddr_in (txrr_dstaddr[AW-1:0]),
.data_in (txrr_data[DW-1:0]),
.srcaddr_in (txrr_srcaddr[AW-1:0])
);
//#########################################################################
//AXI unimplemented constants
//#########################################################################
assign m_axi_awburst[1:0] = 2'b01; //TODO???
assign m_axi_awcache[3:0] = 4'b0010;//TODO??update value to 4'b0011 if coherent accesses to be used via the zynq acp port
assign m_axi_awprot[2:0] = 3'h0;
assign m_axi_awqos[3:0] = 4'h0;
assign m_axi_bready = 1'b1; //TODO? axi_bready, why constant
assign m_axi_arburst[1:0] = 2'b01;
assign m_axi_arburst[1:0] = 2'b01;//TODO???
assign m_axi_arcache[3:0] = 4'b0010;
assign m_axi_arprot[2:0] = 3'h0;
assign m_axi_arqos[3:0] = 4'h0;
//--------------------
//write address channel
//--------------------
//#########################################################################
//Write address channel
//#########################################################################
assign aw_go = m_axi_awvalid & m_axi_awready;
assign w_go = m_axi_wvalid & m_axi_wready;
assign emwr_rd_en = ( emwr_access & ~awvalid_b & ~wvalid_b);
assign w_go = m_axi_wvalid & m_axi_wready;
assign rxwr_wait = awvalid_b | wvalid_b;
// generate write-address signals
always @( posedge m_axi_aclk )
@ -173,10 +228,7 @@ module emaxi(/*autoarg*/
m_axi_awaddr[31:0] <= 32'd0;
m_axi_awlen[7:0] <= 8'd0;
m_axi_awsize[2:0] <= 3'd0;
awvalid_b <= 1'b0;
awaddr_b[31:0] <= 32'd0;
awlen_b[7:0] <= 8'd0;
awsize_b[2:0] <= 3'd0;
end
else
begin
@ -191,47 +243,43 @@ module emaxi(/*autoarg*/
end
else
begin
m_axi_awvalid <= emwr_rd_en;
m_axi_awaddr[31:0] <= emwr_dstaddr[31:0];
m_axi_awvalid <= rxwr_access;
m_axi_awaddr[31:0] <= rxwr_dstaddr[31:0];
m_axi_awlen[7:0] <= 8'b0;
m_axi_awsize[2:0] <= { 1'b0, emwr_datamode[1:0]};
m_axi_awsize[2:0] <= { 1'b0, rxwr_datamode[1:0]};
end
end
if( emwr_rd_en & m_axi_awvalid & ~aw_go )
if( rxwr_access & m_axi_awvalid & ~aw_go )
awvalid_b <= 1'b1;
else if( aw_go )
awvalid_b <= 1'b0;
//Pipeline stage
if( emwr_rd_en )
if( rxwr_access )
begin
awaddr_b[31:0] <= emwr_dstaddr[31:0];
awaddr_b[31:0] <= rxwr_dstaddr[31:0];
awlen_b[7:0] <= 8'b0;
awsize_b[2:0] <= { 1'b0, emwr_datamode[1:0] };
awsize_b[2:0] <= { 1'b0, rxwr_datamode[1:0] };
end
end // else: !if(~m_axi_aresetn)
//--------------------
//write alignment circuit
//--------------------
//#########################################################################
//Write data alignment circuit
//#########################################################################
always @*
case( emwr_datamode[1:0] )
2'd0: wdata_aligned[63:0] = { 8{emwr_data[7:0]}};
2'd1: wdata_aligned[63:0] = { 4{emwr_data[15:0]}};
2'd2: wdata_aligned[63:0] = { 2{emwr_data[31:0]}};
default: wdata_aligned[63:0] = { emwr_srcaddr[31:0], emwr_data[31:0]};
case( rxwr_datamode[1:0] )
2'd0: wdata_aligned[63:0] = { 8{rxwr_data[7:0]}};
2'd1: wdata_aligned[63:0] = { 4{rxwr_data[15:0]}};
2'd2: wdata_aligned[63:0] = { 2{rxwr_data[31:0]}};
default: wdata_aligned[63:0] = { rxwr_srcaddr[31:0], rxwr_data[31:0]};
endcase
//TODO: Simplify logic below!!!!!
//Should include separate fields for address/data/datamode!!!!
always @*
begin
case(emwr_datamode[1:0])
case(rxwr_datamode[1:0])
2'd0: // byte
case(emwr_dstaddr[2:0])
case(rxwr_dstaddr[2:0])
3'd0: wstrb_aligned[7:0] = 8'h01;
3'd1: wstrb_aligned[7:0] = 8'h02;
3'd2: wstrb_aligned[7:0] = 8'h04;
@ -242,14 +290,14 @@ module emaxi(/*autoarg*/
default: wstrb_aligned[7:0] = 8'h80;
endcase
2'd1: // 16b hword
case(emwr_dstaddr[2:1])
case(rxwr_dstaddr[2:1])
2'd0: wstrb_aligned[7:0] = 8'h03;
2'd1: wstrb_aligned[7:0] = 8'h0c;
2'd2: wstrb_aligned[7:0] = 8'h30;
default: wstrb_aligned[7:0] = 8'hc0;
endcase
2'd2: // 32b word
if(emwr_dstaddr[2])
if(rxwr_dstaddr[2])
wstrb_aligned[7:0] = 8'hf0;
else
wstrb_aligned[7:0] = 8'h0f;
@ -257,15 +305,18 @@ module emaxi(/*autoarg*/
wstrb_aligned[7:0] = 8'hff;
endcase // case (emwr_datamode[1:0])
end // always @ *
// generate the write-data signals
//#########################################################################
//Write data channel
//#########################################################################
always @ (posedge m_axi_aclk )
if(~m_axi_aresetn)
begin
m_axi_wvalid <= 1'b0;
m_axi_wdata[63:0] <= 64'b0;
m_axi_wstrb[7:0] <= 8'b0;
m_axi_wlast <= 1'b1; // todo: no bursts for now?
m_axi_wlast <= 1'b1; // TODO: no bursts for now?
wvalid_b <= 1'b0;
wdata_b[63:0] <= 64'b0;
wstrb_b[7:0] <= 8'b0;
@ -282,40 +333,38 @@ module emaxi(/*autoarg*/
end
else
begin
m_axi_wvalid <= emwr_rd_en;//todo
m_axi_wvalid <= rxwr_access;
m_axi_wdata[63:0] <= wdata_aligned[63:0];
m_axi_wstrb[7:0] <= wstrb_aligned[7:0];
end
end // if ( ~axi_wvalid | w_go )
if( emwr_rd_en & m_axi_wvalid & ~w_go )
if( rxwr_access & m_axi_wvalid & ~w_go )
wvalid_b <= 1'b1;
else if( w_go )
wvalid_b <= 1'b0;
if( emwr_rd_en )
if( rxwr_access )
begin
wdata_b[63:0] <= wdata_aligned[63:0];
wstrb_b[7:0] <= wstrb_aligned[7:0];
end
end // else: !if(~m_axi_aresetn)
//----------------------------
// 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.
//----------------------------
//TODO: Can we improve this??
//#########################################################################
//Read request channel
//#########################################################################
//1. read request comes in on ar channel
//2. use src address to match with writes coming back
//3. Assumes in order returns
assign readinfo_in[47:0] =
{
7'b0,
emrq_srcaddr[31:0],//40:9
emrq_dstaddr[2:0], //8:6
emrq_ctrlmode[3:0], //5:2
emrq_datamode[1:0]
rxrd_srcaddr[31:0],//40:9
rxrd_dstaddr[2:0], //8:6
rxrd_ctrlmode[3:0], //5:2
rxrd_datamode[1:0]
};
fifo_sync
@ -333,82 +382,87 @@ module emaxi(/*autoarg*/
.clk (m_axi_aclk),
.reset (~m_axi_aresetn),
.wr_data (readinfo_in[47:0]),
.wr_en (emrq_rd_en),
.rd_en (readinfo_rden));
.wr_en (rxrd_access & ~readinfo_full),
.rd_en (~txrr_wait & m_axi_rvalid)
);
assign emrr_datamode[1:0] = readinfo_out[1:0];
assign emrr_ctrlmode[3:0] = readinfo_out[5:2];
assign emrr_dstaddr[31:0] = readinfo_out[40:9];
//----------------------------
// read address channel
//----------------------------
assign m_axi_araddr[31:0] = emrq_dstaddr[31:0];
assign m_axi_arsize[2:0] = {1'b0, emrq_datamode[1:0]};
assign m_axi_arlen[7:0] = 8'd0;
assign m_axi_arvalid = emrq_access & ~readinfo_full;
assign emrq_rd_en = m_axi_arvalid & m_axi_arready;
assign txrr_datamode[1:0] = readinfo_out[1:0];
assign txrr_ctrlmode[3:0] = readinfo_out[5:2];
assign txrr_dstaddr[31:0] = readinfo_out[40:9];
//#########################################################################
//Read address channel
//#########################################################################
//--------------------------------
// read data (and response) channel
//--------------------------------
assign m_axi_araddr[31:0] = rxrd_dstaddr[31:0];
assign m_axi_arsize[2:0] = {1'b0, rxrd_datamode[1:0]};
assign m_axi_arlen[7:0] = 8'd0;
assign m_axi_arvalid = rxrd_access & ~readinfo_full;
assign rxrd_wait = ~(m_axi_arvalid & m_axi_arready);
assign m_axi_rready = ~emrr_progfull;
assign readinfo_rden = ~emrr_progfull & m_axi_rvalid;
//#########################################################################
//Read response channel
//#########################################################################
assign m_axi_rready = ~txrr_wait;
assign readinfo_rden = ~txrr_wait & m_axi_rvalid;
assign emrr_write = 1'b1;
assign txrr_write = 1'b1;
always @( posedge m_axi_aclk )
if( ~m_axi_aresetn )
begin
emrr_data[31:0] <= 32'b0;
emrr_srcaddr[31:0] <= 32'b0;
emrr_access_reg <= 1'b0;
emrr_access <= 1'b0;
txrr_data[31:0] <= 32'b0;
txrr_srcaddr[31:0] <= 32'b0;
txrr_access_reg <= 1'b0;
txrr_access <= 1'b0;
end
else
begin
emrr_access_reg <= m_axi_rready & m_axi_rvalid;
emrr_access <= emrr_access_reg;//added pipeline stage for data
emrr_srcaddr[31:0] <= m_axi_rdata[63:32];
txrr_access_reg <= m_axi_rready & m_axi_rvalid;
txrr_access <= txrr_access_reg;//added pipeline stage for data
txrr_srcaddr[31:0] <= m_axi_rdata[63:32];
// steer read data according to size & host address lsbs
//all data needs to be right aligned
//(this is due to the Epiphany right aligning all words)
case(readinfo_out[1:0])//datamode
2'd0: // byte read
case(readinfo_out[8:6])
3'd0: emrr_data[7:0] <= m_axi_rdata[7:0];
3'd1: emrr_data[7:0] <= m_axi_rdata[15:8];
3'd2: emrr_data[7:0] <= m_axi_rdata[23:16];
3'd3: emrr_data[7:0] <= m_axi_rdata[31:24];
3'd4: emrr_data[7:0] <= m_axi_rdata[39:32];
3'd5: emrr_data[7:0] <= m_axi_rdata[47:40];
3'd6: emrr_data[7:0] <= m_axi_rdata[55:48];
default: emrr_data[7:0] <= m_axi_rdata[63:56];
3'd0: txrr_data[7:0] <= m_axi_rdata[7:0];
3'd1: txrr_data[7:0] <= m_axi_rdata[15:8];
3'd2: txrr_data[7:0] <= m_axi_rdata[23:16];
3'd3: txrr_data[7:0] <= m_axi_rdata[31:24];
3'd4: txrr_data[7:0] <= m_axi_rdata[39:32];
3'd5: txrr_data[7:0] <= m_axi_rdata[47:40];
3'd6: txrr_data[7:0] <= m_axi_rdata[55:48];
default: txrr_data[7:0] <= m_axi_rdata[63:56];
endcase
2'd1: // 16b hword
case( readinfo_out[8:7] )
2'd0: emrr_data[15:0] <= m_axi_rdata[15:0];
2'd1: emrr_data[15:0] <= m_axi_rdata[31:16];
2'd2: emrr_data[15:0] <= m_axi_rdata[47:32];
default: emrr_data[15:0] <= m_axi_rdata[63:48];
2'd0: txrr_data[15:0] <= m_axi_rdata[15:0];
2'd1: txrr_data[15:0] <= m_axi_rdata[31:16];
2'd2: txrr_data[15:0] <= m_axi_rdata[47:32];
default: txrr_data[15:0] <= m_axi_rdata[63:48];
endcase
2'd2: // 32b word
if( readinfo_out[8] )
emrr_data[31:0] <= m_axi_rdata[63:32];
txrr_data[31:0] <= m_axi_rdata[63:32];
else
emrr_data[31:0] <= m_axi_rdata[31:0];
txrr_data[31:0] <= m_axi_rdata[31:0];
// 64b word already defined by defaults above
2'd3: begin // 64b dword
emrr_data[31:0] <= m_axi_rdata[31:0];
txrr_data[31:0] <= m_axi_rdata[31:0];
end
endcase
end // else: !if( ~m_axi_aresetn )
endmodule
endmodule // emaxi
// Local Variables:
// verilog-library-directories:("." "../../emesh/hdl" "../../memory/hdl")
// End:
/*
copyright (c) 2014 adapteva, inc.
contributed by fred huettig <fred@adapteva.com>

View File

@ -1,86 +1,48 @@
module esaxi (/*autoarg*/
// Outputs
emwr_access, emwr_write, emwr_datamode, emwr_ctrlmode,
emwr_dstaddr, emwr_data, emwr_srcaddr, emrq_access, emrq_write,
emrq_datamode, emrq_ctrlmode, emrq_dstaddr, emrq_data,
emrq_srcaddr, emrr_rd_en, mi_clk, mi_rx_emmu_sel, mi_tx_emmu_sel,
mi_ecfg_sel, mi_embox_sel, mi_we, mi_addr, mi_din, s_axi_arready,
s_axi_awready, s_axi_bid, s_axi_bresp, s_axi_bvalid, s_axi_rid,
s_axi_rdata, s_axi_rlast, s_axi_rresp, s_axi_rvalid, s_axi_wready,
txwr_access, txwr_packet, txrd_access, txrd_packet, rxrr_wait,
s_axi_arready, s_axi_awready, s_axi_bid, s_axi_bresp, s_axi_bvalid,
s_axi_rid, s_axi_rdata, s_axi_rlast, s_axi_rresp, s_axi_rvalid,
s_axi_wready,
// Inputs
emwr_progfull, emrq_progfull, emrr_data, emrr_access, mi_ecfg_dout,
mi_tx_emmu_dout, mi_rx_emmu_dout, mi_embox_dout, ecfg_tx_ctrlmode,
ecfg_coreid, ecfg_timeout_enable, s_axi_aclk, s_axi_aresetn,
s_axi_arid, s_axi_araddr, s_axi_arburst, s_axi_arcache,
s_axi_arlock, s_axi_arlen, s_axi_arprot, s_axi_arqos, s_axi_arsize,
s_axi_arvalid, s_axi_awid, s_axi_awaddr, s_axi_awburst,
s_axi_awcache, s_axi_awlock, s_axi_awlen, s_axi_awprot,
s_axi_awqos, s_axi_awsize, s_axi_awvalid, s_axi_bready,
s_axi_rready, s_axi_wid, s_axi_wdata, s_axi_wlast, s_axi_wstrb,
s_axi_wvalid
txwr_wait, txrd_wait, rxrr_access, rxrr_packet, s_axi_aclk,
s_axi_aresetn, s_axi_arid, s_axi_araddr, s_axi_arburst,
s_axi_arcache, s_axi_arlock, s_axi_arlen, s_axi_arprot,
s_axi_arqos, s_axi_arsize, s_axi_arvalid, s_axi_awid, s_axi_awaddr,
s_axi_awburst, s_axi_awcache, s_axi_awlock, s_axi_awlen,
s_axi_awprot, s_axi_awqos, s_axi_awsize, s_axi_awvalid,
s_axi_bready, s_axi_rready, s_axi_wid, s_axi_wdata, s_axi_wlast,
s_axi_wstrb, s_axi_wvalid
);
parameter [11:0] c_read_tag_addr = 12'h810;//emesh srcaddr tag
parameter integer c_s_axi_addr_width = 30; //address width
parameter [11:0] ELINKID = 12'h810;
parameter [11:0] ID = 12'h810;
parameter IDW = 12;
parameter PW = 104;
parameter [15:0] RETURN_ADDR = {ID,4'hE};
parameter AW = 32;
parameter DW = 32;
/*****************************/
/*Write request for TX fifo */
/*****************************/
output emwr_access;
output emwr_write;
output [1:0] emwr_datamode;
output [3:0] emwr_ctrlmode;
output [31:0] emwr_dstaddr;
output [31:0] emwr_data;
output [31:0] emwr_srcaddr;
input emwr_progfull;
output txwr_access;
output [PW-1:0] txwr_packet;
input txwr_wait;
/*****************************/
/*Read request for TX fifo */
/*****************************/
output emrq_access;
output emrq_write;
output [1:0] emrq_datamode;
output [3:0] emrq_ctrlmode;
output [31:0] emrq_dstaddr;
output [31:0] emrq_data;
output [31:0] emrq_srcaddr;
input emrq_progfull; //TODO? used for?
output txrd_access;
output [PW-1:0] txrd_packet;
input txrd_wait;
/*****************************/
/*Read response from RX fifo */
/*****************************/
//Only data needed
input [31:0] emrr_data;
input emrr_access;
output emrr_rd_en; //update read fifo
/*****************************/
/*Register RD/WR Interface */
/*****************************/
output mi_clk;
output mi_rx_emmu_sel;
output mi_tx_emmu_sel;
output mi_ecfg_sel;
output mi_embox_sel;
output mi_we;
output [19:0] mi_addr;
output [31:0] mi_din;
input [31:0] mi_ecfg_dout;
input [31:0] mi_tx_emmu_dout;
input [31:0] mi_rx_emmu_dout;
input [31:0] mi_embox_dout;
/*****************************/
/*Config Settings */
/*****************************/
input [3:0] ecfg_tx_ctrlmode;
input [11:0] ecfg_coreid;
input ecfg_timeout_enable;
input rxrr_access;
input [PW-1:0] rxrr_packet;
output rxrr_wait;
/*****************************/
/*AXI slave interface */
/*****************************/
@ -135,19 +97,17 @@ module esaxi (/*autoarg*/
input [3:0] s_axi_wstrb;
input s_axi_wvalid;
output s_axi_wready;
/*-------------------------BODY----------------------------------*/
//###################################################
//#WIRE/REG DECLARATIONS
//###################################################
reg s_axi_awready;
reg s_axi_wready;
reg s_axi_bvalid;
reg [1:0] s_axi_bresp;
reg s_axi_arready;
reg [31:0] emwr_data_reg;
reg [31:0] emwr_dstaddr_reg;
reg [3:0] emwr_ctrlmode_reg;
reg [1:0] emwr_datamode_reg;
reg [31:0] axi_awaddr; // 32b for epiphany addr
reg [1:0] axi_awburst;
reg [2:0] axi_awsize;
@ -167,47 +127,75 @@ module esaxi (/*autoarg*/
reg write_active;
reg b_wait; // waiting to issue write response (unlikely?)
reg emwr_access_all;
reg [3:0] emwr_ctrlmode;
reg [1:0] emwr_datamode;
reg [31:0] emwr_dstaddr;
reg [31:0] emwr_data;
reg [31:0] emwr_srcaddr; //upper 32 bits in case 64 bit writes are supported
reg txwr_access;
reg [1:0] txwr_datamode;
reg [31:0] txwr_dstaddr;
reg [31:0] txwr_data;
reg emrq_access_all;
reg [3:0] emrq_ctrlmode;
reg [1:0] emrq_datamode;
reg [31:0] emrq_dstaddr;
reg [31:0] emrq_srcaddr; //upper 32 bits in case 64 bit writes are supported
reg [31:0] txwr_data_reg;
reg [31:0] txwr_dstaddr_reg;
reg [1:0] txwr_datamode_reg;
reg pre_wr_en; // delay for data alignment
reg txrd_access;
reg [1:0] txrd_datamode;
reg [31:0] txrd_dstaddr;
reg [31:0] txrd_srcaddr; //read reaspne address
reg pre_wr_en; // delay for data alignment
reg ractive_reg; // need leading edge of active for 1st req
reg rnext;
reg mi_rx_emmu_reg;
reg mi_tx_emmu_reg;
reg mi_ecfg_reg;
reg mi_embox_reg;
reg mi_rd_reg;
wire last_wr_beat;
wire last_rd_beat;
wire mi_wr;
wire mi_rd;
wire mi_we;
wire mi_en;
wire [31:0] mi_dout;
wire mi_sel;
wire [31:0] emrr_mux_data;
wire [31:0] rxrr_mux_data;
wire [DW-1:0] rxrr_data;
//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)
//TODO? Do we really need this?
localparam integer addr_lsb = 2;
wire [11:0] elinkid=ELINKID;
//###################################################
//#PACKET TO MESH
//###################################################
//TXWR
emesh2packet e2p_txwr (
// Outputs
.packet_out (txwr_packet[PW-1:0]),
// Inputs
.access_in (txwr_access),
.write_in (1'b1),
.datamode_in (txwr_datamode[1:0]),
.ctrlmode_in (4'b0),
.dstaddr_in (txwr_dstaddr[AW-1:0]),
.data_in (txwr_data[DW-1:0]),
.srcaddr_in (32'b0)//only 32b slave write supported
);
//TXRD
emesh2packet e2p_txrd (
// Outputs
.packet_out (txrd_packet[PW-1:0]),
// Inputs
.access_in (txrd_access),
.write_in (txrd_write),
.datamode_in (txrd_datamode[1:0]),
.ctrlmode_in (4'b0),
.dstaddr_in (txrd_dstaddr[AW-1:0]),
.data_in (32'b0),
.srcaddr_in (txrd_srcaddr[AW-1:0])
);
//RXRR
packet2emesh p2e_rxrr (
// Outputs
.access_out (),
.write_out (),
.datamode_out (),
.ctrlmode_out (),
.dstaddr_out (),
.data_out (rxrr_data[DW-1:0]),
.srcaddr_out (),
// Inputs
.packet_in (rxrr_packet[PW-1:0])
);
//###################################################
//#WRITE ADDRESS CHANNEL
@ -243,7 +231,6 @@ module esaxi (/*autoarg*/
end // else: !if(~s_axi_aresetn)
end // always @ (posedge s_axi_aclk )
// capture address & other aw info, update address during cycle
always @( posedge s_axi_aclk )
if (~s_axi_aresetn)
@ -260,23 +247,20 @@ module esaxi (/*autoarg*/
axi_awaddr[31:0] <= s_axi_awaddr[31:0];
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 & s_axi_wready )
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.
//TODO: BUG!!
axi_awaddr[31:addr_lsb] <= axi_awaddr[31:addr_lsb] + 30'd1;
//awaddr alignedto data width
axi_awaddr[addr_lsb-1:0] <= {addr_lsb{1'b0}};
end // both fixed & wrapping types are treated as fixed, no update.
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:2] <= axi_awaddr[31:2] + 30'd1;
//awaddr alignedto data width
axi_awaddr[1:0] <= 2'b0;
end // both fixed & wrapping types are treated as fixed, no update.
end // else: !if(~s_axi_aresetn)
//###################################################
//#WRITE CHANNEL
//#WRITE RESPONSE CHANNEL
//###################################################
always @ (posedge s_axi_aclk)
if(~s_axi_aresetn)
@ -286,13 +270,9 @@ module esaxi (/*autoarg*/
if( last_wr_beat )
s_axi_wready <= 1'b0;
else if( write_active )
s_axi_wready <= ~emwr_progfull;
s_axi_wready <= ~txwr_wait;
end
// 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 )
if (~s_axi_aresetn)
begin
@ -305,7 +285,7 @@ module esaxi (/*autoarg*/
if( last_wr_beat )
begin
s_axi_bvalid <= 1'b1;
s_axi_bresp[1:0] <= 2'b0; // 'okay' response
s_axi_bresp[1:0] <= 2'b0; // 'okay' response
b_wait <= ~s_axi_bready; // note: assumes bready will not drop without valid?
end
else if (s_axi_bready & s_axi_bvalid)
@ -315,13 +295,11 @@ module esaxi (/*autoarg*/
end
end // else: !if( s_axi_aresetn == 1'b0 )
//###################################################
//#READ REQUEST CHANNEL
//###################################################
assign last_rd_beat = s_axi_rvalid & s_axi_rlast & s_axi_rready;
assign last_rd_beat = s_axi_rvalid & s_axi_rlast & s_axi_rready;
always @( posedge s_axi_aclk )
if (~s_axi_aresetn)
@ -358,9 +336,8 @@ module esaxi (/*autoarg*/
else
begin
if( s_axi_arready & s_axi_arvalid )
begin
//NOTE: upper 2 bits get chopped by Zynq
axi_araddr[31:0] <= s_axi_araddr[31:0]; //transfer start address
begin
axi_araddr[31:0] <= s_axi_araddr[31:0]; //NOTE: upper 2 bits get chopped by Zynq
axi_arlen <= s_axi_arlen;
axi_arburst <= s_axi_arburst;
axi_arsize <= s_axi_arsize;
@ -376,9 +353,9 @@ module esaxi (/*autoarg*/
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;
axi_araddr[31:2] <= axi_araddr[31:2] + 1;
//araddr aligned to 4 byte boundary
axi_araddr[addr_lsb-1:0] <= {addr_lsb{1'b0}};
axi_araddr[1:0] <= 2'b0;
//for awsize = 4 bytes (010)
end
end // if ( s_axi_rvalid & s_axi_rready)
@ -386,119 +363,103 @@ module esaxi (/*autoarg*/
//###################################################
//#WRITE DATA
//#WRITE REQUEST
//###################################################
assign emwr_write = 1'b1;
assign txwr_write = 1'b1;
always @( posedge s_axi_aclk )
if (~s_axi_aresetn)
begin
emwr_data_reg[31:0] <= 32'd0;
emwr_dstaddr_reg[31:0] <= 32'd0;
emwr_ctrlmode_reg[3:0] <= 4'd0;
emwr_datamode_reg[1:0] <= 2'd0;
emwr_access_all <= 1'b0;
txwr_data_reg[31:0] <= 32'd0;
txwr_dstaddr_reg[31:0] <= 32'd0;
txwr_datamode_reg[1:0] <= 2'd0;
txwr_access <= 1'b0;
pre_wr_en <= 1'b0;
end
else
begin
pre_wr_en <= s_axi_wready & s_axi_wvalid;
emwr_access_all <= pre_wr_en;
emwr_ctrlmode_reg[3:0] <= ecfg_tx_ctrlmode[3:0];//static
emwr_datamode_reg[1:0] <= axi_awsize[1:0];
emwr_dstaddr_reg[31:2] <= axi_awaddr[31:2]; //set lsbs of address based on write strobes
txwr_access <= pre_wr_en;
txwr_datamode_reg[1:0] <= axi_awsize[1:0];
txwr_dstaddr_reg[31:2] <= axi_awaddr[31:2]; //set lsbs of address based on write strobes
if(s_axi_wstrb[0] | (axi_awsize[1:0]==2'b10))
begin
emwr_data_reg[31:0] <= s_axi_wdata[31:0];
emwr_dstaddr_reg[1:0] <= 2'd0;
txwr_data_reg[31:0] <= s_axi_wdata[31:0];
txwr_dstaddr_reg[1:0] <= 2'd0;
end
else if(s_axi_wstrb[1])
begin
emwr_data_reg[31:0] <= {8'd0, s_axi_wdata[31:8]};
emwr_dstaddr_reg[1:0] <= 2'd1;
txwr_data_reg[31:0] <= {8'd0, s_axi_wdata[31:8]};
txwr_dstaddr_reg[1:0] <= 2'd1;
end
else if(s_axi_wstrb[2])
begin
emwr_data_reg[31:0] <= {16'd0, s_axi_wdata[31:16]};
emwr_dstaddr_reg[1:0] <= 2'd2;
txwr_data_reg[31:0] <= {16'd0, s_axi_wdata[31:16]};
txwr_dstaddr_reg[1:0] <= 2'd2;
end
else
begin
emwr_data_reg[31:0] <= {24'd0, s_axi_wdata[31:24]};
emwr_dstaddr_reg[1:0] <= 2'd3;
txwr_data_reg[31:0] <= {24'd0, s_axi_wdata[31:24]};
txwr_dstaddr_reg[1:0] <= 2'd3;
end
end // else: !if(~s_axi_aresetn)
//Pipeline stage
always @( posedge s_axi_aclk )
//Pipeline stage!
always @( posedge s_axi_aclk )
if (~s_axi_aresetn)
begin
emwr_srcaddr[31:0] <= 32'd0;
emwr_data[31:0] <= 32'd0;
emwr_dstaddr[31:0] <= 32'd0;
emwr_ctrlmode[3:0] <= 4'd0;
emwr_datamode[1:0] <= 2'd0;
txwr_data[31:0] <= 32'd0;
txwr_dstaddr[31:0] <= 32'd0;
txwr_datamode[1:0] <= 2'd0;
end
else
begin
emwr_srcaddr[31:0] <= 32'b0;
emwr_data[31:0] <= emwr_data_reg[31:0];
emwr_dstaddr[31:0] <= emwr_dstaddr_reg[31:0];
emwr_ctrlmode[3:0] <= emwr_ctrlmode_reg[3:0];
emwr_datamode[1:0] <= emwr_datamode_reg[1:0];
txwr_data[31:0] <= txwr_data_reg[31:0];
txwr_dstaddr[31:0] <= txwr_dstaddr_reg[31:0];
txwr_datamode[1:0] <= txwr_datamode_reg[1:0];
end // else: !if(~s_axi_aresetn)
assign emwr_access=emwr_access_all & ~(emwr_dstaddr[31:20]==elinkid[11:0]);
//###################################################
//#READ REQUEST (DATA CHANNEL)
//###################################################
// ------------------------------------------
// -- 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.
// -- data to come back through the rx read response 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.
// ------------------------------------------
// since we're only sending one req at a time we can ignore the fifo flags
// always read response data immediately
assign emrr_rd_en = emrr_access & ~mi_rd_reg; //TODO: Verify this assumption!!!
// -- one at a time.
assign emrq_write = 1'b0;
assign emrq_data[31:0] = 32'b0;
assign txrd_write = 1'b0;
always @( posedge s_axi_aclk )
if (~s_axi_aresetn)
begin
emrq_access_all <= 1'b0;
emrq_datamode[1:0] <= 2'd0;
emrq_ctrlmode[3:0] <= 4'd0;
emrq_dstaddr[31:0] <= 32'd0;
emrq_srcaddr[31:0] <= 32'd0;
txrd_access <= 1'b0;
txrd_datamode[1:0] <= 2'd0;
txrd_dstaddr[31:0] <= 32'd0;
txrd_srcaddr[31:0] <= 32'd0;
ractive_reg <= 1'b0;
rnext <= 1'b0;
end
else
begin
ractive_reg <= read_active; //read request state machone
rnext <= s_axi_rvalid & s_axi_rready & ~s_axi_rlast;
emrq_access_all <= ( ~ractive_reg & read_active ) | rnext;
emrq_datamode[1:0] <= axi_arsize[1:0];
emrq_ctrlmode[3:0] <= ecfg_tx_ctrlmode;
emrq_dstaddr[31:0] <= axi_araddr[31:0];
emrq_srcaddr[31:0] <= {c_read_tag_addr[11:0], 20'd0};//TODO? What can we do with lower 32 bits?
ractive_reg <= read_active;
rnext <= s_axi_rvalid & s_axi_rready & ~s_axi_rlast;
txrd_access <= ( ~ractive_reg & read_active ) | rnext;
txrd_datamode[1:0] <= axi_arsize[1:0];
txrd_dstaddr[31:0] <= axi_araddr[31:0];
txrd_srcaddr[31:0] <= {RETURN_ADDR, 16'd0};
//TODO: use arid+srcaddr for out of order ?
end
///Only letting through proper read requests
assign emrq_access=emrq_access_all & ~(emrq_dstaddr[31:20]==elinkid[11:0]);
//###################################################
//#READ RESPONSE (DATA CHANNEL)
//###################################################
//Read response AXI state machine
//Only one outstanding read
assign rxrr_wait = 1'b0;
always @( posedge s_axi_aclk )
if (~s_axi_aresetn)
begin
@ -508,21 +469,19 @@ module esaxi (/*autoarg*/
end
else
begin
if( emrr_access | mi_rd_reg )
if( rxrr_access )
begin
s_axi_rvalid <= 1'b1;
s_axi_rresp <= 2'd0;
case( axi_arsize[1:0] )
2'b00: s_axi_rdata[31:0] <= {4{emrr_mux_data[7:0]}}; //8-bit
2'b01: s_axi_rdata[31:0] <= {2{emrr_mux_data[15:0]}}; //16-bit
default: s_axi_rdata[31:0] <= emrr_mux_data[31:0]; //32-bit
2'b00: s_axi_rdata[31:0] <= {4{rxrr_data[7:0]}}; //8-bit
2'b01: s_axi_rdata[31:0] <= {2{rxrr_data[15:0]}}; //16-bit
default: s_axi_rdata[31:0] <= rxrr_data[31:0]; //32-bit
endcase // case ( axi_arsize[1:0] )
end
else if( s_axi_rready )
s_axi_rvalid <= 1'b0;
end // else: !if( s_axi_aresetn == 1'b0 )
endmodule // esaxi