aboutsummaryrefslogblamecommitdiff
path: root/src/rtl/modexpa7_wrapper.v
blob: 35be61ed1ddc94f1cfbd87f0c0839c2663cdea49 (plain) (tree)































































































































































































































































                                                                                                                                                
//======================================================================
//
// Copyright (c) 2016, 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 modexpa7_wrapper #
	(
		parameter OPERAND_ADDR_WIDTH		= 5,
		parameter SYSTOLIC_ARRAY_POWER	= 2
	)

	(
		input											clk,
		input											rst_n,

		input											cs,
		input											we,

		input		[OPERAND_ADDR_WIDTH+2:0]	address,
		input		[                32-1:0]	write_data,
		output	[                32-1:0]	read_data
	);


		/*
		 * Address Decoder
		 */
	localparam	ADDR_MSB_REGS	= 1'b0;
	localparam	ADDR_MSB_CORE	= 1'b1;
	
	wire										address_msb = address[OPERAND_ADDR_WIDTH+2];
	wire	[OPERAND_ADDR_WIDTH+1:0]	address_lsb = address[OPERAND_ADDR_WIDTH+1:0];


		/*
		 * Output Mux
		 */
	wire	[31: 0]	read_data_regs;
	wire	[31: 0]	read_data_core;


		/*
		 * Registers
		 */
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_NAME0				= 'h00;	//
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_NAME1				= 'h01;	//
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_VERSION			= 'h02;	//

	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_CONTROL			= 'h08;	// {next, init}
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_STATUS				= 'h09;	// {valid, ready}
//	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_MODE							// NOT USED ANYMORE
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_MODULUS_BITS		= 'h11;	//
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_EXPONENT_BITS	= 'h12;	//
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_OPERAND_BITS		= 'h13;	//

	localparam	CONTROL_INIT_BIT	= 0;
	localparam	CONTROL_NEXT_BIT	= 1;

	localparam	STATUS_READY_BIT	= 0;
	localparam	STATUS_VALID_BIT	= 1;

	localparam	CORE_NAME0			= 32'h6D6F6465;	// "mode"
	localparam	CORE_NAME1			= 32'h78706137;	// "xpa7"
	localparam	CORE_VERSION		= 32'h302E3230;	// "0.10"


		/*
		 * Registers
		 */
	reg	[                   1:0]	reg_control;
	reg	[OPERAND_ADDR_WIDTH+5:0]	reg_modulus_bits;
	reg	[OPERAND_ADDR_WIDTH+5:0]	reg_exponent_bits;


		/*
		 * Wires
		 */
	wire	[ 1:0]	reg_status;


		/*
		 * Internal Quantities
		 */		 
	reg	[OPERAND_ADDR_WIDTH-1:0]	modulus_num_words_core;
	reg	[OPERAND_ADDR_WIDTH+4:0]	exponent_num_bits_core;
 
		 

		/*
		 * ModExpA7
		 */
	modexpa7_top #
	(
		.OPERAND_ADDR_WIDTH		(OPERAND_ADDR_WIDTH),
		.SYSTOLIC_ARRAY_POWER	(SYSTOLIC_ARRAY_POWER)
	)
	modexpa7_core
	(
		.clk						(clk),
		.rst_n					(rst_n),

		.init						(reg_control[CONTROL_INIT_BIT]),
		.ready					(reg_status[STATUS_READY_BIT]),
		
		.next						(reg_control[CONTROL_NEXT_BIT]),
		.valid					(reg_status[STATUS_VALID_BIT]),

		.modulus_num_words	(modulus_num_words_core),
		.exponent_num_bits	(exponent_num_bits_core),

		.bus_cs					(cs && (address_msb == ADDR_MSB_CORE)),
		.bus_we					(we),
		.bus_addr				(address_lsb),
		.bus_data_wr			(write_data),
		.bus_data_rd			(read_data_core)
	);


		/*
		 * Read Latch
		 */
		 
	reg	[31: 0]	read_data_regs;
	
	
		/*
		 * Write Checker
		 */
		 
		 // largest supported operand width
	localparam	[OPERAND_ADDR_WIDTH+5:0]	MAX_BITS = {1'b1, {OPERAND_ADDR_WIDTH+4{1'b0}}};
		 
		 // limit operand width to max supported
	function	[OPERAND_ADDR_WIDTH+5:0]	write_check_bits;
		input	[OPERAND_ADDR_WIDTH+5:0]	num_bits;
		begin
			//
			if (num_bits > MAX_BITS)	write_check_bits = MAX_BITS;
			else								write_check_bits = num_bits;
			//
		end
	endfunction


		/*
		 * Write Interface (External Registers)
		 */
		 
	always @(posedge clk)
		//
		if (rst_n == 1'b0) begin
			//
			reg_control				<= {1'b0, 1'b0};
			reg_modulus_bits		<= 
			reg_exponent_bits		<= {1'b1, {OPERAND_ADDR_WIDTH+4{1'b0}}};
			//
		end else if (cs && (address_msb == ADDR_MSB_REGS) && we)
			//
			case (address_lsb)
				//
				ADDR_CONTROL:			reg_control				<= write_data[ 1: 0];
				ADDR_MODULUS_BITS:	reg_modulus_bits		<= write_check_bits(write_data[OPERAND_ADDR_WIDTH+5:0]);
				ADDR_EXPONENT_BITS:	reg_exponent_bits		<= write_check_bits(write_data[OPERAND_ADDR_WIDTH+5:0]);
				//
			endcase


		/*
		 * Write Interface (Internal Quantities)
		 */
		 
	always @(posedge clk)
		//
		if (cs && (address_msb == ADDR_MSB_REGS) && we)
			//
			case (address_lsb)
				//
				ADDR_MODULUS_BITS:	modulus_num_words_core	<= //modulus_num_words_int;
				ADDR_EXPONENT_BITS:	exponent_num_bits_core	<= //exponent_num_bits_int;
				//
			endcase


		/*
		 * Read Interface
		 */
		 
	always @(posedge clk)
		//
		if (cs && (address_msb == ADDR_MSB_REGS))
			//
			case (address_lsb)
				//
				ADDR_NAME0:				tmp_read_data <= CORE_NAME0;
				ADDR_NAME1:				tmp_read_data <= CORE_NAME1;
				ADDR_VERSION:			tmp_read_data <= CORE_VERSION;
				
				ADDR_CONTROL:			tmp_read_data <= {{30{1'b0}}, reg_control};
				ADDR_STATUS:			tmp_read_data <= {{30{1'b0}}, reg_status};
				
				ADDR_MODULUS_BITS:	tmp_read_data <= {{19{1'b0}}, reg_modulus_bits};
				ADDR_EXPONENT_BITS:	tmp_read_data <= {{19{1'b0}}, reg_exponent_bits};
				//
				default:					tmp_read_data <= {32{1'b0}};
				//
			endcase


		/*
		 * Register / Core Memory Selector
		 */
		 
		// delay the leftmost bit of address
	reg address_msb_dly;
	always @(posedge clk) address_msb_dly = address_msb;

		// output mux
	reg	[31: 0]	read_data_mux;
	assign read_data = read_data_mux;

	always @(*)
		//
		case (address_msb_last)
			ADDR_MSB_REGS:		read_data_mux = read_data_regs;
			ADDR_MSB_CORE:		read_data_mux = read_data_core;
		endcase


endmodule