⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 carrier_nco.v

📁 通信电路中产生载波的电路
💻 V
字号:
//                              -*- Mode: Verilog -*-
// Filename        : carrier_nco.v
// Description     : Generates the 8 stage carrier local oscilator.

// Author          : Peter Mumford, UNSW, 2005

/*
                  Numerically Controlled Oscillator (NCO) which replicates the
                 carrier frequency. This pseudo-sinusoid waveform consists of
                 8 stages or phases.

                 The NCO frequency is:
                
                    f = fControl * Clk / 2^N
                 where:
                 f = the required carrier wave frequency
                 Clk = the system clock (= 40MHz)
                 N = 30 (bit width of the phase accumulator)
                 fControl = the 30 bit (unsigned) control word 
 
                 The generated waveforms for I & Q look like:
                 Phase   :  0  1  2  3  4  5  6  7
                 ---------------------------------
                        I: -1 +1 +2 +2 +1 -1 -2 -2
                        Q: +2 +2 +1 -1 -2 -2 -1 +1

                 The nominal center frequency for the GP2015 is:
                 IF = 1.405396825MHz
                 Clk = 40 MHz
                 fControl = 2^N * IF / Clk
                 fControl = 0x23FA689 for center frequency

                 Resolution:
                 fControl increment value = 0.037252902 Hz
                 Put another way:
                 37mHz is the smallest change in carrier frequency possible
                 with this NCO.
 
                 The carrier phase and carrier cycle count are latched into
                 the carrier_val on the tic_enable. The carrier phase is the
                 10 msb of the accumulator register (accum_reg). The cycle count
                 is the number of full carrier wave cycles between the last 2
                 tic_enables. The two values are combined into the carrier_val.
                 Bits 9:0 are the carrier phase, bits 31:10 are the cycle count.
 */
/*
	Copyright (C) 2007  Peter Mumford

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

module carrier_nco (clk, rstn, tic_enable, f_control, carrier_val, i_sign, i_mag, q_sign, q_mag);

   input clk, rstn, tic_enable;
   input [28:0] f_control;
   output reg [31:0] carrier_val;
   output reg i_sign, i_mag; // in-phase (cosine) carrier wave
   output reg q_sign, q_mag; // quadrature (sine) carrier wave

   reg [29:0] accum_reg;
   reg [21:0] cycle_count_reg;
   
   wire [3:0] phase_key;
   wire [30:0] accum_sum;
   wire	accum_carry;
   wire [31:0] combined_carr_value;
   
   
   // 30 bit phase accumulator
   always @ (posedge clk)
   begin
	 if (!rstn) accum_reg <= 0;
	 else accum_reg <= accum_sum[29:0];
   end

   assign accum_sum = accum_reg + f_control;
   assign accum_carry = accum_sum[30];
   assign phase_key = accum_sum[29:26];
   
   assign combined_carr_value[9:0] = accum_reg[29:20];
   assign combined_carr_value[31:10] = cycle_count_reg;
   
   // cycle counter and value latching
   always @ (posedge clk)
   begin
	 if (!rstn) cycle_count_reg <= 0;
	 else if (tic_enable)
      begin
	    carrier_val = combined_carr_value; // latch in carrier value, then...
      cycle_count_reg = 0; // reset counter
	    end
	 else if (accum_carry)
      cycle_count_reg <= cycle_count_reg + 1;
   end

   // look up table for carrier pseudo-sinewave generation
   always @ (phase_key)
     // ?? is there a way to have or'ed values in case statements ??
     case (phase_key)
       // 0  0 degrees
       15 : begin
         i_sign <= 0;
         i_mag <= 0;
         q_sign <= 1;
         q_mag <= 1;
       end
       0 : begin
         i_sign <= 0;
         i_mag <= 0;
         q_sign <= 1;
         q_mag <= 1;
       end
       
       // 1  45 degrees
       1 : begin
	       i_sign <= 1;
	       i_mag <= 0;
	       q_sign <= 1;
	       q_mag <= 1;
       end
       2 : begin
	       i_sign <= 1;
	       i_mag <= 0;
	       q_sign <= 1;
	       q_mag <= 1;
       end
       
       // 2  90 degrees
       3 : begin
	       i_sign <= 1;
	       i_mag <= 1;
	       q_sign <= 1;
	       q_mag <= 0;
       end
       4 : begin
	       i_sign <= 1;
	       i_mag <= 1;
	       q_sign <= 1;
	       q_mag <= 0;
       end
       
       // 3 135 degrees
       5 : begin
	       i_sign <= 1;
	       i_mag <= 1;
	       q_sign <= 0;
	       q_mag <= 0;
       end
       6 : begin
	       i_sign <= 1;
	       i_mag <= 1;
	       q_sign <= 0;
	       q_mag <= 0;
       end
       
       // 4  180 degrees
       7 : begin
	       i_sign <= 1;
	       i_mag <= 0;
	       q_sign <= 0;
	       q_mag <= 1;
       end
       8 : begin
	       i_sign <= 1;
	       i_mag <= 0;
	       q_sign <= 0;
	       q_mag <= 1;
       end
       
       // 5  225 degrees
       9 : begin
	       i_sign <= 0;
	       i_mag <= 0;
	       q_sign <= 0;
	       q_mag <= 1;
       end
       10 : begin
	        i_sign <= 0;
	        i_mag <= 0;
	        q_sign <= 0;
	        q_mag <= 1;
       end
       
       // 6  270 degrees
       11 : begin
	        i_sign <= 0;
	        i_mag <= 1;
	        q_sign <= 0;
	        q_mag <= 0;
       end
       12 : begin
	        i_sign <= 0;
	        i_mag <= 1;
	        q_sign <= 0;
	        q_mag <= 0;
       end
       
       // 7  315 degrees
       13 : begin
	        i_sign <= 0;
	        i_mag <= 1;
	        q_sign <= 1;
	        q_mag <= 0;
       end
       14 : begin
	        i_sign <= 0;
	        i_mag <= 1;
	        q_sign <= 1;
	        q_mag <= 0;
       end
     endcase // case(phase_key)
endmodule // carrier_nco

	  
       
       
       

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -