关于DDS的正弦波ROM裁剪问题 质疑著 在这里感谢电子森林的苏老师对上一篇博客提出的质疑
[TOC]
问题是这样的 在上一篇博客中我曾经写到:
$\frac18$是在一个别人写的专利交底书的里面看到的,当时心理想了想觉得是可以的,没有实际地操作过
然后我把博客分享到朋友圈后收到了电子森林苏老师的一些质疑,其中一个便是这个应该是$\frac14$还是$\frac18$的问题,当时年少轻狂的我说着应该是$\frac18$,结果吃完饭想着实验一下,便发现,这错的离谱了。。。史称秒打脸,故作此篇实地操作一下这个$\frac14$的ROM表压缩,也算是对自己的一个小警示..
MATLAB生成1/4的ROM表 这里本来应该是8192个点的,因为我中途意识到自己的错误的时候,为了偷懒不重新配置ROM,所以就把这里改成了4096个点,其他的唯一改动就在于在文件写入操作的时候只写了前$\frac14$个点,和修复了以前mif文件没有自动加END;结尾的BUG.
这并不是很重要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 depth = 4096 ; width = 14 ; x = 0 : 2 *pi /(depth-1 ) :2 *pi ; y = sin (x); y=(y+1 )/2 *16383 /16384 ; disp (y);y_qua = round (y*2 ^width); fid = fopen('/home/heweibao/project_matlab/fpga_dds/sindiv8.mif' ,'wt' ); fprintf(fid,'WIDTH=%d;\n' ,width); fprintf(fid,'DEPTH=%d;\n' ,depth/4 ); fprintf(fid,'ADDRESS_RADIX=UNS;\n' ); fprintf(fid,'DATA_RADIX=UNS;\n' ); fprintf(fid,'CONTENT BEGIN\n' ); for num=0 : (depth-1 )/4 fprintf(fid,'%d:%14.0f;\n' ,num,y_qua(num+1 )); end fprintf(fid,'END;' ); fclose(fid); plot (x,y_qua);
FPGA状态机控制地址和加减 这里直接上图看一个周期: 至于为什么是这样,大家可以从导数的角度自己理解一下,所以写出来的状态机是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 module fsm_control( input clk,rst_n, output reg oper_add_sub, output reg [9 :0 ] phase_address ); parameter s0 = 2'b00 , s1 = 2'b01 , s2 = 2'b10 , s3 = 2'b11 ; reg [2 :0 ] now_state;always @(posedge clk or negedge rst_n)begin if (!rst_n) begin now_state <= s0; phase_address <= 10'd0 ; oper_add_sub <= 1'b0 ; end else case (now_state) s0:begin phase_address <= phase_address + 1'b1 ; oper_add_sub <= 1'b0 ; if (phase_address == 10'd1023 ) begin phase_address <= 10'd1023 ; now_state <= s1; end else now_state <= s0; end s1:begin phase_address <= phase_address - 1'b1 ; oper_add_sub <= 1'b1 ; if (phase_address == 10'd0 ) begin phase_address <= 10'd0 ; now_state <= s2; end else now_state <= s1; end s2:begin phase_address <= phase_address + 1'b1 ; oper_add_sub <= 1'b1 ; if (phase_address == 10'd1023 ) begin phase_address <= 10'd1023 ; now_state <= s3; end else now_state <= s2; end s3:begin phase_address <= phase_address - 1'b1 ; oper_add_sub <= 1'b0 ; if (phase_address == 10'd0 ) begin phase_address <= 10'd0 ; now_state <= s0; end else now_state <= s3; end endcase end endmodule
ROM操作端 这里要考虑就是我的数据是没有符号位的,所以取加减的时候需要求出变化量的绝对值,而且变化量要防止因为状态切换而突然变大导致波形失真,要做一个阈值判断.最后就是初始值给最大值的一半.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 module data_process( input clk,rst_n, input oper_add_sub, input [9 :0 ] phase_address, output wire [13 :0 ] data_out ); wire [13 :0 ] rom_data_out;rom_sin_8 rom_sin_8_inst ( .address ( phase_address ), .clock ( clk ), .q ( rom_data_out ) ); reg [13 :0 ] data_shift ,data_shift_pre;always @(posedge clk or negedge rst_n)begin if (!rst_n) begin data_shift <= 14'd0 ; data_shift_pre <= 14'd0 ; end else begin data_shift <= data_shift_pre; data_shift_pre <= rom_data_out; end end wire [13 :0 ] delta_data;assign delta_data_pre = data_shift<data_shift_pre ? (data_shift_pre - data_shift) : (data_shift-data_shift_pre); reg [13 :0 ] out_data;always @(posedge clk or negedge rst_n)begin if (!rst_n) out_data <= 14'd8192 ; else out_data <= oper_add_sub ? (out_data-delta_data) :(out_data+delta_data); end assign data_out = out_data;endmodule
仿真结果
结语 这次确实是年少轻狂,没认真思考惹的问题. 不过错了就应该大大方方承认嘛.
自省年少显轻狂,俯首道歉表心怀
再一次谢谢电子森林苏老师的质疑.
如果你觉得有丶收获的话