1
0
mirror of https://github.com/aolofsson/oh.git synced 2025-01-17 20:02:53 +08:00
oh/elink/hdl/etx_arbiter.v
Andreas Olofsson a68bba1572 Cleaning up register interface
- Removed the cfgif block, too confusing. There is a good lesson here. Probably the n'th time I that I have been overzealous about reuse. When you end up adding a parameter to a block that duplicates the logic 2X it's always better to create two separate blocks...
- Changed the register access interface to packet format
- Change the priority on the etx_arbiter to pick read responses first
- Removed redundant signals
- Took away the read resonse bypass on remap in tx for now..
- Removed defparams (convention)
- Unified wait signal on tx
- Fixed cfg wait
-
2016-01-11 17:35:53 -05:00

153 lines
4.1 KiB
Verilog

/*
########################################################################
EPIPHANY eMesh Arbiter
########################################################################
This block takes three FIFO inputs (write, read request, read response)
and the DMA channel, arbitrates between the active channels, and forwards
the result to the transmit output pins.
Arbitration Priority:
1) read responses (highest)
2) host writes
3) read requests from host (lowest)
*/
module etx_arbiter (/*AUTOARG*/
// Outputs
txwr_wait, txrd_wait, txrr_wait, etx_access, cfg_access,
etx_packet,
// Inputs
clk, nreset, txwr_access, txwr_packet, txrd_access, txrd_packet,
txrr_access, txrr_packet, etx_wait, etx_cfg_wait
);
parameter AW = 32;
parameter PW = 2*AW+40;
parameter ID = 0;
//tx clock and reset
input clk;
input nreset;
//Write Request (from slave)
input txwr_access;
input [PW-1:0] txwr_packet;
output txwr_wait;
//Read Request (from slave)
input txrd_access;
input [PW-1:0] txrd_packet;
output txrd_wait;
//Read Response (from master)
input txrr_access;
input [PW-1:0] txrr_packet;
output txrr_wait;
//Wait signal inputs
input etx_wait;
input etx_cfg_wait;
//Outgoing transaction
output etx_access; //for IO
output cfg_access; //for RX/RX configuration
output [PW-1:0] etx_packet;
//regs
reg etx_access;
reg [PW-1:0] etx_packet;
reg cfg_access; //bypass translation on read response
//wires
wire [3:0] txrd_ctrlmode;
wire [3:0] txwr_ctrlmode;
wire access_in;
wire [PW-1:0] etx_packet_mux;
wire txrr_grant;
wire txrd_grant;
wire txwr_grant;
wire [PW-1:0] etx_mux;
wire [31:0] dstaddr_mux;
//########################################################################
//# Arbiter
//########################################################################
//TODO: change to round robin!!! (live lock hazard)
oh_arbiter #(.N(3)) arbiter (.grants({txrd_grant,
txwr_grant, //highest priority
txrr_grant
}),
.requests({txrd_access,
txwr_access,
txrr_access
})
);
oh_mux3 #(.DW(PW))
mux3(.out (etx_mux[PW-1:0]),
.in0 (txwr_packet[PW-1:0]),.sel0 (txwr_grant),
.in1 (txrd_packet[PW-1:0]),.sel1 (txrd_grant),
.in2 (txrr_packet[PW-1:0]),.sel2 (txrr_grant)
);
//######################################################################
//Pushback (stall) Signals
//######################################################################
assign etx_all_wait = etx_wait | etx_cfg_wait;
//Read response
assign txrr_wait = etx_all_wait;
//Write waits on pin wr wait or cfg_wait
assign txwr_wait = etx_all_wait |
txrr_access;
//Host read request (self throttling, one read at a time)
assign txrd_wait = etx_all_wait |
txrr_access |
txwr_access;
//#####################################################################
//# Pipeline stage (arbiter+mux takes time..)
//#####################################################################
assign access_in = (txwr_grant & ~txwr_wait) |
(txrd_grant & ~txrd_wait) |
(txrr_grant & ~txrr_wait);
packet2emesh #(.AW(AW))
p2e (.write_in (),
.datamode_in (),
.ctrlmode_in (),
.dstaddr_in (dstaddr_mux[31:0]),
.srcaddr_in (),
.data_in (),
.packet_in (etx_mux[PW-1:0]));
assign cfg_match = (dstaddr_mux[31:20]==ID);
//access decode
always @ (posedge clk)
if (!nreset)
begin
etx_access <= 1'b0;
cfg_access <= 1'b0;
end
else if (~etx_all_wait)
begin
etx_access <= access_in & ~cfg_match;
cfg_access <= access_in & cfg_match;
end
//packet
always @ (posedge clk)
if (access_in & ~etx_all_wait)
etx_packet[PW-1:0] <= etx_mux[PW-1:0];
endmodule // etx_arbiter
// Local Variables:
// verilog-library-directories:("." "../../emesh/hdl" "../../common/hdl")
// End: