mirror of
https://github.com/aolofsson/oh.git
synced 2025-01-17 20:02:53 +08:00
a68bba1572
- 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 -
153 lines
4.1 KiB
Verilog
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:
|
|
|
|
|