OpenCores
URL https://opencores.org/ocsvn/common/common/trunk

Subversion Repositories common

[/] [common/] [trunk/] [LPM_gates.v] - Rev 48

Compare with Previous | Blame | View Log

//------------------------------------------------------------------------
//   This Verilog file was developed by Altera Corporation.  It may be
// freely copied and/or distributed at no cost.  Any persons using this
// file for any purpose do so at their own risk, and are responsible for
// the results of such use.  Altera Corporation does not guarantee that
// this file is complete, correct, or fit for any particular purpose.
// NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.  This notice must
// accompany any copy of this file.
//
//------------------------------------------------------------------------
// Imported to Opencores directory.   Date Sept 10, 2001
// Split related modules into separate files, as the manual splits them.
// Added example instantiations to the beginning of each file.
//
/* EXAMPLE INSTANTIATIONS:
 
lpm_constant
#( 1,                         // lpm_width
   0,                         // lpm_cvalue
   "UNUSED"                   // lpm_strength, optional, {UNUSED, WEAK}
 ) lpm_constant_example (
  .result                     (const_out[lpm_width-1:0])
);
 
lpm_inv
#( 1                          // lpm_width
 ) lpm_inv_example (
  .result                     (data_out[lpm_width-1:0]),
  .data                       (data_in[lpm_width-1:0])
);
 
// NOTE: Bits data[lpm_size-1:0] are ANDed together to make result[0]
lpm_and
#( 1,                         // lpm_width (output width)
   1                          // lpm_size (inputs to each gate)
 ) lpm_and_example (
  .result                     (data_out[lpm_width-1:0]),
  .data                       (data_in[(lpm_size*lpm_width)-1:0])
);
 
// NOTE: Bits data[lpm_size-1:0] are ORed together to make result[0]
lpm_or
#( 1,                         // lpm_width (output width)
   1                          // lpm_size (inputs to each gate)
 ) lpm_or_example (
  .result                     (data_out[lpm_width-1:0]),
  .data                       (data_in[(lpm_size*lpm_width)-1:0])
);
 
// NOTE: Bits data_[lpm_size-1:0] are XORed together to make result[0]
lpm_xor
#( 1,                         // lpm_width (output width)
   1                          // lpm_size (inputs to each gate)
 ) lpm_xor_example (
  .result                     (data_out[lpm_width-1:0]),
  .data                       (data_in[(lpm_size*lpm_width)-1:0])
);
 
lpm_bustri
#( 1                          // lpm_width
 ) lpm_bustri_example (
  .tridata                    (data_tristate[lpm_width-1:0]),
  .data                       (data_to_tristate[lpm_width-1:0]),    // CHOICE
  .enabledt                   (enable_data_to_tristate_bus_HIGH),   // OPTIONAL
  .result                     (data_from_tristate[lpm_width-1:0]),  // CHOICE
  .enabletr                   (enable_data_to_result_bus_HIGH),     // OPTIONAL
);
 
// NOTE: Bits data[lpm_size-1:0] are SELECTED to make result[0]
lpm_mux
#( 1,                         // lpm_width (output width)
   1,                         // lpm_size (inputs to each mux)
   1,                         // lpm_widths (number of bits in output select bus)
   0                          // lpm_pipeline, optional, {0, 1}
 ) lpm_mux_example (
  .result                     (data_out[lpm_width-1:0]),
  .data                       (data_in[(lpm_size*lpm_width)-1:0]),
  .sel                        (data_sel[lpm_widths-1:0]),
  .clock                      (clock_if_pipelined),              // OPTIONAL
  .clken                      (clock_enable_HIGH_if_pipelined),  // OPTIONAL
  .aclr                       (async_clear_if_pipelined)         // OPTIONAL
);
 
lpm_decode
#( 1,                         // lpm_width (number of bits in input to be decoded)
   1,                         // lpm_decodes (number of actual outputs decoded)
   0                          // lpm_pipeline, optional, {0, 1}
 ) lpm_decode_example (
  .eq                         (decodes_out[lpm_decodes-1:0]),
  .data                       (data_in[lpm_width:0]),
  .enable                     (force_all_outputs_LOW_when_LOW),  // OPTIONAL
  .clock                      (clock_if_pipelined),              // OPTIONAL
  .clken                      (clock_enable_HIGH_if_pipelined),  // OPTIONAL
  .aclr                       (async_clear_if_pipelined)         // OPTIONAL
);
 
lpm_clshift
#( 1,                         // lpm_width (width of input vector)
   1,                         // lpm_widthdist (width of shift distance port)
   "LOGICAL"                  // lpm_shifttype, optional, {LOGICAL, ROTATE, ARITHMETIC}
 ) lpm_clshift_example (
  .result                     (data_out[lpm_width-1:0]),
  .overflow                   (overflow_means_arith_bit_lost_or_result_became_0),  // OPTIONAL
  .underflow                  (underflow_means_result_became_0),  // OPTIONAL
  .data                       (data_in[lpm_width-1:0]),
  .direction                  (low_means_towards_LSB),  // OPTIONAL
  .distance                   (shift_distance[lpm_widthdist-1:0])
);
*/
 
//------------------------------------------------------------------------
// LPM Synthesizable Models
//------------------------------------------------------------------------
// Version 1.5 (lpm 220)      Date 12/17/99
//
// Modified LPM_ADD_SUB and LPM_MULT to accomodate LPM_WIDTH = 1.
//   Default values for LPM_WIDTH* are changed back to 1.
// Added LPM_HINT to LPM_DIVIDE.
// Rewritten LPM_FIFO_DC to output correctly.
// Modified LPM_FIFO to output 0s before first read, output correct
//   values after aclr and sclr, and output LPM_NUMWORDS mod
//   exp(2, LPM_WIDTHU) when FIFO is full.
//
//------------------------------------------------------------------------
// Version 1.4.1 (lpm 220)    Date 10/29/99
//
// Default values for LPM_WIDTH* of LPM_ADD_SUB and LPM_MULT are changed
//   from 1 to 2.
//
//------------------------------------------------------------------------
// Version 1.4 (lpm 220)      Date 10/18/99
//
// Default values for each optional inputs for ALL modules are added.
// Some LPM_PVALUE implementations were missing, and now implemented.
//
//------------------------------------------------------------------------
// Version 1.3 (lpm 220)      Date 06/23/99
//
// Corrected LPM_FIFO and LPM_FIFO_DC cout and empty/full flags.
// Implemented LPM_COUNTER cin/cout, and LPM_MODULUS is now working.
//
//------------------------------------------------------------------------
// Version 1.2 (lpm 220)      Date 06/16/99
//
// Added LPM_RAM_DP, LPM_RAM_DQ, LPM_IO, LPM_ROM, LPM_FIFO, LPM_FIFO_DC.
// Parameters and ports are added/discarded according to the spec.
//
//------------------------------------------------------------------------
// Version 1.1 (lpm 220)      Date 02/05/99
//
// Added LPM_DIVIDE module.
//
//------------------------------------------------------------------------
// Version 1.0                Date 07/09/97
//
//------------------------------------------------------------------------
// Excluded Functions:
//
//  LPM_FSM and LPM_TTABLE.
//
//------------------------------------------------------------------------
// Assumptions:
//
// 1. LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, and LPM_NUMWORDS,
//    LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE  default value is
//    string UNUSED.
//
//------------------------------------------------------------------------
// Verilog Language Issues:
//
// Two dimensional ports are not supported. Modules with two dimensional
// ports are implemented as one dimensional signal of (LPM_SIZE * LPM_WIDTH)
// bits wide.
//
//------------------------------------------------------------------------
// Synthesis Issues:
// 
// 1. LPM_COUNTER 
//
// Currently synthesis tools do not allow mixing of level and edge
// sensetive signals. To overcome that problem the "data" signal is
// removed from the clock always block of lpm_counter, however the
// synthesis result is accurate. For correct simulation add the "data"
// pin to the sensetivity list as follows:
//
//  always @(posedge clock or posedge aclr or posedge aset or 
//           posedge aload or data)
//------------------------------------------------------------------------
 
module lpm_constant ( result );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_cvalue = 0;
	parameter lpm_strength = "UNUSED";
	parameter lpm_type = "lpm_constant";
	parameter lpm_hint = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	output [lpm_width-1:0] result;
 
	assign result = lpm_cvalue;
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_constant") || (lpm_type !== "lpm_constant"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_constant
 
//------------------------------------------------------------------------
 
module lpm_inv ( result, data );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_type = "lpm_inv";
	parameter lpm_hint = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input  [lpm_width-1:0] data;
	output [lpm_width-1:0] result;
 
	reg    [lpm_width-1:0] result;
 
	always @(data)
	begin
		result = ~data;
	end
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_inv") || (lpm_type !== "lpm_inv"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_inv
 
//------------------------------------------------------------------------
 
module lpm_and ( result, data );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_size = 1;
	parameter lpm_type = "lpm_and";
	parameter lpm_hint = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input  [(lpm_size * lpm_width)-1:0] data;
	output [lpm_width-1:0] result;
 
	reg    [lpm_width-1:0] result;
	integer i, j, k;
 
	always @(data)
	begin
		for (i=0; i<lpm_width; i=i+1)
		begin
			result[i] = data[i];
			for (j=1; j<lpm_size; j=j+1)
			begin
				k = j * lpm_width + i;
				result[i] = result[i] & data[k];
			end
		end
	end
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_and") || (lpm_type !== "lpm_and"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_and
 
//------------------------------------------------------------------------
 
module lpm_or ( result, data );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_size = 1;
	parameter lpm_type = "lpm_or";
	parameter lpm_hint  = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input  [(lpm_size * lpm_width)-1:0] data;
	output [lpm_width-1:0] result;
 
	reg    [lpm_width-1:0] result;
	integer i, j, k;
 
	always @(data)
	begin
		for (i=0; i<lpm_width; i=i+1)
		begin
			result[i] = data[i];
			for (j=1; j<lpm_size; j=j+1)
			begin
				k = j * lpm_width + i;
				result[i] = result[i] | data[k];
			end
		end
	end
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_or") || (lpm_type !== "lpm_or"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_or
 
//------------------------------------------------------------------------
 
module lpm_xor ( result, data );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_size = 1;
	parameter lpm_type = "lpm_xor";
	parameter lpm_hint  = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input  [(lpm_size * lpm_width)-1:0] data;
	output [lpm_width-1:0] result;
 
	reg    [lpm_width-1:0] result;
	integer i, j, k;
 
	always @(data)
	begin
		for (i=0; i<lpm_width; i=i+1)
		begin
			result[i] = data[i];
			for (j=1; j<lpm_size; j=j+1)
			begin
				k = j * lpm_width + i;
				result[i] = result[i] ^ data[k];
			end
		end
	end
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_xor") || (lpm_type !== "lpm_xor"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_xor
 
//------------------------------------------------------------------------
 
module lpm_bustri ( result, tridata, data, enabledt, enabletr );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_type = "lpm_bustri";
	parameter lpm_hint = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input  [lpm_width-1:0] data;
	input  enabledt;
	input  enabletr;
	output [lpm_width-1:0] result;
	inout  [lpm_width-1:0] tridata;
 
	reg    [lpm_width-1:0] result;
	reg    [lpm_width-1:0] tmp_tridata;
 
	tri0  enabledt;
	tri0  enabletr;
	buf (i_enabledt, enabledt);
	buf (i_enabletr, enabletr);
 
	always @(data or tridata or i_enabletr or i_enabledt)
	begin
		if (i_enabledt == 0 && i_enabletr == 1)
		begin
			result = tridata;
			tmp_tridata = 'bz;
		end
		else if (i_enabledt == 1 && i_enabletr == 0)
		begin
			result = 'bz;
			tmp_tridata = data;
		end
		else if (i_enabledt == 1 && i_enabletr == 1)
		begin
			result = data;
			tmp_tridata = data;
		end
		else
		begin
			result = 'bz;
			tmp_tridata = 'bz;
		end
	end
 
	assign tridata = tmp_tridata;
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_bustri") || (lpm_type !== "lpm_bustri"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_bustri
 
//------------------------------------------------------------------------
 
module lpm_mux ( result, clock, clken, data, aclr, sel );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_size = 1;
	parameter lpm_widths = 1;
	parameter lpm_pipeline = 0;
	parameter lpm_type = "lpm_mux";
	parameter lpm_hint  = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input [(lpm_size * lpm_width)-1:0] data;
	input aclr;
	input clock;
	input clken;
	input [lpm_widths-1:0] sel;
	output [lpm_width-1:0] result;
 
	integer i, j, m, n;
	reg [lpm_width-1:0] tmp_result;
	reg [lpm_width-1:0] tmp_result2 [lpm_pipeline:0];
 
	tri0 aclr;
	tri0 clock;
	tri1 clken;
 
	buf (i_aclr, aclr);
	buf (i_clock, clock);
	buf (i_clken, clken);
 
	always @(data or sel)
	begin
		tmp_result = 0;
		for (m=0; m<lpm_width; m=m+1)
		begin
			n = sel * lpm_width + m;
			tmp_result[m] = data[n];
		end
	end
 
	always @(posedge i_clock or posedge i_aclr)
	begin
		if (i_aclr)
		begin
			for (i = 0; i <= lpm_pipeline; i = i + 1)
				tmp_result2[i] = 'b0;
		end
		else if (i_clken == 1)
		begin
			tmp_result2[lpm_pipeline] = tmp_result;
			for (j = 0; j < lpm_pipeline; j = j +1)
				tmp_result2[j] = tmp_result2[j+1];
		end
	end
 
	assign result = (lpm_pipeline > 0) ? tmp_result2[0] : tmp_result;
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_mux") || (lpm_type !== "lpm_mux"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_mux
 
//------------------------------------------------------------------------
 
module lpm_decode ( eq, data, enable, clock, clken, aclr );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_decodes = 1 << lpm_width;
	parameter lpm_pipeline = 0;
	parameter lpm_type = "lpm_decode";
	parameter lpm_hint = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input  [lpm_width-1:0] data;
	input  enable;
	input  clock;
	input  clken;
	input  aclr;
	output [lpm_decodes-1:0] eq;
 
	reg    [lpm_decodes-1:0] tmp_eq2 [lpm_pipeline:0];
	reg    [lpm_decodes-1:0] tmp_eq;
	integer i, j;
 
	tri0   clock;
	tri1   clken;
	tri0   aclr;
	tri1   enable;
 
	buf (i_clock, clock);
	buf (i_clken, clken);
	buf (i_aclr, aclr);
	buf (i_enable, enable);
 
 
	always @(data or i_enable)
	begin
		tmp_eq = 0;
		if (i_enable)
		begin
			if ((data < lpm_decodes))
			begin
				tmp_eq[data] = 1'b1;
			end
		else
			tmp_eq = 0;
		end
	end
 
	always @(posedge i_clock or posedge i_aclr)
	begin
		if (i_aclr)
		begin 
			for (i = 0; i <= lpm_pipeline; i = i + 1)
				tmp_eq2[i] = 'b0;
		end
		else if (clken == 1) 
		begin
			tmp_eq2[lpm_pipeline] = tmp_eq;
			for (j = 0; j < lpm_pipeline; j = j +1)
				tmp_eq2[j] = tmp_eq2[j+1];
		end
	end
 
	assign eq = (lpm_pipeline > 0) ? tmp_eq2[0] : tmp_eq;
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_decode") || (lpm_type !== "lpm_decode"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_decode
 
//------------------------------------------------------------------------
 
module lpm_clshift ( result, overflow, underflow, data, direction, distance );
 
// NOTE: Parameters must be declared in the same order as the Properties
//       are specified in the Cell Specification document.
	parameter lpm_width = 1;
	parameter lpm_widthdist = 1;
	parameter lpm_shifttype = "LOGICAL";
	parameter lpm_type = "lpm_clshift";
	parameter lpm_hint = "UNUSED";
	parameter lpm_source_version = "lpm 220 version 1.6";
 
	input  [lpm_width-1:0] data;
	input  [lpm_widthdist-1:0] distance;
	input  direction;
	output [lpm_width-1:0] result;
	output overflow;
	output underflow;
 
	reg    [lpm_width-1:0] ONES;
	reg    [lpm_width-1:0] result;
	reg    overflow, underflow;
	integer i;
 
	tri0  direction;
 
	buf (i_direction, direction);
 
//---------------------------------------------------------------//
	function [lpm_width+1:0] LogicShift;
		input [lpm_width-1:0] data;
		input [lpm_widthdist-1:0] dist;
		input direction;
		reg   [lpm_width-1:0] tmp_buf;
		reg   overflow, underflow;
 
		begin
			tmp_buf = data;
			overflow = 1'b0;
			underflow = 1'b0;
			if ((direction) && (dist > 0)) // shift right
			begin
				tmp_buf = data >> dist;
				if ((data != 0) && ((dist >= lpm_width) || (tmp_buf == 0)))
					underflow = 1'b1;
			end
			else if (dist > 0) // shift left
			begin
				tmp_buf = data << dist;
				if ((data != 0) && ((dist >= lpm_width)
					|| ((data >> (lpm_width-dist)) != 0)))
					overflow = 1'b1;
			end
			LogicShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
		end
	endfunction
 
//---------------------------------------------------------------//
	function [lpm_width+1:0] ArithShift;
		input [lpm_width-1:0] data;
		input [lpm_widthdist-1:0] dist;
		input direction;
		reg   [lpm_width-1:0] tmp_buf;
		reg   overflow, underflow;
 
		begin
			tmp_buf = data;
			overflow = 1'b0;
			underflow = 1'b0;
 
			if (direction && (dist > 0))   // shift right
			begin
				if (data[lpm_width-1] == 0) // positive number
				begin
					tmp_buf = data >> dist;
					if ((data != 0) && ((dist >= lpm_width) || (tmp_buf == 0)))
						underflow = 1'b1;
				end
				else // negative number
				begin
					tmp_buf = (data >> dist) | (ONES << (lpm_width - dist));
					if ((data != ONES) && ((dist >= lpm_width-1) || (tmp_buf == ONES)))
						underflow = 1'b1;
				end
			end
			else if (dist > 0) // shift left
			begin
				tmp_buf = data << dist;
				if (data[lpm_width-1] == 0) // positive number
				begin
					if ((data != 0) && ((dist >= lpm_width-1) 
					|| ((data >> (lpm_width-dist-1)) != 0)))
						overflow = 1'b1;
				end
				else // negative number
				begin
					if ((data != ONES) && ((dist >= lpm_width) 
					|| (((data >> (lpm_width-dist-1))|(ONES << (dist+1))) != ONES)))
						overflow = 1'b1;
				end
			end
			ArithShift = {overflow,underflow,tmp_buf[lpm_width-1:0]};
		end
	endfunction
 
//---------------------------------------------------------------//
	function [lpm_width-1:0] RotateShift;
		input [lpm_width-1:0] data;
		input [lpm_widthdist-1:0] dist;
		input direction;
		reg   [lpm_width-1:0] tmp_buf;
 
		begin
			tmp_buf = data;
			if ((direction) && (dist > 0)) // shift right
			begin
				tmp_buf = (data >> dist) | (data << (lpm_width - dist));
			end
			else if (dist > 0) // shift left
			begin
				tmp_buf = (data << dist) | (data >> (lpm_width - dist));
			end
			RotateShift = tmp_buf[lpm_width-1:0];
		end
	endfunction
//---------------------------------------------------------------//
 
	initial
	begin
		for (i=0; i < lpm_width; i=i+1)
			ONES[i] = 1'b1;
	end
 
	always @(data or i_direction or distance)
	begin
		// lpm_shifttype is optional and default to LOGICAL
		if ((lpm_shifttype == "LOGICAL"))
		begin
			{overflow,underflow,result} = LogicShift(data,distance,i_direction);
		end
		else if (lpm_shifttype == "ARITHMETIC")
		begin
			{overflow,underflow,result} = ArithShift(data,distance,i_direction);
		end
		else if (lpm_shifttype == "ROTATE")
		begin
			result = RotateShift(data, distance, i_direction);
			overflow = 1'b0;
			underflow = 1'b0;
		end
		else
		begin
			result = 'bx;
			overflow = 1'b0;
			underflow = 1'b0;
		end
	end
 
// Check for previous Parameter declaration order
initial if ((lpm_width === "lpm_clshift") || (lpm_type !== "lpm_clshift"))
  begin
    $display ("LPM 220 Version 1.6 Parameter Order changed; update instantiation");
    $finish;
  end
endmodule // lpm_clshift
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.