aboutsummaryrefslogblamecommitdiff
path: root/src/rtl/modexpa7_wrapper.v
blob: 3b749bee5e7c4b3b7e4b919a54eb0051a14cb555 (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;	// number of bits in modulus
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_EXPONENT_BITS	= 'h12;	// number of bits in exponent
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_BUFFER_BITS		= 'h13;	// largest supported number of bits
	localparam	[OPERAND_ADDR_WIDTH+1:0]	ADDR_ARRAY_BITS		= 'h15;	// number of bits in systolic array

	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]	BUFFER_BITS	= {1'b1, {OPERAND_ADDR_WIDTH+4{1'b0}}};
		 
		 // check_modulus_bits
	function	[OPERAND_ADDR_WIDTH+5:0]	check_modulus_bits;
		input	[OPERAND_ADDR_WIDTH+5:0]	num_bits;
		begin
			//
			//t = num_bits[]
			//if (num_bits > MAX_BITS)	write_check_bits = MAX_BITS;
			//else								write_check_bits = num_bits;
			//
		end
	endfunction

	function	[OPERAND_ADDR_WIDTH+5:0]	check_exponent_bits;
		input	[OPERAND_ADDR_WIDTH+5:0]	num_bits;
		begin
			
				// store input value
			check_exponent_bits = num_bits;
			
				// too large?
			if (num_bits > BUFFER_BITS)
				check_exponent_bits = BUFFER_BITS;
			
				// too small?
			if (num_bits == {OPERAND_ADDR_WIDTH+5{1'b0}})
				num_bits = {{OPERAND_ADDR_WIDTH+4{1'b0}}, 1'b1};
				
			//
		end
	endfunction


		/*
		 * Internal Quantities Generator
		 */

	function	[OPERAND_ADDR_WIDTH-1:0]	modulus_num_words_core;
		input	[OPERAND_ADDR_WIDTH+5:0]	num_bits;
		begin
		end
	endfunction

	function	[OPERAND_ADDR_WIDTH+4:0]	get_exponent_num_bits_core;
		input	[OPERAND_ADDR_WIDTH+5:0]	num_bits;
		reg	[OPERAND_ADDR_WIDTH+5:0]	num_bits_checked;
		begin
			
				// check number of bits (not too large, not too small)
			num_bits_checked = check_exponent_bits(num_bits);
			
				// de
		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		<= check_modulus_bits(write_data[OPERAND_ADDR_WIDTH+5:0]);
				ADDR_EXPONENT_BITS:	reg_exponent_bits		<= check_exponent_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 <= 
												get_modulus_num_words_core(write_data[OPERAND_ADDR_WIDTH+5:0]);
												
				ADDR_EXPONENT_BITS:	exponent_num_bits_core	<=
												get_exponent_num_bits_core(write_data[OPERAND_ADDR_WIDTH+5:0]);
				//
			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