任务介绍:
很早就想去接触一下FPGA了。感觉它很神秘,像是单片机,又和单片机有很大区别。趁着“电子森林推出的2022暑期在家一起练(3) - 基于FPGA的电子琴设计”的机会,开始了学习FPGA的路程。这次活动使用的是STEP小脚丫FPGA STEP-MXO2-C。
-
板载资源:
-
两位7段数码管;
-
两个RGB三色LED;
-
8路用户LED;
-
4路拨码开关;
-
4路按键;
-
-
36个用户可扩展I/O(其中包括一路SPI硬核接口和一路I2C硬核接口)
-
支持的开发工具Lattice Diamond
-
支持MICO32/8软核处理器
-
板上集成FPGA编程器
-
一路Micro USB接口
-
板卡尺寸52mm x 18mm
任务内容:
- 基于我们提供的套件和工具,自己组装电子琴
- 自己编程基于FPGA实现:
- 存储一段音乐,并可以进行音乐播放,
- 可以自己通过板上的按键进行弹奏,支持两个按键同时按下(和弦)并且声音不能失真,板上的按键只有13个,可以通过有上方的“上“、”下”两个按键对音程进行扩展
- 使用扬声器进行播放时,输出的音调信号除了对应于该音调的单频正弦波外,还必须包含至少一个谐波分量
- 音乐的播放支持两种方式,这两种方式可以通过开关进行切换:
- 当开关切换到蜂鸣器端,可以通过蜂鸣器来进行音乐播放
- 当开关切换到扬声器端,可以通过模拟扬声器来进行音乐播放,每个音符都必须包含基频 + 至少一个谐波分量
任务实现:
入门:第一次接触FPGA,各种不适应。从硬禾学堂的《小脚丫FPGA在数字电路设计中的应用》开始学起,才明白FPGA和自己掌握的软件知识完全不一样。FPGA更加偏向于硬件,编程也更加底层。开发工具使用了“Diamond”和小脚丫的在线编程,在群里老师的帮助下,学会了使用apio来做模拟。最后在老师的直播课《2022暑假练FPGA电子琴直播 - 项目需求及参考资源》指导下开始了自己的项目。
输入:电子琴有13个琴键;右上角还有两个按键,底部还有一个拨动开关。分配一下各个按键的功能。底部拨动开关作为扬声器、蜂鸣器的选择开关。右边两个按键上边的按键作为音调切换按键,下边的用来控制是否自动播放音乐。自己音乐知识匮乏,就知道个简谱。安排13个琴键为低音mi到高音do,当音调切换后就变换为 从do到高音la。一共19个音调。使用小脚丫板子上的三个LED灯,用了指示当前状态。
音名 | 对应简谱 | 频率 | 传入参数 | |
低音 | 1 | 261.63 | 366 | |
低音 | 2 | 293.67 | 411 | |
低音 | 3 | 329.63 | 461 | |
低音 | 4 | 349.23 | 488 | |
低音 | 5 | 391.99 | 548 | |
低音 | 6 | 440 | 615 | |
低音 | 7 | 493.88 | 690 | |
中音 | 1 | 532.25 | 744 | |
中音 | 2 | 587.33 | 821 | |
中音 | 3 | 659.25 | 922 | |
中音 | 4 | 698.46 | 977 | |
中音 | 5 | 783.99 | 1096 | |
中音 | 6 | 880 | 1230 | |
中音 | 7 | 987.76 | 1381 | |
高音 | 1 | 1046.5 | 1463 | |
高音 | 2 | 1174.66 | 1642 | |
高音 | 3 | 1318.51 | 1843 | |
高音 | 4 | 1396.92 | 1953 | |
高音 | 5 | 1567.98 | 2192 | |
高音 | 6 | 1760 | 2461 |
消抖:小脚丫FPGA电子琴使用的是机械开关,这就会导致琴键(按键)按下后大概率会有多次电平的高低跳变。这里直接使用了一个消抖模块进行消抖处理。
// Module Function:按键消抖
module debounce (clk,rst,key,key_out,key_pulse);
parameter N = 1; //要消除抖动的按键的数量
input clk;
input rst;
input [N-1:0] key; //输入的按键
output [N-1:0] key_out;
output [N-1:0] key_pulse; //按键动作产生的脉冲一个时钟周期高电平
reg [N-1:0] key_rst_pre; //定义一个寄存器型变量存储上一个触发时的按键值
reg [N-1:0] key_rst; //定义一个寄存器变量储存储当前时刻触发的按键值
wire [N-1:0] key_edge; //检测到按键由高到低变化时产生一个高脉冲
//利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中
always @(posedge clk or negedge rst)
begin
if (!rst) begin
key_rst <= {N{1'b1}}; //初始化时给key_rst赋值全为1,{}中表示N个1
key_rst_pre <= {N{1'b1}};
end
else begin
key_rst <= key; //第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_pre
key_rst_pre <= key_rst; //非阻塞赋值。相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值
end
end
//脉冲边沿检测。当key检测到下降沿时,key_edge产生一个时钟周期的高电平
assign key_edge = key_rst_pre & (~key_rst);
reg [17:0] cnt; //产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器
//产生20ms延时,当检测到key_edge有效是计数器清零开始计数
always @(posedge clk or negedge rst)
begin
if(!rst)
cnt <= 18'h0;
else if(key_edge)
cnt <= 18'h0;
else
cnt <= cnt + 1'h1;
end
reg [N-1:0] key_sec_pre; //延时后检测电平寄存器变量
reg [N-1:0] key_sec;
//延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec <= {N{1'b1}};
else if (cnt==18'h3ffff)
key_sec <= key;
end
always @(posedge clk or negedge rst)
begin
if (!rst)
key_sec_pre <= {N{1'b1}};
else
key_sec_pre <= key_sec;
end
assign key_pulse = key_sec_pre & (~key_sec);
assign key_out = key_sec;
endmodule
自动播放音乐:自动播放的曲子选了《梁祝》,曲子是1/4节拍的,相当于每秒按下4次按键。程序只需要将对应的按键信息记录下来,然后依次自动按下就可以实现自动播放。于是就使用晶振产生4Hz的时钟,然后将保存在136位的数组里的曲子信息,依次弹奏出来,就实现了自动播放音乐。
module clk_quarter(
input wire clk_in,rst_in,
output reg clk_out
);
localparam counter_max = 32'd3000000; //
reg [31:0]counter;
always@(posedge clk_in or negedge rst_in)begin
if(!rst_in)begin
counter <= 0;
clk_out <= 1'b0;
end
else begin
if(counter >= counter_max)begin
counter <= 0;
clk_out <= 1'b1;
end
else begin
counter <= counter + 1'b1;
clk_out <= 1'b0;
end
end
end
endmodule
形成正弦波信号:需要将输入的信息转换为对应的正弦波信息。反复观看直播课老师的视频,学习老师思路和方法,通过查询波表的方式形成对应的正弦波。
module sin_table(
input [5:0] address, //64个点来生成1/4个周期的波形,完整的一个周期为256个点
output reg [8:0] sin //实际波形表为9位分辨率(1/4周期)
);
always @(address)
begin
case(address)
6'h0: sin=9'h0;
6'h1: sin=9'hC;
6'h2: sin=9'h19;
6'h3: sin=9'h25;
6'h4: sin=9'h32;
6'h5: sin=9'h3E;
6'h6: sin=9'h4B;
6'h7: sin=9'h57;
6'h8: sin=9'h63;
6'h9: sin=9'h70;
6'ha: sin=9'h7C;
6'hb: sin=9'h88;
6'hc: sin=9'h94;
6'hd: sin=9'hA0;
6'he: sin=9'hAC;
6'hf: sin=9'hB8;
6'h10: sin=9'hC3;
6'h11: sin=9'hCF;
6'h12: sin=9'hDA;
6'h13: sin=9'hE6;
6'h14: sin=9'hF1;
6'h15: sin=9'hFC;
6'h16: sin=9'h107;
6'h17: sin=9'h111;
6'h18: sin=9'h11C;
6'h19: sin=9'h126;
6'h1a: sin=9'h130;
6'h1b: sin=9'h13A;
6'h1c: sin=9'h144;
6'h1d: sin=9'h14E;
6'h1e: sin=9'h157;
6'h1f: sin=9'h161;
6'h20: sin=9'h16A;
6'h21: sin=9'h172;
6'h22: sin=9'h17B;
6'h23: sin=9'h183;
6'h24: sin=9'h18B;
6'h25: sin=9'h193;
6'h26: sin=9'h19B;
6'h27: sin=9'h1A2;
6'h28: sin=9'h1A9;
6'h29: sin=9'h1B0;
6'h2a: sin=9'h1B7;
6'h2b: sin=9'h1BD;
6'h2c: sin=9'h1C3;
6'h2d: sin=9'h1C9;
6'h2e: sin=9'h1CE;
6'h2f: sin=9'h1D4;
6'h30: sin=9'h1D9;
6'h31: sin=9'h1DD;
6'h32: sin=9'h1E2;
6'h33: sin=9'h1E6;
6'h34: sin=9'h1E9;
6'h35: sin=9'h1ED;
6'h36: sin=9'h1F0;
6'h37: sin=9'h1F3;
6'h38: sin=9'h1F6;
6'h39: sin=9'h1F8;
6'h3a: sin=9'h1FA;
6'h3b: sin=9'h1FC;
6'h3c: sin=9'h1FD;
6'h3d: sin=9'h1FE;
6'h3e: sin=9'h1FF;
6'h3f: sin=9'h1FF;
endcase
end
endmodule
//查找正弦值
module look_table(
input [7:0] phase,
output [9:0] sin_out
);
reg [5:0] address;
wire [1:0] sel;
wire [8:0] sine_table_out;
reg [9:0] sine_onecycle_amp;
assign sin_out = sine_onecycle_amp[9:0];
assign sel = phase[7:6];
sin_table u_sin_table(
.address(address),
.sin(sine_table_out)
);
always @(sel or sine_table_out or phase)
begin
case(sel)
2'b00: begin
sine_onecycle_amp = 9'h1ff+sine_table_out[8:0];
address = phase[5:0];
end
2'b01: begin
sine_onecycle_amp = 9'h1ff+sine_table_out[8:0];
address = ~phase[5:0];
end
2'b10: begin
sine_onecycle_amp = 9'h1ff- sine_table_out[8:0];
address = phase[5:0];
end
2'b11: begin
sine_onecycle_amp = 9'h1ff- sine_table_out[8:0];
address = ~ phase[5:0];
end
endcase
end
endmodule
这里sintable记录了正弦波的1/4波型的离散值,共64个点。当一个指定频率的波需要查询当前时间点的值时,在looktable使用8位地址(其中高两位来判断在播的那个位置)来找出波的值。
module wave(
input clk,
input rst,
input enable,
output reg [9:0] waveout
);
parameter FREQ = 24'd366; //C1 261.63Hz 时钟12MHz =(261.63*2**24)/12000000
reg [23:0] phase_acc;
wire [9:0] sinout;
always @(posedge clk or negedge rst)
if(!rst)
phase_acc <= 0;
else
phase_acc <= phase_acc + FREQ;
always@(posedge clk or negedge rst)
if(!rst)
waveout <=0;
else if(!enable)
waveout <= sinout;
else
waveout <= 0;
look_table u0_table(
.phase(phase_acc[23:16]),
.sin_out(sinout)
);
endmodule
核心部分wave这个模块,用来获得一个具体的正弦波。波的频率由参FREQ决定。频率计算公式:输入值=(波的频率值*2^24)/12000000 。
这里用apio做模拟,获得532.25Hz(do,输入值744)的波形。正弦波还是挺漂亮的!(这里需要留意,因为apio模拟程序的限制,clk无法输入小于1的值,导致波的周期时间不对)
有了正玄波,仅仅是能够表达正确的频率。我们能够准确地分辨各种乐器的演奏,是因为除了制定频率的波之外还有个谐波。谐波的频率是基波的整数倍。在本项目中,我使用2倍频率作为谐波,并且做了适当的弱化(*0.6)。仿真图如下。
按题目要求,当多按键按下时,必须同时产生多个按键对应频率的波。所以这里还需要处理多个波的信号的叠加。模块synthesizer就是将多个波形进行叠加输出。这里是叠加了 532.25Hz,659.25Hz,783.995Hz(do,mi,so)三条波形。
输出:信号最终是要由扬声器(蜂鸣器)做展示。但是小脚丫的输出管脚输出的只能是0、1的数字信号,这里就需要使用PWM通过对占空比的控制来获得到一个直流分量。PWM波自身有一个频率,通过占空比的改变来形成正弦波的输出。质量就要求PWM的频率远大于输入的正弦波的频率。
这里的输出本质上依然是高低电平。高低电平作用于蜂鸣器和扬声器还是有区别的。观察电路图可以发现,蜂鸣器是小脚丫的输出管脚使用一个三极管S8050直接驱动;而扬声器还经历了一个R-2R DAC的转换然后在由放大器8002B来驱动扬声器的。R-2R DAC将数字信号转换为模拟信号,但是R-2R电路我没看太懂。这块我的基本理解就是扬声器使用了变化的电压作为输入信号,蜂鸣器使用的是1/0持续的时间来模拟电压的信号量。这里导致的结果就是,扬声器听上去声音比较好,失真小。而蜂鸣器就声音非常小,几乎到了听不见的程度。
module pwm
(
input clk,
input rst,
input [10:0] duty,
output pwm_out
);
reg [11:0] PWM_accumulator0;
always @(posedge clk or negedge rst)
if(!rst)
PWM_accumulator0 <= 0;
else
PWM_accumulator0 <= PWM_accumulator0[10:0] + duty;
assign pwm_out = PWM_accumulator0[11];
endmodule
PWM转换这里使用的是1阶的sigma-delta调制。在保证占空比的前提下尽可能采用更高的脉冲频率,尽可能地提高了DAC的转换频率,减少了对合成频率的频段内的混叠。但是任何输出的PWM波中,总是包含着两个频率的信息,只是一个频率较高,无法听见而已。
最后top模块将各个模块进行整合,分配管脚。通过两个状态变量,来记录功能键的信息。将当前状态信息通过LED灯展示出来。13个琴键,按高低音切换状态信息,来决定左补6位还是右补6位。然后按输出状态开关来决定是送到蜂鸣器还是扬声器。(项目地址:https://www.stepfpga.com/project/3329/)
run.log
--- Lattice Diamond Version 3.7.0.96.1
--- Copyright (C) 1992-2016 Lattice Semiconductor Corporation.
--- All Rights Reserved.
--- Lattice Diamond install path: 3.7_x64
--- Start Time: Sat Aug 20 09:37:29 2022
WARNING - Create a new implementation in an existing sub-directory 'implement'.
synthesis -f "PRJ_3329_implement_lattice.synproj"
synthesis: version Diamond (64-bit) 3.7.0.96.1
Copyright (c) 1991-1994 by NeoCAD Inc. All rights reserved.
Copyright (c) 1995 AT&T Corp. All rights reserved.
Copyright (c) 1995-2001 Lucent Technologies Inc. All rights reserved.
Copyright (c) 2001 Agere Systems All rights reserved.
Copyright (c) 2002-2016 Lattice Semiconductor Corporation, All rights reserved.
Sat Aug 20 09:37:30 2022
Command Line: synthesis -f PRJ_3329_implement_lattice.synproj
INFO - synthesis: Lattice Synthesis Engine Launched.
Synthesis options:
The -a option is MachXO2.
The -s option is 5.
The -t option is CSBGA132.
The -d option is LCMXO2-4000HC.
Using package CSBGA132.
Using performance grade 5.
##########################################################
### Lattice Family : MachXO2
### Device : LCMXO2-4000HC
### Package : CSBGA132
### Speed : 5
##########################################################
Optimization goal = Balanced
The -top option is not used.
Target frequency = 1.000000 MHz.
Maximum fanout = 1000.
Timing path count = 3
BRAM utilization = 100.000000 %
DSP usage = true
DSP utilization = 100.000000 %
fsm_encoding_style = auto
resolve_mixed_drivers = 0
fix_gated_clocks = 1
Mux style = Auto
Use Carry Chain = true
carry_chain_length = 0
Loop Limit = 1950.
Use IO Insertion = TRUE
Use IO Reg = AUTO
Resource Sharing = TRUE
Propagate Constants = TRUE
Remove Duplicate Registers = TRUE
force_gsr = auto
ROM style = auto
RAM style = auto
The -comp option is FALSE.
The -syn option is FALSE.
-p 3329 (searchpath added)
-p data (searchpath added)
-p implement (searchpath added)
-p 3329 (searchpath added)
Verilog design file = clk_quarter.v
Verilog design file = debounce.v
Verilog design file = looktable.v
Verilog design file = pwm.v
Verilog design file = sintable.v
Verilog design file = synthesizer.v
Verilog design file = top.v
Verilog design file = wave.v
NGD file = PRJ_3329_implement.ngd
-sdc option: SDC file input not used.
-lpf option: Output file option is ON.
Hardtimer checking is enabled (default). The -dt option is not used.
The -r option is OFF. [ Remove LOC Properties is OFF. ]
WARNING - synthesis: Setting top as the top-level module. To specify the top-level module explicitly, use the -top option.
Technology check ok...
Analyzing Verilog file machxo2.v. VERI-1482
Compile design.
Compile Design Begin
Analyzing Verilog file clk_quarter.v. VERI-1482
Analyzing Verilog file debounce.v. VERI-1482
Analyzing Verilog file looktable.v. VERI-1482
Analyzing Verilog file pwm.v. VERI-1482
Analyzing Verilog file sintable.v. VERI-1482
Analyzing Verilog file synthesizer.v. VERI-1482
Analyzing Verilog file top.v. VERI-1482
Analyzing Verilog file wave.v. VERI-1482
Analyzing Verilog file machxo2.v. VERI-1482
Top module name (Verilog): top
INFO - synthesis: top.v(1): compiling module top. VERI-1018
INFO - synthesis: clk_quarter.v(18): compiling module clk_quarter. VERI-1018
INFO - synthesis: debounce.v(18): compiling module debounce(N=13). VERI-1018
INFO - synthesis: debounce.v(18): compiling module debounce. VERI-1018
INFO - synthesis: pwm.v(18): compiling module pwm. VERI-1018
INFO - synthesis: synthesizer.v(1): compiling module synthesizer. VERI-1018
INFO - synthesis: wave.v(1): compiling module wave(FREQ=461). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: looktable.v(2): compiling module look_table. VERI-1018
INFO - synthesis: sintable.v(1): compiling module sin_table. VERI-1018
INFO - synthesis: wave.v(1): compiling module wave(FREQ=488). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=548). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=615). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=690). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=744). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=821). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=922). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=977). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1096). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1230). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1381). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1463). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1642). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1843). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1953). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=2192). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=2641). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=2762). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=1488). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=2461). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=2926). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=3285). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=3687). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=3906). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=3384). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=4921). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
INFO - synthesis: wave.v(1): compiling module wave(FREQ=5524). VERI-1018
WARNING - synthesis: wave.v(16): expression size 32 truncated to fit in target size 24. VERI-1209
ERROR - synthesis: synthesizer.v(82): illegal operation with real number. VERI-1044
资源使用情况:还不太会看这个列表,待学习。
Design Summary:
Number of registers: 1221 out of 4635 (26%)
PFU registers: 1221 out of 4320 (28%)
PIO registers: 0 out of 315 (0%)
Number of SLICEs: 2021 out of 2160 (94%)
SLICEs as Logic/ROM: 2021 out of 2160 (94%)
SLICEs as RAM: 0 out of 1620 (0%)
SLICEs as Carry: 1000 out of 2160 (46%)
Number of LUT4s: 4036 out of 4320 (93%)
Number used as logic LUTs: 2036
Number used as distributed RAM: 0
Number used as ripple logic: 2000
Number used as shift registers: 0
Number of PIO sites used: 23 + 4(JTAG) out of 105 (26%)
Number of block RAMs: 0 out of 10 (0%)
Number of GSRs: 1 out of 1 (100%)
EFB used : No
JTAG used : No
Readback used : No
Oscillator used : No
Startup used : No
POR : On
Bandgap : On
Number of Power Controller: 0 out of 1 (0%)
Number of Dynamic Bank Controller (BCINRD): 0 out of 6 (0%)
Number of Dynamic Bank Controller (BCLVDSO): 0 out of 1 (0%)
Number of DCCA: 0 out of 8 (0%)
Number of DCMA: 0 out of 2 (0%)
Number of PLLs: 0 out of 2 (0%)
Number of DQSDLLs: 0 out of 2 (0%)
Number of CLKDIVC: 0 out of 4 (0%)
Number of ECLKSYNCA: 0 out of 4 (0%)
Number of ECLKBRIDGECS: 0 out of 2 (0%)
Notes:-
1. Total number of LUT4s = (Number of logic LUT4s) + 2*(Number of distributed RAMs) + 2*(Number of ripple logic)
2. Number of logic LUT4s does not include count of distributed RAM and ripple logic.
Number of clocks: 2
Net clk_c: 674 loads, 674 rising, 0 falling (Driver: PIO clk )
Net clk_4Hz: 5 loads, 5 rising, 0 falling (Driver: clk_inst/clk_out_12 )
Number of Clock Enables: 2
Net debounce_k13/clk_c_enable_1: 1 loads, 1 LSLICEs
Net debounce_k14/clk_c_enable_2: 1 loads, 1 LSLICEs
Number of LSRs: 21
Net pos_7__N_64: 5 loads, 5 LSLICEs
Net wave_in_4: 12 loads, 12 LSLICEs
Net wave_in_6: 12 loads, 12 LSLICEs
Net wave_in_7: 12 loads, 12 LSLICEs
Net wave_in_1: 12 loads, 12 LSLICEs
Net wave_in_8: 12 loads, 12 LSLICEs
Net wave_in_10: 12 loads, 12 LSLICEs
Net wave_in_0: 12 loads, 12 LSLICEs
Net debounce_k13/key_edge_0: 10 loads, 10 LSLICEs
Net clk_inst/counter_31__N_131: 17 loads, 17 LSLICEs
Net wave_in_2: 12 loads, 12 LSLICEs
Net wave_in_9: 12 loads, 12 LSLICEs
Net wave_in_11: 12 loads, 12 LSLICEs
Net wave_in_3: 12 loads, 12 LSLICEs
Net wave_in_16: 12 loads, 12 LSLICEs
Net wave_in_18: 12 loads, 12 LSLICEs
Net wave_in_13: 12 loads, 12 LSLICEs
Net wave_in_14: 12 loads, 12 LSLICEs
Net wave_in_17: 12 loads, 12 LSLICEs
Net wave_in_15: 12 loads, 12 LSLICEs
Net debounce_k14/key_edge_0: 10 loads, 10 LSLICEs
Number of nets driven by tri-state buffers: 0
Top 10 highest fanout non-clock nets:
Net synthesizer_u0/n11086: 61 loads
Net synthesizer_u0/n11071: 60 loads
Net synthesizer_u0/n11073: 58 loads
Net synthesizer_u0/n19351: 58 loads
Net synthesizer_u0/n11079: 56 loads
Net synthesizer_u0/n19358: 56 loads
Net synthesizer_u0/n11078: 54 loads
Net synthesizer_u0/n19367: 54 loads
Net synthesizer_u0/n11077: 52 loads
Net synthesizer_u0/n19375: 52 loads
Number of warnings: 0
Number of errors: 0
Total CPU Time: 1 secs
Total REAL Time: 2 secs
Peak Memory Usage: 74 MB
遇到的问题及解决方法
FPGA编程真难。Diamond软件真的很不友好,错误提示完全不明就里。Verilog中的并行概念非常有意思,自己的先入为主,按着经验推测代码都是顺序执行的,结果让自己卡了很久,在各位老师的解释下才明白,FPGA中的并行执行。自动播放音乐部分想用模块实现,可要么报错,要么无法实现功能,无奈下只能放在top模块中了。感觉入门FPGA还是挺艰辛 的,感谢硬禾学堂的课程和电子森林的教程,自己的学习道路才刚刚开始。在群里讨论中,还有几个思路还没有去尝试:谐波使用波表来解决,就是在查表时就将谐波信息写入,但添加了谐波的正弦波对称性就破坏了,使用四分之一波表应该是不行了,感觉要使用二分之一波表才够用。IP核编程,群里老师介绍,可以将模块功能放置在ip核中,还没太明白怎么做,后续需要继续尝试一下。