//======================================================================
//
// core_selector.v
// ---------------
// Core selector Cryptech Novena FPGA framework.
//
//
// Author: Pavel Shatov
// Copyright (c) 2014, NORDUnet A/S All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// - Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// - Neither the name of the NORDUnet nor the names of its contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//======================================================================
module core_selector
(
input wire sys_clk,
input wire sys_rst,
input wire [13: 0] sys_eim_addr,
input wire sys_eim_wr,
input wire sys_eim_rd,
output wire [31 : 0] read_data,
input wire [31 : 0] write_data
);
//
// Internal Registers
//
reg [31: 0] reg_x = {32{1'b0}};
reg [31: 0] reg_y = {32{1'b0}};
reg [15: 0] reg_ctl = {16{1'b0}};
reg [31: 0] read_data_reg = {32{1'b0}};
//
// Parameters
//
localparam ADDER_BASE_ADDR = 12'h321; // upper 12 bits of address
localparam ADDER_OFFSET_REG_X = 2'd0; // X
localparam ADDER_OFFSET_REG_Y = 2'd1; // Y
localparam ADDER_OFFSET_REG_Z = 2'd2; // Z
localparam ADDER_OFFSET_REG_SC = 2'd3; // {STATUS, CONTROL}
/* This flag detects whether adder core is being addressed. */
wire eim_access_adder = (sys_eim_addr[13:2] == ADDER_BASE_ADDR) ? 1'b1 : 1'b0;
/* These flags detect whether write or read access is requested. */
wire eim_access_write = sys_eim_wr & eim_access_adder;
wire eim_access_read = sys_eim_rd & eim_access_adder;
//
// Write Request Handler
//
always @(posedge sys_clk)
//
if (sys_rst) begin
reg_x <= {32{1'b0}};
reg_y <= {32{1'b0}};
reg_ctl <= {16{1'b0}};
end else if (eim_access_write) begin
//
case (sys_eim_addr[1:0])
ADDER_OFFSET_REG_X: reg_x <= write_data;
ADDER_OFFSET_REG_Y: reg_y <= write_data;
ADDER_OFFSET_REG_SC: reg_ctl <= write_data[15 : 0];
endcase
//
end
//
// Read Request Handler
//
wire [31: 0] reg_z;
wire [15: 0] reg_sts;
always @(posedge sys_clk)
//
if (sys_rst) read_data_reg <= {32{1'b0}};
//
else if (eim_access_read) begin
//
case (sys_eim_addr[1:0])
ADDER_OFFSET_REG_X: read_data_reg <= reg_x;
ADDER_OFFSET_REG_Y: read_data_reg <= reg_y;
ADDER_OFFSET_REG_Z: read_data_reg <= reg_z;
ADDER_OFFSET_REG_SC: read_data_reg <= {reg_sts, reg_ctl};
endcase
//
end
assign read_data = read_data_reg;
//
// Demo Adder Core
//
demo_adder adder_core
(
.clk (sys_clk),
.rst (sys_rst),
.x (reg_x),
.y (reg_y),
.z (reg_z),
.ctl (reg_ctl),
.sts (reg_sts)
);
endmodule
//======================================================================
// EOF core_selector.v
//======================================================================