作业3 DDS模块设计

作业要求

在FPGA上设计一个DDS模块,在DE0 开发板上运行,在FPGA芯片内部合成出数字波形即可。不用输出模拟信号,本模块满足以下条件

  • 使用板载晶振的50MHz时钟,合成以下频率的信号
  • 1、500KHz 正弦波信号。 2、1MHz 正弦波信号。 3、3MHz 正弦波信号。
  • 频率字字长32位,波表ROM尺寸为 10比特地址,1024个word
  • 波形格式为2补码格式,12比特量化
  • 每个CLK输出一个有效样点。
  • 输入信号为频率字和频率字输入使能信号
  • 使用板载的拨码开关(Switch)控制生成的波形信号的不同频率。

注意:波表ROM代码是用matlab或C打印生成的。不要手写

人工绘制的电路结构RTL设计图

这里写图片描述

Quartus扫描生成的电路RTL图

  • 顶层RTL图
    这里写图片描述
  • DDS_CORE_ROM RTL图
    这里写图片描述

SignalTap截图

  • 500KHz输出正弦波的样值波形截图
    这里写图片描述
  • 1MKHz输出正弦波的样值波形截图
    这里写图片描述
  • 3MKHz输出正弦波的样值波形截图
    这里写图片描述

设计代码

1. 生成波表ROM的MATLAB代码

function generate_DDS_rom()
clc;
close all;
disp('##########################################');
disp('# generate_DDS_rom() RUN');
disp('##########################################');

%%///
%   set your rom config here
rom_word_len = 12;  % rom data word length in bit
rom_addr_len = 10;  % rom address word length in bit
rom_file_name = 'DDS_CORE_ROM.v';  % rom file name
rom_file_dir  = './';  % rom file dir path
description   = 'DDS CORE ROM FILE' % rom description
%%///

rom_vec_len = 2^rom_addr_len;
index = [0:rom_vec_len-1] .';
rom_data_vec_float = sin(2*pi*index/rom_vec_len);
figure; plot(rom_data_vec_float);    % for debug
rom_data_vec_int = fix(rom_data_vec_float * (2^(rom_word_len-1) - 1));
figure; plot(rom_data_vec_int);    % for debug

rom_cfg.rom_word_len  = rom_word_len   ;
rom_cfg.rom_file_name = rom_file_name  ;
rom_cfg.rom_file_dir  = rom_file_dir   ;
rom_cfg.description   = description    ;
gen_rom_rtl(rom_cfg, rom_data_vec_int);


end % generate_DDS_rom()

% ///////////////////////////////////////////////////////////////////////////////
% gen_rom_rtl()
%   generate synthesizable rom  hdl code(need synthesizer support).
% ///////////////////////////////////////////////////////////////////////////////
% INPUT: 
%   data vector, must be integer value
%   rom word len
%   rom file dir string
%   rom file name string
% OUTPUT:
%   verilog format rom file, all data in 2's complement code format
function gen_rom_rtl(rom_cfg, data_vec);

  rom_word_len   = rom_cfg.rom_word_len  ;
  rom_file_name  = rom_cfg.rom_file_name ;
  rom_file_dir   = rom_cfg.rom_file_dir  ;

  description    = rom_cfg.description   ;
  data_vec_len = length(data_vec);
  addr_word_len  = ceil(log2(data_vec_len));

  % check input be integer value
  data_vec_fixed = fix(data_vec);
  diff_sum = sum(data_vec == data_vec_fixed);
  % all integer elements will cause the diff_sum be vector length 
  if(diff_sum < data_vec_len)
    fprintf(1,'# ERROR, gen_rom_rtl(), input data_vec must be integer value\n');
    return;
  end


  rom_file_dir_name = strcat(rom_file_dir, rom_file_name);

  data_vec_fixed_2c =  data_vec_fixed + (2^rom_word_len) .* (data_vec_fixed < 0);


  romNum        = 2^addr_word_len;
  data_str_cell  = cell(data_vec_len, 1);

  for(idx = 1:data_vec_len)
   data_str_cell{idx} = Dec2BinStr(data_vec_fixed_2c(idx), rom_word_len);
  end % for(idx = 1:data_vec_len)

  if(romNum > data_vec_len)
    for(idx = data_vec_len+1:romNum)
     data_str_cell{idx} = Dec2BinStr(0, rom_word_len); 
   end
  end

  fid_rom_file = fopen(rom_file_dir_name, 'w');
  if(fid_rom_file == -1)
    errMsg = strcat('ERROR, gen_rom_rtl(), create file',rom_file_dir_name, ',failed');
    fprintf(1, '%s\n', errMsg);
    return;
  end

  % rom data print 
  % get rom module name
  rom_name = rom_file_name;
  len_rom_file_name = length(rom_file_name);
  if(rom_name(len_rom_file_name-1:len_rom_file_name) == '.v')
    rom_name(len_rom_file_name-1:len_rom_file_name) = [];
  else
    fprintf(1,'#WARNINIG, gen_rom_rtl(), rom_file_name may error, check it!\n');
  end
  fprintf(fid_rom_file,  ...
  '// ************************************************************** //\n');
  fprintf(fid_rom_file,  ...
  '// FILE    : %s \n', rom_file_name);
  fprintf(fid_rom_file,  ...
  '// DSCP    : %s\n', description);
  fprintf(fid_rom_file,  ...
  '// ABOUT   : auto generated rom file by gen_rom_rtl.m\n');
  fprintf(fid_rom_file,  ...
  '// DATE    : %s \n',  datestr(now));
  fprintf(fid_rom_file,  ...
  '// ************************************************************** //\n');
  % generate the crom module
  fprintf(fid_rom_file, ...
  '// module %s()\n', rom_name);
  fprintf(fid_rom_file, ...
  'module %s(\n', rom_name);
  fprintf(fid_rom_file, ...
  '  CLK    ,           // clock\n');
  fprintf(fid_rom_file, ...
  '  RA     ,           // read address\n');
  fprintf(fid_rom_file, ...
  '  RD     );          // read data\n');

  fprintf(fid_rom_file, ...
  'input          CLK;\n');
  fprintf(fid_rom_file, ...
  'input  [%-2d :0] RA;\n', addr_word_len-1); 
  fprintf(fid_rom_file, ...
  'output [%-2d :0] RD;\n', rom_word_len-1);
  fprintf(fid_rom_file, ...
  'reg    [%-2d :0] RD;\n', rom_word_len-1);

  fprintf(fid_rom_file, ...
  'always @ (posedge CLK)\n'); 
  fprintf(fid_rom_file, ...
  '  case(RA)\n');

  for addr = 0:1:data_vec_len-1
    fprintf(fid_rom_file, ... 
  '     %-2d''d %-6d:RD = #1 %-2d''b %s; ', ...
      addr_word_len,addr, rom_word_len, data_str_cell{addr+1});
    fprintf(fid_rom_file, ... 
  '// %6d 0x%s \n', ...
      data_vec_fixed(addr+1), dec2hex(data_vec_fixed_2c(addr+1)));

  end
  fprintf(fid_rom_file, ...
  '  default : RD = #1 0;\n');
  fprintf(fid_rom_file, ...
  '  endcase\n');

  fprintf(fid_rom_file, ...
  'endmodule \n');
  fclose(fid_rom_file);
  fprintf(1,'# File: %s written\n', rom_file_dir_name);

end % function gen_rom_rtl() 
% ////////////////////////////////////////////////////////////////////
function str = Dec2BinStr(data, word_len)
  str = '';
  for(idx = word_len-1:-1:0)
    bit_val = bitand(1, bitshift(data, -idx));
    str = strcat(str, int2str(bit_val));
  end
end % function Dec2BinStr()

2. 波表ROM代码

module DDS_CORE_ROM(
  CLK    ,           // clock
  RA     ,           // read address
  RD     );          // read data
input          CLK;
input  [9  :0] RA;
output [11 :0] RD;
reg    [11 :0] RD;
always @ (posedge CLK)
  case(RA)
     10'd 0     :RD = #1 12'b 000000000000; //      0 0x0 
     10'd 1     :RD = #1 12'b 000000001100; //     12 0xC 
     10'd 2     :RD = #1 12'b 000000011001; //     25 0x19 
     10'd 3     :RD = #1 12'b 000000100101; //     37 0x25 
     10'd 4     :RD = #1 12'b 000000110010; //     50 0x32 
     10'd 5     :RD = #1 12'b 000000111110; //     62 0x3E 
     10'd 6     :RD = #1 12'b 000001001011; //     75 0x4B 
     10'd 7     :RD = #1 12'b 000001010111; //     87 0x57 
     10'd 8     :RD = #1 12'b 000001100100; //    100 0x64 
     10'd 9     :RD = #1 12'b 000001110000; //    112 0x70 
     10'd 10    :RD = #1 12'b 000001111101; //    125 0x7D 
     10'd 11    :RD = #1 12'b 000010001010; //    138 0x8A 
     10'd 12    :RD = #1 12'b 000010010110; //    150 0x96 
     10'd 13    :RD = #1 12'b 000010100011; //    163 0xA3 
     10'd 14    :RD = #1 12'b 000010101111; //    175 0xAF 
     10'd 15    :RD = #1 12'b 000010111100; //    188 0xBC 
     10'd 16    :RD = #1 12'b 000011001000; //    200 0xC8 
     10'd 17    :RD = #1 12'b 000011010101; //    213 0xD5 
     10'd 18    :RD = #1 12'b 000011100001; //    225 0xE1 
     10'd 19    :RD = #1 12'b 000011101110; //    238 0xEE 
     10'd 20    :RD = #1 12'b 000011111010; //    250 0xFA 
     10'd 21    :RD = #1 12'b 000100000111; //    263 0x107 
     10'd 22    :RD = #1 12'b 000100010011; //    275 0x113 
     10'd 23    :RD = #1 12'b 000100011111; //    287 0x11F 
     10'd 24    :RD = #1 12'b 000100101100; //    300 0x12C 
     10'd 25    :RD = #1 12'b 000100111000; //    312 0x138 
     10'd 26    :RD = #1 12'b 000101000101; //    325 0x145 
     10'd 27    :RD = #1 12'b 000101010001; //    337 0x151 
     10'd 28    :RD = #1 12'b 000101011101; //    349 0x15D 
     10'd 29    :RD = #1 12'b 000101101010; //    362 0x16A 
     10'd 30    :RD = #1 12'b 000101110110; //    374 0x176 
     10'd 31    :RD = #1 12'b 000110000011; //    387 0x183 
     10'd 32    :RD = #1 12'b 000110001111; //    399 0x18F 
     10'd 33    :RD = #1 12'b 000110011011; //    411 0x19B 
     10'd 34    :RD = #1 12'b 000110100111; //    423 0x1A7 
     10'd 35    :RD = #1 12'b 000110110100; //    436 0x1B4 
     10'd 36    :RD = #1 12'b 000111000000; //    448 0x1C0 
     10'd 37    :RD = #1 12'b 000111001100; //    460 0x1CC 
     10'd 38    :RD = #1 12'b 000111011000; //    472 0x1D8 
     10'd 39    :RD = #1 12'b 000111100101; //    485 0x1E5 
     10'd 40    :RD = #1 12'b 000111110001; //    497 0x1F1 
     10'd 41    :RD = #1 12'b 000111111101; //    509 0x1FD 
     10'd 42    :RD = #1 12'b 001000001001; //    521 0x209 
     10'd 43    :RD = #1 12'b 001000010101; //    533 0x215 
     10'd 44    :RD = #1 12'b 001000100001; //    545 0x221 
     10'd 45    :RD = #1 12'b 001000101110; //    558 0x22E 
     10'd 46    :RD = #1 12'b 001000111010; //    570 0x23A 
     10'd 47    :RD = #1 12'b 001001000110; //    582 0x246 
     10'd 48    :RD = #1 12'b 001001010010; //    594 0x252 
     10'd 49    :RD = #1 12'b 001001011110; //    606 0x25E 
     10'd 50    :RD = #1 12'b 001001101010; //    618 0x26A 
     10'd 51    :RD = #1 12'b 001001110110; //    630 0x276 
     10'd 52    :RD = #1 12'b 001010000010; //    642 0x282 
     10'd 53    :RD = #1 12'b 001010001110; //    654 0x28E 
     10'd 54    :RD = #1 12'b 001010011001; //    665 0x299 
     10'd 55    :RD = #1 12'b 001010100101; //    677 0x2A5 
     10'd 56    :RD = #1 12'b 001010110001; //    689 0x2B1 
     10'd 57    :RD = #1 12'b 001010111101; //    701 0x2BD 
     10'd 58    :RD = #1 12'b 001011001001; //    713 0x2C9 
     10'd 59    :RD = #1 12'b 001011010100; //    724 0x2D4 
     10'd 60    :RD = #1 12'b 001011100000; //    736 0x2E0 
     10'd 61    :RD = #1 12'b 001011101100; //    748 0x2EC 
     10'd 62    :RD = #1 12'b 001011111000; //    760 0x2F8 
     10'd 63    :RD = #1 12'b 001100000011; //    771 0x303 
     10'd 64    :RD = #1 12'b 001100001111; //    783 0x30F 
     10'd 65    :RD = #1 12'b 001100011010; //    794 0x31A 
     10'd 66    :RD = #1 12'b 001100100110; //    806 0x326 
     10'd 67    :RD = #1 12'b 001100110010; //    818 0x332 
     10'd 68    :RD = #1 12'b 001100111101; //    829 0x33D 
     10'd 69    :RD = #1 12'b 001101001000; //    840 0x348 
     10'd 70    :RD = #1 12'b 001101010100; //    852 0x354 
     10'd 71    :RD = #1 12'b 001101011111; //    863 0x35F 
     10'd 72    :RD = #1 12'b 001101101011; //    875 0x36B 
     10'd 73    :RD = #1 12'b 001101110110; //    886 0x376 
     10'd 74    :RD = #1 12'b 001110000001; //    897 0x381 
     10'd 75    :RD = #1 12'b 001110001101; //    909 0x38D 
     10'd 76    :RD = #1 12'b 001110011000; //    920 0x398 
     10'd 77    :RD = #1 12'b 001110100011; //    931 0x3A3 
     10'd 78    :RD = #1 12'b 001110101110; //    942 0x3AE 
     10'd 79    :RD = #1 12'b 001110111001; //    953 0x3B9 
     10'd 80    :RD = #1 12'b 001111000100; //    964 0x3C4 
     10'd 81    :RD = #1 12'b 001111010000; //    976 0x3D0 
     10'd 82    :RD = #1 12'b 001111011011; //    987 0x3DB 
     10'd 83    :RD = #1 12'b 001111100110; //    998 0x3E6 
     10'd 84    :RD = #1 12'b 001111110000; //   1008 0x3F0 
     10'd 85    :RD = #1 12'b 001111111011; //   1019 0x3FB 
     10'd 86    :RD = #1 12'b 010000000110; //   1030 0x406 
     10'd 87    :RD = #1 12'b 010000010001; //   1041 0x411 
     10'd 88    :RD = #1 12'b 010000011100; //   1052 0x41C 
     10'd 89    :RD = #1 12'b 010000100111; //   1063 0x427 
     10'd 90    :RD = #1 12'b 010000110001; //   1073 0x431 
     10'd 91    :RD = #1 12'b 010000111100; //   1084 0x43C 
     10'd 92    :RD = #1 12'b 010001000111; //   1095 0x447 
     10'd 93    :RD = #1 12'b 010001010001; //   1105 0x451 
     10'd 94    :RD = #1 12'b 010001011100; //   1116 0x45C 
     10'd 95    :RD = #1 12'b 010001100110; //   1126 0x466 
     10'd 96    :RD = #1 12'b 010001110001; //   1137 0x471 
     10'd 97    :RD = #1 12'b 010001111011; //   1147 0x47B 
     10'd 98    :RD = #1 12'b 010010000110; //   1158 0x486 
     10'd 99    :RD = #1 12'b 010010010000; //   1168 0x490 
     10'd 100   :RD = #1 12'b 010010011010; //   1178 0x49A 
     10'd 101   :RD = #1 12'b 010010100100; //   1188 0x4A4 
     10'd 102   :RD = #1 12'b 010010101111; //   1199 0x4AF 
     10'd 103   :RD = #1 12'b 010010111001; //   1209 0x4B9 
     10'd 104   :RD = #1 12'b 010011000011; //   1219 0x4C3 
     10'd 105   :RD = #1 12'b 010011001101; //   1229 0x4CD 
     10'd 106   :RD = #1 12'b 010011010111; //   1239 0x4D7 
     10'd 107   :RD = #1 12'b 010011100001; //   1249 0x4E1 
     10'd 108   :RD = #1 12'b 010011101011; //   1259 0x4EB 
     10'd 109   :RD = #1 12'b 010011110101; //   1269 0x4F5 
     10'd 110   :RD = #1 12'b 010011111111; //   1279 0x4FF 
     10'd 111   :RD = #1 12'b 010100001000; //   1288 0x508 
     10'd 112   :RD = #1 12'b 010100010010; //   1298 0x512 
     10'd 113   :RD = #1 12'b 010100011100; //   1308 0x51C 
     10'd 114   :RD = #1 12'b 010100100101; //   1317 0x525 
     10'd 115   :RD = #1 12'b 010100101111; //   1327 0x52F 
     10'd 116   :RD = #1 12'b 010100111001; //   1337 0x539 
     10'd 117   :RD = #1 12'b 010101000010; //   1346 0x542 
     10'd 118   :RD = #1 12'b 010101001011; //   1355 0x54B 
     10'd 119   :RD = #1 12'b 010101010101; //   1365 0x555 
     10'd 120   :RD = #1 12'b 010101011110; //   1374 0x55E 
     10'd 121   :RD = #1 12'b 010101100111; //   1383 0x567 
     10'd 122   :RD = #1 12'b 010101110001; //   1393 0x571 
     10'd 123   :RD = #1 12'b 010101111010; //   1402 0x57A 
     10'd 124   :RD = #1 12'b 010110000011; //   1411 0x583 
     10'd 125   :RD = #1 12'b 010110001100; //   1420 0x58C 
     10'd 126   :RD = #1 12'b 010110010101; //   1429 0x595 
     10'd 127   :RD = #1 12'b 010110011110; //   1438 0x59E 
     10'd 128   :RD = #1 12'b 010110100111; //   1447 0x5A7 
     10'd 129   :RD = #1 12'b 010110110000; //   1456 0x5B0 
     10'd 130   :RD = #1 12'b 010110111001; //   1465 0x5B9 
     10'd 131   :RD = #1 12'b 010111000001; //   1473 0x5C1 
     10'd 132   :RD = #1 12'b 010111001010; //   1482 0x5CA 
     10'd 133   :RD = #1 12'b 010111010011; //   1491 0x5D3 
     10'd 134   :RD = #1 12'b 010111011011; //   1499 0x5DB 
     10'd 135   :RD = #1 12'b 010111100100; //   1508 0x5E4 
     10'd 136   :RD = #1 12'b 010111101100; //   1516 0x5EC 
     10'd 137   :RD = #1 12'b 010111110101; //   1525 0x5F5 
     10'd 138   :RD = #1 12'b 010111111101; //   1533 0x5FD 
     10'd 139   :RD = #1 12'b 011000000101; //   1541 0x605 
     10'd 140   :RD = #1 12'b 011000001110; //   1550 0x60E 
     10'd 141   :RD = #1 12'b 011000010110; //   1558 0x616 
     10'd 142   :RD = #1 12'b 011000011110; //   1566 0x61E 
     10'd 143   :RD = #1 12'b 011000100110; //   1574 0x626 
     10'd 144   :RD = #1 12'b 011000101110; //   1582 0x62E 
     10'd 145   :RD = #1 12'b 011000110110; //   1590 0x636 
     10'd 146   :RD = #1 12'b 011000111110; //   1598 0x63E 
     10'd 147   :RD = #1 12'b 011001000101; //   1605 0x645 
     10'd 148   :RD = #1 12'b 011001001101; //   1613 0x64D 
     10'd 149   :RD = #1 12'b 011001010101; //   1621 0x655 
     10'd 150   :RD = #1 12'b 011001011101; //   1629 0x65D 
     10'd 151   :RD = #1 12'b 011001100100; //   1636 0x664 
     10'd 152   :RD = #1 12'b 011001101100; //   1644 0x66C 
     10'd 153   :RD = #1 12'b 011001110011; //   1651 0x673 
     10'd 154   :RD = #1 12'b 011001111011; //   1659 0x67B 
     10'd 155   :RD = #1 12'b 011010000010; //   1666 0x682 
     10'd 156   :RD = #1 12'b 011010001001; //   1673 0x689 
     10</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值