SignalTap抓取的波形
500KHz波形
1MHz波形
3MHz波形
基本原理:一个周期内有1024 个采样点,基本的时钟周期为50MHz;为使输出的波形频率发生变化,可以改变输出的间隔即每隔K个点输出一个采样数据,此时输出的波形频率与K之间的关系为:
代码块
VerilogHDL代码
module addr_cnt(
CLK, //时钟
sw_fq, //频率选择控制
Address, //输出间隔
ROMadd); //ROM表地址
input CLK;
input [1 : 0] sw_fq;
output reg [31 : 0] Address;
output reg [9 : 0] ROMadd;
reg [5 :0] K; //最大为60,五位二进制数的最大表示为63.
always @ (posedge CLK)
begin
case(sw_fq)
2'd00 : Address <= 10; //输出500KHz
2'd01 : Address <= 20; //输出1MHz
2'd10 : Address <= 60; //输出3MHz
default Address <= 10;
endcase
end
always @ (posedge CLK)
begin
ROMadd <= Address + ROMadd; //ROM表步进间隔输出
end
endmodule
生成ROM表的MatLab程序是使用杜大大的程序:
function generate_DDS_rom()
clc;
close all;
disp('# generate_DDS_rom() Running~');
%%///////////////////////////////////////////////////
% 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; %2^10=1024
index = (0:rom_vec_len-1) ; %0~1023
rom_data_vec_float = sin(2*pi*index/rom_vec_len); %最大值为1的1024点正弦波
figure; plot(rom_data_vec_float); % for debug
rom_data_vec_int = fix(rom_data_vec_float * (2^(rom_word_len-1) - 1)); %最大值为2047,为了保证最高位为符号位
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(strcmp(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()
用分析500k波形的MATLAB代码作为示例:
signal = transpose(VarName6) / 2048; %数据归一化处理
CLK = 50 * 1000000;
N = 512;
t=[0:1/CLK:(N-1)/CLK]; %持续时间
figure(1);plot(t,signal);
xlabel('时间(s)');ylabel('value');
title('时域图');%绘制时域图形
Y = fft(signal,N); %FFT变换
size = abs(Y); %取模
size=size/(N/2); %换算成实际的幅度
figure(2);
stem(F(1:N/2),size(1:N/2)); %fft频域图
axis([0 5E6 0 1.5]);
title('频谱图');
xlabel('频率(Hz)');ylabel('幅度');
将signal tap中的数据导入到MATLAB中分析的注意事项:
- 导出signal tap 中的数据有TXT和CSV两种文本格式,但是CSV的数据格式是带符号的二进制数据,用MATLAB分析需要先将其转换为十进制在分析。这个过程较为麻烦,TXT文本的数据是十进制可以用MATLAB的import data直接导入。
- 用TXT导入数据时,数据会被截断需要合并。
- 导入的数据要注意是文本格式还是Number。