2014-12-14 22:24:16 -05:00
|
|
|
/*
|
|
|
|
###########################################################################
|
2015-04-27 16:03:57 -04:00
|
|
|
# **EMMU**
|
|
|
|
#
|
|
|
|
# This block uses the upper 12 bits [31:20] of a memory address as an index
|
|
|
|
# to read an entry from a table.
|
2015-04-11 00:04:18 -04:00
|
|
|
#
|
2015-04-27 16:03:57 -04:00
|
|
|
# The table is written from the mi_* configuration interface.
|
|
|
|
#
|
|
|
|
# The table can be configured as 12 bits wide or 44 bits wide.
|
|
|
|
#
|
|
|
|
# 32bit address output = {table_data[11:0],dstaddr[19:0]}
|
|
|
|
# 64bit address output = {table_data[43:0],dstaddr[19:0]}
|
2014-11-05 14:31:05 -05:00
|
|
|
#
|
|
|
|
############################################################################
|
|
|
|
*/
|
|
|
|
module emmu (/*AUTOARG*/
|
|
|
|
// Outputs
|
2016-01-11 17:35:53 -05:00
|
|
|
reg_rdata, emesh_access_out, emesh_packet_out,
|
2014-11-05 14:31:05 -05:00
|
|
|
// Inputs
|
2016-01-11 20:49:31 -05:00
|
|
|
wr_clk, rd_clk, nreset, mmu_en, reg_access, reg_packet,
|
|
|
|
emesh_access_in, emesh_packet_in, emesh_wait_in
|
2014-11-05 14:31:05 -05:00
|
|
|
);
|
2016-01-11 17:35:53 -05:00
|
|
|
|
|
|
|
//#####################################################################
|
|
|
|
//# INTERFACE
|
|
|
|
//#####################################################################
|
|
|
|
|
|
|
|
// parameters
|
2016-01-13 15:31:38 -05:00
|
|
|
parameter AW = 32; // address width
|
|
|
|
parameter MW = 48; // width of table
|
|
|
|
parameter MAW = 12; // memory addres width (entries = 1<<MAW)
|
|
|
|
localparam PW = 2*AW+40; // packet width
|
2015-03-25 19:25:12 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
// clocks
|
|
|
|
input wr_clk; // single clock
|
|
|
|
input rd_clk; // single clock
|
2016-01-11 20:49:31 -05:00
|
|
|
input nreset; // async active low reset
|
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
// config
|
|
|
|
input mmu_en; // enables mmu (by config register)
|
|
|
|
|
|
|
|
// register access
|
|
|
|
input reg_access; // valid packet
|
|
|
|
input [PW-1:0] reg_packet; // packet
|
|
|
|
output [31:0] reg_rdata; // readback data
|
2015-10-19 11:08:28 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
// input packet
|
|
|
|
input emesh_access_in; // valid packet
|
|
|
|
input [PW-1:0] emesh_packet_in; // input packet
|
|
|
|
input emesh_wait_in; // pushback
|
|
|
|
|
|
|
|
// translated packet
|
|
|
|
output emesh_access_out; // valid packet
|
|
|
|
output [PW-1:0] emesh_packet_out; // output packet
|
2015-09-14 13:29:42 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
//#####################################################################
|
|
|
|
//# BODY
|
|
|
|
//#####################################################################
|
|
|
|
|
|
|
|
//wires + regs
|
2015-04-24 17:39:05 -04:00
|
|
|
reg emesh_access_out;
|
|
|
|
reg [PW-1:0] emesh_packet_reg;
|
2015-04-27 23:51:00 -04:00
|
|
|
wire [63:0] emesh_dstaddr_out;
|
2015-04-24 17:39:05 -04:00
|
|
|
wire [MW-1:0] emmu_lookup_data;
|
2016-01-11 17:35:53 -05:00
|
|
|
wire [MW-1:0] mem_wem;
|
|
|
|
wire [MW-1:0] mem_data;
|
|
|
|
wire [AW-1:0] emesh_dstaddr_in;
|
|
|
|
|
|
|
|
/*AUTOWIRE*/
|
|
|
|
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
|
|
|
wire [4:0] reg_ctrlmode; // From pe2 of packet2emesh.v
|
|
|
|
wire [AW-1:0] reg_data; // From pe2 of packet2emesh.v
|
|
|
|
wire [1:0] reg_datamode; // From pe2 of packet2emesh.v
|
|
|
|
wire [AW-1:0] reg_dstaddr; // From pe2 of packet2emesh.v
|
|
|
|
wire [AW-1:0] reg_srcaddr; // From pe2 of packet2emesh.v
|
|
|
|
wire reg_write; // From pe2 of packet2emesh.v
|
|
|
|
// End of automatics
|
|
|
|
|
|
|
|
//###########################
|
|
|
|
//# WRITE LOGIC
|
|
|
|
//###########################
|
2015-04-23 17:54:23 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
/*packet2emesh AUTO_TEMPLATE ( .\(.*\)_in (reg_\1[]));*/
|
2015-04-23 23:16:03 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
packet2emesh #(.AW(AW))
|
|
|
|
pe2 (/*AUTOINST*/
|
|
|
|
// Outputs
|
|
|
|
.write_in (reg_write), // Templated
|
|
|
|
.datamode_in (reg_datamode[1:0]), // Templated
|
|
|
|
.ctrlmode_in (reg_ctrlmode[4:0]), // Templated
|
|
|
|
.dstaddr_in (reg_dstaddr[AW-1:0]), // Templated
|
|
|
|
.srcaddr_in (reg_srcaddr[AW-1:0]), // Templated
|
|
|
|
.data_in (reg_data[AW-1:0]), // Templated
|
|
|
|
// Inputs
|
|
|
|
.packet_in (reg_packet[PW-1:0])); // Templated
|
|
|
|
|
2015-04-11 00:04:18 -04:00
|
|
|
//write controls
|
2016-01-11 17:35:53 -05:00
|
|
|
assign mem_wem[MW-1:0] = ~reg_dstaddr[2] ? {{(MW-32){1'b0}},32'hFFFFFFFF} :
|
2016-01-13 15:31:38 -05:00
|
|
|
{{(MW-32){1'b1}},32'h00000000};
|
2016-01-11 17:35:53 -05:00
|
|
|
|
|
|
|
assign mem_write = reg_access &
|
2016-01-13 15:31:38 -05:00
|
|
|
reg_write;
|
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
assign mem_data[MW-1:0] = {reg_data[31:0], reg_data[31:0]};
|
2015-03-25 19:25:12 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
//###########################
|
|
|
|
//# EMESh PACKET DECODE
|
|
|
|
//###########################
|
2015-05-03 23:24:27 -04:00
|
|
|
|
2016-01-10 11:51:49 -05:00
|
|
|
packet2emesh #(.AW(32))
|
2016-01-11 17:35:53 -05:00
|
|
|
p2e (
|
|
|
|
// Outputs
|
|
|
|
.write_in (),
|
2016-01-10 11:51:49 -05:00
|
|
|
.datamode_in (),
|
|
|
|
.ctrlmode_in (),
|
2016-01-11 17:35:53 -05:00
|
|
|
.dstaddr_in (emesh_dstaddr_in[AW-1:0]),
|
2016-01-10 11:51:49 -05:00
|
|
|
.srcaddr_in (),
|
2016-01-11 17:35:53 -05:00
|
|
|
.data_in (),
|
|
|
|
// Inputs
|
|
|
|
.packet_in (emesh_packet_in[PW-1:0])
|
|
|
|
);
|
|
|
|
|
|
|
|
//###########################
|
|
|
|
//# LOOKUP TABLE
|
|
|
|
//###########################
|
|
|
|
|
|
|
|
oh_memory_dp #(.DW(MW),
|
|
|
|
.AW(MAW))
|
|
|
|
memory_dp (//read port
|
|
|
|
.rd_dout (emmu_lookup_data[MW-1:0]),
|
|
|
|
.rd_en (emesh_access_in),
|
|
|
|
.rd_addr (emesh_dstaddr_in[31:20]),
|
|
|
|
.rd_clk (rd_clk),
|
|
|
|
//write port
|
|
|
|
.wr_en (mem_write),
|
|
|
|
.wr_wem (mem_wem[MW-1:0]),
|
|
|
|
.wr_addr (reg_dstaddr[14:3]),
|
|
|
|
.wr_din (mem_data[MW-1:0]),
|
|
|
|
.wr_clk (wr_clk)
|
|
|
|
);
|
|
|
|
|
|
|
|
//###########################
|
|
|
|
//# OUTPUT PACKET
|
|
|
|
//###########################
|
2015-09-14 13:29:42 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
//pipeline (compensates for 1 cycle memory access)
|
2016-01-11 20:49:31 -05:00
|
|
|
|
|
|
|
always @ (posedge rd_clk)
|
|
|
|
if (!nreset)
|
|
|
|
emesh_access_out <= 1'b0;
|
|
|
|
else if(~emesh_wait_in)
|
|
|
|
emesh_access_out <= emesh_access_in;
|
|
|
|
|
2015-10-19 11:08:28 -04:00
|
|
|
always @ (posedge rd_clk)
|
2016-01-11 17:35:53 -05:00
|
|
|
if(~emesh_wait_in)
|
2015-11-13 16:22:23 -05:00
|
|
|
emesh_packet_reg[PW-1:0] <= emesh_packet_in[PW-1:0];
|
2015-09-14 13:29:42 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
//like base register for trampolining to 64 bit space
|
|
|
|
assign emesh_dstaddr_out[63:0] = mmu_en ? {emmu_lookup_data[43:0],
|
|
|
|
emesh_packet_reg[27:8]} :
|
|
|
|
{32'b0,emesh_packet_reg[39:8]};
|
|
|
|
|
|
|
|
//concatenating output packet
|
2015-04-24 17:39:05 -04:00
|
|
|
assign emesh_packet_out[PW-1:0] = {emesh_packet_reg[PW-1:40],
|
2015-10-19 11:08:28 -04:00
|
|
|
emesh_dstaddr_out[31:0],
|
|
|
|
emesh_packet_reg[7:0]
|
|
|
|
};
|
2015-04-23 17:54:23 -04:00
|
|
|
|
2015-04-17 10:08:17 -04:00
|
|
|
|
2016-01-11 17:35:53 -05:00
|
|
|
//assign emesh_packet_hi_out[31:0] = emesh_dstaddr_out[63:32];
|
2015-04-23 17:54:23 -04:00
|
|
|
|
2014-11-05 14:31:05 -05:00
|
|
|
endmodule // emmu
|
2015-04-08 23:40:16 -04:00
|
|
|
// Local Variables:
|
2015-11-13 16:22:23 -05:00
|
|
|
// verilog-library-directories:("." "../../common/hdl" "../../memory/hdl" "../../emesh/hdl")
|
2015-04-08 23:40:16 -04:00
|
|
|
// End:
|
|
|
|
|
2014-11-05 14:31:05 -05:00
|
|
|
|
|
|
|
|
2015-03-24 20:44:03 -04:00
|
|
|
|