module f15_histo_mem #(
	parameter integer ADDR_WIDTH = 16
)(
	// Port A Read
	input  wire [ADDR_WIDTH-1:0] addr_AR,
	output reg  [8:0] data_AR,
	input  wire ena_AR,

	// Port A Write
	input  wire [ADDR_WIDTH-1:0] addr_AW,
	input  wire [8:0] data_AW,
	input  wire ena_AW,

	// Port B Read
	input  wire [ADDR_WIDTH-1:0] addr_BR,
	output reg  [8:0] data_BR,
	input  wire ena_BR,

	// Port B Write
	input  wire [ADDR_WIDTH-1:0] addr_BW,
	input  wire [8:0] data_BW,
	input  wire ena_BW,

	// Error detection
	output reg  conflict_A,
	output reg  conflict_B,

	// Common
	input  wire clk,
	input  wire rst
);

	// Signals
		// Memory banks IF
	wire [ADDR_WIDTH-2:0] even_addra, odd_addra;
	wire [ADDR_WIDTH-2:0] even_addrb, odd_addrb;
	wire [8:0] even_dia, odd_dia;
	wire [8:0] even_dib, odd_dib;
	wire [8:0] even_doa, odd_doa;
	wire [8:0] even_dob, odd_dob;
	wire even_wea, odd_wea;
	wire even_web, odd_web;
	wire even_rea, odd_rea;
	wire even_reb, odd_reb;

		// Control
	wire sel_A, sel_B;


	// Mux selection
	assign sel_A = ena_AR ? addr_AR[0] : ~addr_AW[0];
	assign sel_B = ena_BR ? addr_BR[0] : ~addr_BW[0];

	// Conflict detection
	always @(posedge clk)
	begin
		conflict_A <= !(addr_AR[0] ^ addr_AW[0]) & ena_AR & ena_AW;
		conflict_B <= !(addr_BR[0] ^ addr_BW[0]) & ena_BR & ena_BW;
	end

	// Control signals
	assign even_wea =  sel_A & ena_AW;
	assign odd_wea  = !sel_A & ena_AW;
	assign even_web =  sel_B & ena_BW;
	assign odd_web  = !sel_B & ena_BW;
	assign even_rea = !sel_A & ena_AR;
	assign odd_rea  =  sel_A & ena_AR;
	assign even_reb = !sel_B & ena_BR;
	assign odd_reb  =  sel_B & ena_BR;

	// Address path mapping
	assign even_addra = sel_A ? addr_AW[ADDR_WIDTH-1:1] : addr_AR[ADDR_WIDTH-1:1];
	assign even_addrb = sel_B ? addr_BW[ADDR_WIDTH-1:1] : addr_BR[ADDR_WIDTH-1:1];
	assign odd_addra  = sel_A ? addr_AR[ADDR_WIDTH-1:1] : addr_AW[ADDR_WIDTH-1:1];
	assign odd_addrb  = sel_B ? addr_BR[ADDR_WIDTH-1:1] : addr_BW[ADDR_WIDTH-1:1];

	// Data path mapping
	assign even_dia = data_AW;
	assign odd_dia  = data_AW;
	assign even_dib = data_BW;
	assign odd_dib  = data_BW;

	always @(posedge clk)
	begin
		data_AR <= even_doa | odd_doa;
		data_BR <= even_dob | odd_dob;
	end

	// Instanciate memory banks
	f15_histo_mem_bank #(
		.ADDR_WIDTH(ADDR_WIDTH-1)
	) mem_even (
		.addra(even_addra),
		.addrb(even_addrb),
		.dia(even_dia),
		.dib(even_dib),
		.doa(even_doa),
		.dob(even_dob),
		.wea(even_wea),
		.web(even_web),
		.rea(even_rea),
		.reb(even_reb),
		.clk(clk),
		.rst(rst)
	);

	f15_histo_mem_bank #(
		.ADDR_WIDTH(ADDR_WIDTH-1)
	) mem_odd (
		.addra(odd_addra),
		.addrb(odd_addrb),
		.dia(odd_dia),
		.dib(odd_dib),
		.doa(odd_doa),
		.dob(odd_dob),
		.wea(odd_wea),
		.web(odd_web),
		.rea(odd_rea),
		.reb(odd_reb),
		.clk(clk),
		.rst(rst)
	);

endmodule // f15_histo_mem