【FPGA】Robei EDA的使用(5)——DDS的发生

Liana ·
更新时间:2024-11-13
· 978 次阅读

#今天也是咸鱼的一天~(换口头禅了)

DDS全称直接数字频率合成(Direct Digital Synthesis),系统结构可分为这几个部分,其中相位控制字可调整输出正弦波的相位,频率控制字可以调整输出正弦波的频率。
在这里插入图片描述
BUT,我在这里必须吐槽一下,Robei比赛的骚操作(别打我),比赛不允许我们使用除了RISC-V 以外的IP核,如果这个在后面真的不做任何改动的话,这就意味着,我没法使用像DDS,PLL,SPI,ROM,RAM,EEPROM,FIFO的IP核(菜鸡流泪),我可能得全部自己手写,手写各种通信协议和常用IP核。因此,这次介绍的是这样一个常用IP核,DDS。(vivado是有dds的IP,quartus好像是没有的)
在这里插入图片描述
DDS是一个在很多地方都有很大的用处的硬件,能够产生多种波形,包括现在的信号源,大多也是用FPGA做的,因为Robei没法使用这些IP核,所以就用源代码写一个。
参考是是这两份博客:

DDS的FPGA实现 DDS原理及FPGA实现
————————————————毫无感情的分割线———————————————— 方波发生

参考的资料是这个:
在这里插入图片描述
Robei 模块图:
在这里插入图片描述
绿色的模块是一个16进制的计数器,另两个蓝色的模块,是对计数器的数据进行处理,实现方波的过程。

计数器

在这里插入图片描述
Code:

// let's create a 16 bits free-running binary counter always @(posedge clk or negedge rst) if(!rst) cnt <= 16'h0; else if(cnt == 16'hff) cnt <= 16'h0; else cnt <= cnt + 16'h1; // and use it to generate the DAC signal output 取位数

在这里插入图片描述

assign cnt_tap = cnt[7]; // we take one bit out of the counter (here bit 7 = the 8th bit) 累乘

在这里插入图片描述

assign DAC_data = {10{cnt_tap}}; // and we duplicate it 10 times to create the 10-bits DAC value 三角波

在这里插入图片描述
code:

assign tri_data = cnt_tap [10] ? ~cnt_tap [9:0] : cnt_tap [9:0]; 锯齿波

在这里插入图片描述

assign saw_data = cnt_tap[9:0]; testbech

在这里插入图片描述

initial begin clk = 0; rst = 0; #5 rst = 1; #5 clk = 1; #150000 rst = 0; #5 $finish; end always begin #5 clk =~clk; end 信号波形

在这里插入图片描述

——————菜鸡冷漠的分割线————————

前几个都是很简单的代码,利用计数器就可以实现,这是因为像方波、三角波、锯齿波这类波形,都有很“线性”的关系。方波是边沿陡峭,其它平稳;锯齿波是一个线性上升,再边沿陡峭;三角波是线性上升,线性下降。这些关系都比较容易模拟,但是对于正弦波这样的信号波形,它的函数是sin,这样子在数字量输出上,就比较惨了~

在Quartus的编程里,有Rom可以存储波形数据,直接输出就行,非常方便;更是直接有现成的IP Core 可以调用DDS。但是Robei既没有ROM,也没有IP,所以只能手写数据来输出正弦波。

模块配置 分频counter

在这里插入图片描述
Code:

reg [10:0] num; always@(posedge clk or negedge rst) begin if(!rst) begin num <= 11'd0; clk_1 =1280) //这个是对系统时钟分频,根据想得到正弦波的频率,算这里取多少 begin clk_1<=~clk_1; num <=11'd0; end else num <=num+11'b1; end

这个计数器就是一个简易的分频器,当然,如果有条件,直接用pll 多简单。

波形数据

在这里插入图片描述
Code:

reg [7:0] addr ; always@(posedge clk_1 or negedge rst) begin if(!rst) addr <= 8'd0; else begin addr<=addr+1; case(addr) 8'd0:out=8'h80; 8'd1:out=8'h83; 8'd2:out=8'h86; 8'd3:out=8'h89; 8'd4:out=8'h8d; 8'd5:out=8'h90; 8'd6:out=8'h93; 8'd7:out=8'h96; 8'd8:out=8'h99; 8'd9:out=8'h9c; 8'd10:out=8'h9f; 8'd11:out=8'ha2; 8'd12:out=8'ha5; 8'd13:out=8'ha8; 8'd14:out=8'hab; 8'd15:out=8'hae; 8'd16:out=8'hb1; 8'd17:out=8'hb4; 8'd18:out=8'hb7; 8'd19:out=8'hba; 8'd20:out=8'hbc; 8'd21:out=8'hbf; 8'd22:out=8'hc2; 8'd23:out=8'hc5; 8'd24:out=8'hc7; 8'd25:out=8'hca; 8'd26:out=8'hcc; 8'd27:out=8'hcf; 8'd28:out=8'hd1; 8'd29:out=8'hd4; 8'd30:out=8'hd6; 8'd31:out=8'hd8; 8'd32:out=8'hda; 8'd33:out=8'hdd; 8'd34:out=8'hdf; 8'd35:out=8'he1; 8'd36:out=8'he3; 8'd37:out=8'he5; 8'd38:out=8'he7; 8'd39:out=8'he9; 8'd40:out=8'hea; 8'd41:out=8'hec; 8'd42:out=8'hee; 8'd43:out=8'hef; 8'd44:out=8'hf1; 8'd45:out=8'hf2; 8'd46:out=8'hf4; 8'd47:out=8'hf5; 8'd48:out=8'hf6; 8'd49:out=8'hf7; 8'd50:out=8'hf8; 8'd51:out=8'hf9; 8'd52:out=8'hfa; 8'd53:out=8'hfb; 8'd54:out=8'hfc; 8'd55:out=8'hfd; 8'd56:out=8'hfd; 8'd57:out=8'hfe; 8'd58:out=8'hff; 8'd59:out=8'hff; 8'd60:out=8'hff; 8'd61:out=8'hff; 8'd62:out=8'hff; 8'd63:out=8'hff; 8'd64:out=8'hff; 8'd65:out=8'hff; 8'd66:out=8'hff; 8'd67:out=8'hff; 8'd68:out=8'hff; 8'd69:out=8'hff; 8'd70:out=8'hfe; 8'd71:out=8'hfd; 8'd72:out=8'hfd; 8'd73:out=8'hfc; 8'd74:out=8'hfb; 8'd75:out=8'hfa; 8'd76:out=8'hf9; 8'd77:out=8'hf8; 8'd78:out=8'hf7; 8'd79:out=8'hf6; 8'd80:out=8'hf5; 8'd81:out=8'hf4; 8'd82:out=8'hf2; 8'd83:out=8'hf1; 8'd84:out=8'hef; 8'd85:out=8'hee; 8'd86:out=8'hec; 8'd87:out=8'hea; 8'd88:out=8'he9; 8'd89:out=8'he7; 8'd90:out=8'he5; 8'd91:out=8'he3; 8'd92:out=8'he1; 8'd93:out=8'hde; 8'd94:out=8'hdd; 8'd95:out=8'hda; 8'd96:out=8'hd8; 8'd97:out=8'hd6; 8'd98:out=8'hd4; 8'd99:out=8'hd1; 8'd100:out=8'hcf; 8'd101:out=8'hcc; 8'd102:out=8'hca; 8'd103:out=8'hc7; 8'd104:out=8'hc5; 8'd105:out=8'hc2; 8'd106:out=8'hbf; 8'd107:out=8'hbc; 8'd108:out=8'hba; 8'd109:out=8'hb7; 8'd110:out=8'hb4; 8'd111:out=8'hb1; 8'd112:out=8'hae; 8'd113:out=8'hab; 8'd114:out=8'ha8; 8'd115:out=8'ha5; 8'd116:out=8'ha2; 8'd117:out=8'h9f; 8'd118:out=8'h9c; 8'd119:out=8'h99; 8'd120:out=8'h96; 8'd121:out=8'h93; 8'd122:out=8'h90; 8'd123:out=8'h8d; 8'd124:out=8'h89; 8'd125:out=8'h86; 8'd126:out=8'h83; 8'd127:out=8'h80; 8'd128:out=8'h80; 8'd129:out=8'h7c; 8'd130:out=8'h79; 8'd131:out=8'h76; 8'd132:out=8'h72; 8'd133:out=8'h6f; 8'd134:out=8'h6c; 8'd135:out=8'h69; 8'd136:out=8'h66; 8'd137:out=8'h63; 8'd138:out=8'h60; 8'd139:out=8'h5d; 8'd140:out=8'h5a; 8'd141:out=8'h57; 8'd142:out=8'h55; 8'd143:out=8'h51; 8'd144:out=8'h4e; 8'd145:out=8'h4c; 8'd146:out=8'h48; 8'd147:out=8'h45; 8'd148:out=8'h43; 8'd149:out=8'h40; 8'd150:out=8'h3d; 8'd151:out=8'h3a; 8'd152:out=8'h38; 8'd153:out=8'h35; 8'd154:out=8'h33; 8'd155:out=8'h30; 8'd156:out=8'h2e; 8'd157:out=8'h2b; 8'd158:out=8'h29; 8'd159:out=8'h27; 8'd160:out=8'h25; 8'd161:out=8'h22; 8'd162:out=8'h20; 8'd163:out=8'h1e; 8'd164:out=8'h1c; 8'd165:out=8'h1a; 8'd166:out=8'h18; 8'd167:out=8'h16 ; 8'd168:out=8'h15; 8'd169:out=8'h13; 8'd170:out=8'h11; 8'd171:out=8'h10; 8'd172:out=8'h0e; 8'd173:out=8'h0d; 8'd174:out=8'h0b; 8'd175:out=8'h0a; 8'd176:out=8'h09; 8'd177:out=8'h08; 8'd178:out=8'h07; 8'd179:out=8'h06; 8'd180:out=8'h05; 8'd181:out=8'h04; 8'd182:out=8'h03; 8'd183:out=8'h02; 8'd184:out=8'h02; 8'd185:out=8'h01; 8'd186:out=8'h00; 8'd187:out=8'h00; 8'd188:out=8'h00; 8'd189:out=8'h00; 8'd190:out=8'h00; 8'd191:out=8'h00; 8'd192:out=8'h00; 8'd193:out=8'h00; 8'd194:out=8'h00; 8'd195:out=8'h00; 8'd196:out=8'h00; 8'd197:out=8'h00; 8'd198:out=8'h01; 8'd199:out=8'h02 ; 8'd200:out=8'h02; 8'd201:out=8'h03; 8'd202:out=8'h04; 8'd203:out=8'h05; 8'd204:out=8'h06; 8'd205:out=8'h07; 8'd206:out=8'h08; 8'd207:out=8'h09; 8'd208:out=8'h0a; 8'd209:out=8'h0b; 8'd210:out=8'h0d; 8'd211:out=8'h0e; 8'd212:out=8'h10; 8'd213:out=8'h11; 8'd214:out=8'h13; 8'd215:out=8'h15 ; 8'd216:out=8'h16; 8'd217:out=8'h18; 8'd218:out=8'h1a; 8'd219:out=8'h1c; 8'd220:out=8'h1e; 8'd221:out=8'h20; 8'd222:out=8'h22; 8'd223:out=8'h25; 8'd224:out=8'h27; 8'd225:out=8'h29; 8'd226:out=8'h2b; 8'd227:out=8'h2e; 8'd228:out=8'h30; 8'd229:out=8'h33; 8'd230:out=8'h35; 8'd231:out=8'h38; 8'd232:out=8'h3a; 8'd233:out=8'h3d; 8'd234:out=8'h40; 8'd235:out=8'h43; 8'd236:out=8'h45; 8'd237:out=8'h48; 8'd238:out=8'h4c; 8'd239:out=8'h4e; 8'd240:out=8'h51; 8'd241:out=8'h55; 8'd242:out=8'h57; 8'd243:out=8'h5a; 8'd244:out=8'h5d; 8'd245:out=8'h60; 8'd246:out=8'h63; 8'd247:out=8'h66 ; 8'd248:out=8'h69; 8'd249:out=8'h6c; 8'd250:out=8'h6f; 8'd251:out=8'h72; 8'd252:out=8'h76; 8'd253:out=8'h79; 8'd254:out=8'h7c; 8'd255:out=8'h80; endcase end end

这里的out赋值没有用非阻塞赋值,不过仿真的时候没有错误,数据可以正常显示。但是为了代码规范,还是用<=比较稳妥一些。

testbech

在这里插入图片描述
颜色可以在右侧的Color那里修改,不改也没有影响,这里看着好看而已。
code:

initial begin clk = 0; rst = 0; #5 rst = 1; #5 clk = 1; #150000 rst = 0; #5 $finish; end always begin #1 clk =~clk; end

这里我分频分的有点多,因为实际的FPGA的时钟频率都挺高的,不分多点不好看。但是仿真的话,这个数据就有点丑,将就将就。

波形显示

在这里插入图片描述
前面看这里都是红色,就是因为计数还没够,所以没有输出。
在这里插入图片描述
现在的效果就很明显了,不过,因为这个实际波形要用DAC 输出来看,Robei好像没有像Modesim那样可以合并数据看波形的功能,所以至此就是仿真成功了。

————————————正文结束的分割线————————————

FPGA的本质是什么?
复读机
逻辑单元构成的数字电路,所以在FPGA里,利用各种基础的逻辑运算来优化Verilog代码,在实际中,可以很大程度提高计算/处理能力。(当然这个得优化到宏观,才能从一定程度体现出来,就我现在这个水平的代码,优不优化没区别)
与,或,非,异或,?:,这些,可以在一些 tip 上用,来达到巧妙的化简代码。(比如上次PWM的三目运算符)


作者:Ninquelote



dds fpga eda

需要 登录 后方可回复, 如果你还没有账号请 注册新账号
相关文章