/////////////////////////////////////////////////////////////////////////////        
//  dds_core.v           : DDS 电路实验参考代码                                         
//  author               : 杜伟韬                                                   
//  date                 : 2011-10-10                                               
/////////////////////////////////////////////////////////////////////////////        
//        中国传媒大学 广播电视数字化教育部工程研究中心（ECDAV）                    
//                     http://ecdav.cuc.edu.cn                                      
//  本设计用途                                                                      
//    1、 中国传媒大学 电子设计竞赛辅导培训教学参考设计                             
//    2、 数字工程中心 研究生电路设计课程教学参考设计                               
/////////////////////////////////////////////////////////////////////////////        
// 
//              实验作业：掌握DDS的原理，并且能够回答以下问题                                    
//
//   1、如何根据CLK频率和输入频率字来设定输出波形的频率                             
//   2、补码格式能够直接送给DAC么？为什么仿真工具里观察数据有多种选项，         
//      比如unsigned/hex/binary/signed decimal 等等                                 
//   3、如何自动生成波表ROM的verilog代码？                                          
//   4、如何调节ROM的地址空间容量和数据字长？调节这些参数有什么意义和代价？         
//   5、如何评价DDS输出波形的质量？                                                 
//
/////////////////////////////////////////////////////////////////////////////        
//              
//              中国传媒大学数字化工程中心 本科生创新实验项目
//
//  长期招募热爱电子设计的同学，欢迎本科生同学参与到数字化工程中心的科研项目       
//      
//      详情咨询：diansai@cuc.edu.cn 或 中国传媒大学综合楼6层 卢起斌老师            
//
/////////////////////////////////////////////////////////////////////////////        
module dds_core_sin(
  CLK   ,   // clock, posedge valid
  RST   ,   // reset, high level reset
  FWEN  ,   // frequency word update enable, high level enable
  FWIN  ,   // input frequency word
  CLKOUT,   // output clock
  SINOUT);  // sine signal output, 2's complement format

input           CLK;
input           RST;
input           FWEN;
input [32-1:0]  FWIN;
output[12-1:0]  SINOUT;
output          CLKOUT;

parameter FW_WL = 32;   // frequency word word length in bit
parameter RA_WL = 10;   // rom address word length in bit
parameter RD_WL = 12;   // rom data  word word length in bit

reg   [FW_WL -1:0]  fwin_R;     // freq word DFF
reg   [FW_WL -1:0]  acc_R;      // phase ACC DFF
reg   [RA_WL -1:0]  addr_R;     // rom address DFF
reg   [RD_WL -1:0]  sinout_R;   // sin wave output DFF
wire  [RD_WL -1:0]  romout_W;   // rom data output wire

always @ (posedge CLK or posedge RST) begin
  if(RST) begin
    fwin_R   <= 0;
    acc_R    <= 0;
    addr_R   <= 0;
    sinout_R <= 0;
  end
  else begin
    // update fwin_R DFF
    if(FWEN)
      fwin_R <= #1 FWIN;
    else
      fwin_R <= #1 fwin_R;
    
    // update acc_R
    acc_R <= #1 fwin_R + acc_R;
    // update addr_R, the acc_R high RA_WL is rom address
    addr_R <= acc_R[FW_WL-1:FW_WL-1-(RA_WL-1)];     

    // update output DFF
    sinout_R <= #1 romout_W;
  end
end

DDS_CORE_ROM u_sinrom(
  .CLK    (CLK      ),  // clock
  .RA     (addr_R   ),  // read address
  .RD     (romout_W )); // read data

assign SINOUT = sinout_R;
assign CLKOUT = CLK;

endmodule // module dds_core
