写在前面
本篇是对DDS和ADDA实验的补充,就不完全公开了
一、matlab程序
例:使用matlab的DDS ROM生成代码,生成7位输入,16位输出的rom
function generate_DDS_rom()
clc;
close all;
disp('##########################################');
disp('# generate_DDS_rom() RUN');
disp('##########################################');
%%///
% set your rom config here
rom_word_len = 16; % rom data word length in bit
rom_addr_len = 7; % 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()
其生成的Verilog为:
// ************************************************************** //
// FILE : DDS_CORE_ROM.v
// DSCP : DDS CORE ROM FILE
// ABOUT : auto generated rom file by gen_rom_rtl.m
// DATE : 23-Jul-2021 14:15:54
// ************************************************************** //
// module DDS_CORE_ROM()
module DDS_CORE_ROM(
CLK , // clock
RA , // read address
RD ); // read data
input CLK;
input [6 :0] RA;
output [15 :0] RD;
reg [15 :0] RD;
always @ (posedge CLK)
case(RA)
7 'd 0 :RD = #1 16'b 0000000000000000; // 0 0x0
7 'd 1 :RD = #1 16'b 0000011001000111; // 1607 0x647
7 'd 2 :RD = #1 16'b 0000110010001011; // 3211 0xC8B
7 'd 3 :RD = #1 16'b 0001001011000111; // 4807 0x12C7
7 'd 4 :RD = #1 16'b 0001100011111000; // 6392 0x18F8
7 'd 5 :RD = #1 16'b 0001111100011001; // 7961 0x1F19
7 'd 6 :RD = #1 16'b 0010010100100111; // 9511 0x2527
7 'd 7 :RD = #1 16'b 0010101100011110; // 11038 0x2B1E
7 'd 8 :RD = #1 16'b 0011000011111011; // 12539 0x30FB
7 'd 9 :RD = #1 16'b 0011011010111001; // 14009 0x36B9
7 'd 10 :RD = #1 16'b 0011110001010110; // 15446 0x3C56
7 'd 11 :RD = #1 16'b 0100000111001101; // 16845 0x41CD
7 'd 12 :RD = #1 16'b 0100011100011100; // 18204 0x471C
7 'd 13 :RD = #1 16'b 0100110000111111; // 19519 0x4C3F
7 'd 14 :RD = #1 16'b 0101000100110011; // 20787 0x5133
7 'd 15 :RD = #1 16'b 0101010111110100; // 22004 0x55F4
7 'd 16 :RD = #1 16'b 0101101010000001; // 23169 0x5A81
7 'd 17 :RD = #1 16'b 0101111011010110; // 24278 0x5ED6
7 'd 18 :RD = #1 16'b 0110001011110001; // 25329 0x62F1
7 'd 19 :RD = #1 16'b 0110011011001110; // 26318 0x66CE
7 'd 20 :RD = #1 16'b 0110101001101100; // 27244 0x6A6C
7 'd 21 :RD = #1 16'b 0110110111001001; // 28105 0x6DC9
7 'd 22 :RD = #1 16'b 0111000011100001; // 28897 0x70E1
7 'd 23 :RD = #1 16'b 0111001110110101; // 29621 0x73B5
7 'd 24 :RD = #1 16'b 0111011001000000; // 30272 0x7640
7 'd 25 :RD = #1 16'b 0111100010000011; // 30851 0x7883
7 'd 26 :RD = #1 16'b 0111101001111100; // 31356 0x7A7C
7 'd 27 :RD = #1 16'b 0111110000101001; // 31785 0x7C29
7 'd 28 :RD = #1 16'b 0111110110001001; // 32137 0x7D89
7 'd 29 :RD = #1 16'b 0111111010011100; // 32412 0x7E9C
7 'd 30 :RD = #1 16'b 0111111101100001; // 32609 0x7F61
7 'd 31 :RD = #1 16'b 0111111111010111; // 32727 0x7FD7
7 'd 32 :RD = #1 16'b 0111111111111111; // 32767 0x7FFF
7 'd 33 :RD = #1 16'b 0111111111010111; // 32727 0x7FD7
7 'd 34 :RD = #1 16'b 0111111101100001; // 32609 0x7F61
7 'd 35 :RD = #1 16'b 0111111010011100; // 32412 0x7E9C
7 'd 36 :RD = #1 16'b 0111110110001001; // 32137 0x7D89
7 'd 37 :RD = #1 16'b 0111110000101001; // 31785 0x7C29
7 'd 38 :RD = #1 16'b 0111101001111100; // 31356 0x7A7C
7 'd 39 :RD = #1 16'b 0111100010000011; // 30851 0x7883
7 'd 40 :RD = #1 16'b 0111011001000000; // 30272 0x7640
7 'd 41 :RD = #1 16'b 0111001110110101; // 29621 0x73B5
7 'd 42 :RD = #1 16'b 0111000011100001; // 28897 0x70E1
7 'd 43 :RD = #1 16'b 0110110111001001; // 28105 0x6DC9
7 'd 44 :RD = #1 16'b 0110101001101100; // 27244 0x6A6C
7 'd 45 :RD = #1 16'b 0110011011001110; // 26318 0x66CE
7 'd 46 :RD = #1 16'b 0110001011110001; // 25329 0x62F1
7 'd 47 :RD = #1 16'b 0101111011010110; // 24278 0x5ED6
7 'd 48 :RD = #1 16'b 0101101010000001; // 23169 0x5A81
7 'd 49 :RD = #1 16'b 0101010111110100; // 22004 0x55F4
7 'd 50 :RD = #1 16'b 0101000100110011; // 20787 0x5133
7 'd 51 :RD = #1 16'b 0100110000111111; // 19519 0x4C3F
7 'd 52 :RD = #1 16'b 0100011100011100; // 18204 0x471C
7 'd 53 :RD = #1 16'b 0100000111001101; // 16845 0x41CD
7 'd 54 :RD = #1 16'b 0011110001010110; // 15446 0x3C56
7 'd 55 :RD = #1 16'b 0011011010111001; // 14009 0x36B9
7 'd 56 :RD = #1 16'b 0011000011111011; // 12539 0x30FB
7 'd 57 :RD = #1 16'b 0010101100011110; // 11038 0x2B1E
7 'd 58 :RD = #1 16'b 0010010100100111; // 9511 0x2527
7 'd 59 :RD = #1 16'b 0001111100011001; // 7961 0x1F19
7 'd 60 :RD = #1 16'b 0001100011111000; // 6392 0x18F8
7 'd 61 :RD = #1 16'b 0001001011000111; // 4807 0x12C7
7 'd 62 :RD = #1 16'b 0000110010001011; // 3211 0xC8B
7 'd 63 :RD = #1 16'b 0000011001000111; // 1607 0x647
7 'd 64 :RD = #1 16'b 0000000000000000; // 0 0x0
7 'd 65 :RD = #1 16'b 1111100110111001; // -1607 0xF9B9
7 'd 66 :RD = #1 16'b 1111001101110101; // -3211 0xF375
7 'd 67 :RD = #1 16'b 1110110100111001; // -4807 0xED39
7 'd 68 :RD = #1 16'b 1110011100001000; // -6392 0xE708
7 'd 69 :RD = #1 16'b 1110000011100111; // -7961 0xE0E7
7 'd 70 :RD = #1 16'b 1101101011011001; // -9511 0xDAD9
7 'd 71 :RD = #1 16'b 1101010011100010; // -11038 0xD4E2
7 'd 72 :RD = #1 16'b 1100111100000101; // -12539 0xCF05
7 'd 73 :RD = #1 16'b 1100100101000111; // -14009 0xC947
7 'd 74 :RD = #1 16'b 1100001110101010; // -15446 0xC3AA
7 'd 75 :RD = #1 16'b 1011111000110011; // -16845 0xBE33
7 'd 76 :RD = #1 16'b 1011100011100100; // -18204 0xB8E4
7 'd 77 :RD = #1 16'b 1011001111000001; // -19519 0xB3C1
7 'd 78 :RD = #1 16'b 1010111011001101; // -20787 0xAECD
7 'd 79 :RD = #1 16'b 1010101000001100; // -22004 0xAA0C
7 'd 80 :RD = #1 16'b 1010010101111111; // -23169 0xA57F
7 'd 81 :RD = #1 16'b 1010000100101010; // -24278 0xA12A
7 'd 82 :RD = #1 16'b 1001110100001111; // -25329 0x9D0F
7 'd 83 :RD = #1 16'b 1001100100110010; // -26318 0x9932
7 'd 84 :RD = #1 16'b 1001010110010100; // -27244 0x9594
7 'd 85 :RD = #1 16'b 1001001000110111; // -28105 0x9237
7 'd 86 :RD = #1 16'b 1000111100011111; // -28897 0x8F1F
7 'd 87 :RD = #1 16'b 1000110001001011; // -29621 0x8C4B
7 'd 88 :RD = #1 16'b 1000100111000000; // -30272 0x89C0
7 'd 89 :RD = #1 16'b 1000011101111101; // -30851 0x877D
7 'd 90 :RD = #1 16'b 1000010110000100; // -31356 0x8584
7 'd 91 :RD = #1 16'b 1000001111010111; // -31785 0x83D7
7 'd 92 :RD = #1 16'b 1000001001110111; // -32137 0x8277
7 'd 93 :RD = #1 16'b 1000000101100100; // -32412 0x8164
7 'd 94 :RD = #1 16'b 1000000010011111; // -32609 0x809F
7 'd 95 :RD = #1 16'b 1000000000101001; // -32727 0x8029
7 'd 96 :RD = #1 16'b 1000000000000001; // -32767 0x8001
7 'd 97 :RD = #1 16'b 1000000000101001; // -32727 0x8029
7 'd 98 :RD = #1 16'b 1000000010011111; // -32609 0x809F
7 'd 99 :RD = #1 16'b 1000000101100100; // -32412 0x8164
7 'd 100 :RD = #1 16'b 1000001001110111; // -32137 0x8277
7 'd 101 :RD = #1 16'b 1000001111010111; // -31785 0x83D7
7 'd 102 :RD = #1 16'b 1000010110000100; // -31356 0x8584
7 'd 103 :RD = #1 16'b 1000011101111101; // -30851 0x877D
7 'd 104 :RD = #1 16'b 1000100111000000; // -30272 0x89C0
7 'd 105 :RD = #1 16'b 1000110001001011; // -29621 0x8C4B
7 'd 106 :RD = #1 16'b 1000111100011111; // -28897 0x8F1F
7 'd 107 :RD = #1 16'b 1001001000110111; // -28105 0x9237
7 'd 108 :RD = #1 16'b 1001010110010100; // -27244 0x9594
7 'd 109 :RD = #1 16'b 1001100100110010; // -26318 0x9932
7 'd 110 :RD = #1 16'b 1001110100001111; // -25329 0x9D0F
7 'd 111 :RD = #1 16'b 1010000100101010; // -24278 0xA12A
7 'd 112 :RD = #1 16'b 1010010101111111; // -23169 0xA57F
7 'd 113 :RD = #1 16'b 1010101000001100; // -22004 0xAA0C
7 'd 114 :RD = #1 16'b 1010111011001101; // -20787 0xAECD
7 'd 115 :RD = #1 16'b 1011001111000001; // -19519 0xB3C1
7 'd 116 :RD = #1 16'b 1011100011100100; // -18204 0xB8E4
7 'd 117 :RD = #1 16'b 1011111000110011; // -16845 0xBE33
7 'd 118 :RD = #1 16'b 1100001110101010; // -15446 0xC3AA
7 'd 119 :RD = #1 16'b 1100100101000111; // -14009 0xC947
7 'd 120 :RD = #1 16'b 1100111100000101; // -12539 0xCF05
7 'd 121 :RD = #1 16'b 1101010011100010; // -11038 0xD4E2
7 'd 122 :RD = #1 16'b 1101101011011001; // -9511 0xDAD9
7 'd 123 :RD = #1 16'b 1110000011100111; // -7961 0xE0E7
7 'd 124 :RD = #1 16'b 1110011100001000; // -6392 0xE708
7 'd 125 :RD = #1 16'b 1110110100111001; // -4807 0xED39
7 'd 126 :RD = #1 16'b 1111001101110101; // -3211 0xF375
7 'd 127 :RD = #1 16'b 1111100110111001; // -1607 0xF9B9
default : RD = #1 0;
endcase
endmodule
二、使用方法
按照所需要ROM的输入、输出位数,更改matlab代码中的rom_word_len和rom_addr_len这两个变量,然后运行即可。
(参考老师的程序,这玩意要是本人自己写,打死我也写不出来。)