head 1.1; access; symbols; locks; strict; comment @# @; 1.1 date 2001.09.20.10.07.35; author bbeaver; state Exp; branches; next ; desc @@ 1.1 log @adding beginning LPM files @ text @//------------------------------------------------------------------------ // 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 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 @