2022寒假在家练-基于小脚丫FPGA实现DDS任意波形发生器/本地控制
本项目是基于Lattice小脚丫XO-4000HC FPGA核心板以及相应的硬禾学堂电赛训练板,按照官方要求所实现的DDS任意波形发生器/本地控制,可产生1-20MHz,幅度0.1-1V可调的正弦波、方波、三角波、锯齿波。
标签
FPGA
数字逻辑
显示
DDS
2022寒假在家练
damie_EE
更新2022-03-03
哈尔滨工程大学
1860

项目概述

 本项目是基于Lattice小脚丫XO-4000HC FPGA核心板以及相应的硬禾学堂电赛训练板,按照官方要求所实现的DDS任意波形发生器/本地控制,可产生1-20MHz,幅度0.1-1V可调的正弦波、方波、三角波、锯齿波。 基本硬件介绍:

本项目所使用的主要器件包括Lattice小脚丫XO-4000HC FPGA核心板以及相应的硬禾学堂电赛训练板,使用了基于3PD5651E(10-Bit, 50MSPS, CMOS模数变换器)芯片的DAC模块,显示模块使用的是基于ssd1306芯片的128x64的OLED屏幕。

要求/任务:

  • 1个旋转编码器和2个按键控制参数的输入
  • 通过128 * 64的OLED显示参数信息以及菜单
  • FPGA连接10bit/120Msps的高速DAC模块

作品可完成指标:

  • 通过板上的高速DAC(10bits/125Msps)配合FPGA内部DDS的逻辑,生成波形可调(正弦波、三角波、锯齿波、方波)、频率可调(DC-)、幅度可调的波形
  • 生成模拟信号的频率范围为DC-20MHz,调节精度可为1Hz(在家由于设备条件限制也是为了更便于调节,最终版代码改成了100Hz步进)
  • 生成模拟信号的幅度为1-1.0Vpp
  • 可以在OLED上显示当前波形、频率以及幅度
  • 利用板上旋转编码器能够对波形进行切换、进行参数调节

设计思路:

      本作品采用FPGA驱动DAC模块实现DDS任意波形发生器,可以将要输出的波形数据(如正弦函数表或其他)预先存放在存储单元(如BlockRAM)中,然后在系统标准时钟频率下,按照一定的顺序从存储单元中读出波形数据,再进行D/A转换及低通滤波,就可以得到一定频率的输出波形。上述过程可使用HDL硬件描述语言对FPGA编程实现。

下面是该项目系统构成框图:Fu-Ra0j3I3dM6XqNBKu_XqurrAVo

      其中FPGA内部逻辑如图所示:Fmm8WoU_ruGk56BwqqmZyFZSsoDC

      主要的verilog模块如图所示:

Frqd8P4-HPhkowBlYb36od4Qad1X

实物展示图与作品使用说明:通过旋转旋钮以改变参数,通过按压旋钮改变所修改的参数对象(即:波形、幅度、频率),后接示波器即可查看输出。

Fj4oHASjNVROZgTY6Bygk9rfwFOy

实物展示图

主要代码片段:

DDS:

module dds(
	input sys_clk, //The clock rate is same to sample rate, and we set it to SAMPLE_RATE.
	input sys_rst_n,
	input [1:0] wave_type, //The 00:Cos wave;01:Square wave;10:Trig wave;11:Saw wave. 
	input [31:0] wave_freq,
	output reg [9:0] wave_dac
);
wire [9:0] Cos_Dac;
wire [9:0] Square_Dac;
wire [9:0] Trig_Dac;
wire [9:0] Saw_Dac;
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		wave_dac <= 10'd0;
	end else begin
		case(wave_type)
			2'b00: wave_dac <= Cos_Dac;
			2'b01: wave_dac <= Square_Dac;
			2'b10: wave_dac <= Trig_Dac;
			2'b11: wave_dac <= Saw_Dac;
		endcase
	end
end
//Cos wave
reg [27:0] dds_phase;
wire [27:0] dds_phase_add;
assign dds_phase_add = (wave_freq << 1) + (wave_freq >> 3) + (wave_freq >> 4) + (wave_freq >> 5) + (wave_freq >> 6) + (wave_freq >> 9) + (wave_freq >> 11) + (wave_freq >> 13); 
//wave_freq*2.2369384765625(10.00111100101010);
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		dds_phase <= 28'd0;
	end else begin
		dds_phase <= dds_phase + dds_phase_add;
	end
end
lut u_lut(
	.address(dds_phase[27:20]),
	.cos(Cos_Dac)
);
//Square wave
assign Square_Dac = {10{dds_phase[27]}};
//Trig wave
assign Trig_Dac = dds_phase[27] ? ~dds_phase[26:17] : dds_phase[26:17];
//Saw wave
assign Saw_Dac = dds_phase[27:18];

endmodule

OLED:

module oled12864
(
	input				clk,		//12MHz系统时钟
	input				rst_n,		//系统复位,低有效
	
	input		[1:0]	dis_type,
	input		[31:0]  dis_freq,
	input		[3:0]	dis_amp,
//	input				debug,
	
	output	reg			oled_csn,	//OLCD液晶屏使能
	output	reg			oled_rst,	//OLCD液晶屏复位
	output	reg			oled_dcn,	//OLCD数据指令控制
	output	reg			oled_clk,	//OLCD时钟信号
	output	reg			oled_dat	//OLCD数据信号
);
	
	localparam INIT_DEPTH = 16'd23; //LCD初始化的命令的数量
	localparam IDLE = 7'h1, MAIN = 7'h2, INIT = 7'h4, SCAN = 7'h8, WRITE = 7'h10, DELAY = 7'h20,CHINESE=7'h40;
	localparam HIGH	= 1'b1, LOW = 1'b0;
	localparam DATA	= 1'b1, CMD = 1'b0;
	
	reg 	[7:0] 			cmd [22:0]; //The register of command
	reg 	[39:0] 			mem [122:0]; //The register of ASCII memory
	reg		[127:0]			mem_hanzi[16:0]; //The register of chinese chars memeory
	
	reg		[7:0]			mem_hanzi_num; //The number of chinese chars to display
	reg	[7:0]				y_p, x_ph, x_pl;
	reg	[(8*21-1):0]   		char; //The memory of ASCII chars to display
	reg	[7:0]				num; //The number of ASCII chars to display
	reg [7:0]				char_reg;	//The register of ASCII char to display	
	reg	[4:0]				cnt_main, cnt_init, cnt_scan, cnt_write;
	reg	[5:0]				cnt_chinese;
	reg	[15:0]				num_delay, cnt_delay, cnt;
	reg	[6:0] 				state, state_back;
	
	reg [(3*8-1):0] 		dis_type_buff; //Typical: Sin,Squ,Trg,Saw
	wire [(9*8-1):0]		dis_freq_buff; //Typical: 20000 KHz
	wire [(7*8-1):0]		dis_amp_buff; //Typical: 0.1 Vpp
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			dis_type_buff <= "Sin";
		end else begin
			case(dis_type)
				2'b00: dis_type_buff <= "Sin";
				2'b01: dis_type_buff <= "Squ";
				2'b10: dis_type_buff <= "Trg";
				2'b11: dis_type_buff <= "Saw";
			endcase
		end
	end
	
	wire [3:0]				dis_freq_unit;
	wire [3:0]				dis_freq_ten;
	wire [3:0]				dis_freq_hun;
	wire [3:0]				dis_freq_tho;
	wire [3:0]				dis_freq_t_tho;
	wire [3:0]				dis_freq_h_hun;
	wire [3:0]				dis_freq_M;
	wire [3:0]				dis_freq_t_M;
	assign dis_freq_buff = {dis_freq_t_M,4'd0,dis_freq_M,4'd0,dis_freq_h_hun,4'd0,dis_freq_t_tho,4'd0,dis_freq_tho,4'd0,dis_freq_hun,"00 "};
	bcd_8421 u_bcd_8421(
	.sys_clk(clk), //系统时钟,频率50MHz
	.sys_rst_n(rst_n), //复位信号,低电平有效
    .data(dis_freq/1), //输入需要转换的数据

    .unit(dis_freq_unit), //个位BCD码
    .ten(dis_freq_ten), //十位BCD码
    .hun(dis_freq_hun), //百位BCD码
    .tho(dis_freq_tho), //千位BCD码
    .t_tho(dis_freq_t_tho), //万位BCD码
    .h_hun(dis_freq_h_hun),//十万位BCD码
	.M(dis_freq_M),
	.t_M(dis_freq_t_M)
	);
	
	
	assign dis_amp_buff = (dis_amp != 4'd10) ? {"0.",4'd0,dis_amp," Vpp"} : {"1.0 Vpp"};
	
	always @ (posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			cnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;cnt_chinese <= 1'b0;
			y_p <= 1'b0; x_ph <= 1'b0; x_pl <= 1'b0;
			num <= 1'b0; char <= 1'b0; char_reg <= 1'b0;
			num_delay <= 16'd5; cnt_delay <= 1'b0; cnt <= 1'b0;
			oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_dat <= LOW;
			state <= IDLE; state_back <= IDLE;
		end else begin
			case(state)
				IDLE:begin
						cnt_main <= 1'b0; cnt_init <= 1'b0; cnt_scan <= 1'b0; cnt_write <= 1'b0;
						y_p <= 1'b0; x_ph <= 1'b0; x_pl <= 1'b0;
						num <= 1'b0; char <= 1'b0; char_reg <= 1'b0;
						num_delay <= 16'd5; cnt_delay <= 1'b0; cnt <= 1'b0;mem_hanzi_num<=8'd0;
						oled_csn <= HIGH; oled_rst <= HIGH; oled_dcn <= CMD; oled_clk <= HIGH; oled_dat <= LOW;
						state <= MAIN; state_back <= MAIN;
					end
				MAIN:begin
						if(cnt_main >= 5'd15) cnt_main <= 5'd13;//接下来执行空操作,实现数据只刷新一次
						else cnt_main <= cnt_main + 1'b1;
						case(cnt_main)	//MAIN状态							
							5'd0 :	begin state <= INIT; end
																														
							5'd1 :	begin y_p <= 8'hb0; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
							5'd2 :	begin y_p <= 8'hb1; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end												
							5'd3 :	begin y_p <= 8'hb2; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
							5'd4 :	begin y_p <= 8'hb3; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
							5'd5 :	begin y_p <= 8'hb4; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
							5'd6 :	begin y_p <= 8'hb5; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end
							5'd7 :	begin y_p <= 8'hb6; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "              Hz";state <= SCAN; end
							5'd8 :	begin y_p <= 8'hb4; x_ph <= 8'h10; x_pl <= 8'h00; num <= 5'd16; char <= "                ";state <= SCAN; end							
							5'd9 :	begin y_p <= 8'hb2; x_ph <= 8'h00; x_pl <= 8'h08; num <= 5'd16; char <= "WAVE:           ";state <= SCAN; end
							5'd10:	begin y_p <= 8'hb4; x_ph <= 8'h00; x_pl <= 8'h08; num <= 5'd16; char <= "FRE:            ";state <= SCAN; end
							5'd11:	begin y_p <= 8'hb6; x_ph <= 8'h00; x_pl <= 8'h08; num <= 5'd16; char <= "AMP:            ";state <= SCAN; end
							5'd12:	begin y_p <= 8'hb0; x_ph <= 8'h00; x_pl <= 8'h08; num <= 5'd16; char <= "    DDS-LSY     ";state <= SCAN; end
								
							5'd13:	begin y_p <= 8'hb2; x_ph <= 8'h12; x_pl <= 8'h08; num <= 5'd3;  char <= dis_type_buff;state <= SCAN; end
							5'd14:	begin y_p <= 8'hb4; x_ph <= 8'h12; x_pl <= 8'h08; num <= 5'd10;  char <= dis_freq_buff;state <= SCAN; end
							5'd15:	begin y_p <= 8'hb6; x_ph <= 8'h12; x_pl <= 8'h08; num <= 5'd7;  char <= dis_amp_buff;state <= SCAN; end		
							
							default: state <= IDLE;   //如果你需要动态刷新一些信息,此行应该取消注释
						endcase
					end
				INIT:begin	//初始化状态
						case(cnt_init)
							5'd0:	begin oled_rst <= LOW; cnt_init <= cnt_init + 1'b1; end	//复位有效
							5'd1:	begin num_delay <= 16'd25000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end	//延时大于3us
							5'd2:	begin oled_rst <= HIGH; cnt_init <= cnt_init + 1'b1; end	//复位恢复
							5'd3:	begin num_delay <= 16'd25000; state <= DELAY; state_back <= INIT; cnt_init <= cnt_init + 1'b1; end	//延时大于220us
							5'd4:	begin 
										if(cnt>=INIT_DEPTH) begin	//当25条指令及数据发出后,配置完成
											cnt <= 1'b0;
											cnt_init <= cnt_init + 1'b1;
										end else begin	
											cnt <= cnt + 1'b1; num_delay <= 16'd5;
											oled_dcn <= CMD; char_reg <= cmd[cnt]; state <= WRITE; state_back <= INIT;
										end
									end
							5'd5:	begin cnt_init <= 1'b0; state <= MAIN; end	//初始化完成,返回MAIN状态
							default: state <= IDLE;
						endcase
					end
				SCAN:begin	//刷屏状态,从RAM中读取数据刷屏
						if(cnt_scan == 5'd11) begin
							if(num) cnt_scan <= 5'd3;
							else cnt_scan <= cnt_scan + 1'b1;
						end 
						else if(cnt_scan == 5'd12) cnt_scan <= 1'b0;
						else cnt_scan <= cnt_scan + 1'b1;
						case(cnt_scan)
							5'd 0:	begin oled_dcn <= CMD; char_reg <= y_p; state <= WRITE; state_back <= SCAN; end		//定位列页地址
							5'd 1:	begin oled_dcn <= CMD; char_reg <= x_pl; state <= WRITE; state_back <= SCAN; end	//定位行地址低位
							5'd 2:	begin oled_dcn <= CMD; char_reg <= x_ph; state <= WRITE; state_back <= SCAN; end	//定位行地址高位
							
							5'd 3:	begin num <= num - 1'b1;end
							5'd 4:	begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end	//将5*8点阵编程8*8
							5'd 5:	begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end	//将5*8点阵编程8*8
							5'd 6:	begin oled_dcn <= DATA; char_reg <= 8'h00; state <= WRITE; state_back <= SCAN; end	//将5*8点阵编程8*8
							5'd 7:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][39:32]; state <= WRITE; state_back <= SCAN; end
							5'd 8:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][31:24]; state <= WRITE; state_back <= SCAN; end
							5'd 9:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][23:16]; state <= WRITE; state_back <= SCAN; end
							5'd10:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][15: 8]; state <= WRITE; state_back <= SCAN; end
							5'd11:	begin oled_dcn <= DATA; char_reg <= mem[char[(num*8)+:8]][ 7: 0]; state <= WRITE; state_back <= SCAN; end
							5'd12:	begin state <= MAIN; end
							default: state <= IDLE;
						endcase
					end
					
					
			
					
				CHINESE:begin	//显示汉字
						
						if(cnt_chinese == 6'd38) cnt_chinese <= 1'b0;
						else cnt_chinese <= cnt_chinese+1'b1;
						case(cnt_chinese)    
							6'd 0:	begin oled_dcn <= CMD; char_reg <= y_p; state <= WRITE; state_back <= CHINESE; end		//定位列页地址
							6'd 1:	begin oled_dcn <= CMD; char_reg <= x_pl; state <= WRITE; state_back <= CHINESE; end	//定位行地址低位
							6'd 2:	begin oled_dcn <= CMD; char_reg <= x_ph; state <= WRITE; state_back <= CHINESE; end	//定位行地址高位
							
							6'd3 :	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][127:120]; state <= WRITE; state_back <= CHINESE; end
							6'd4 :	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][119:112]; state <= WRITE; state_back <= CHINESE; end
							6'd5 :	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][111:104]; state <= WRITE; state_back <= CHINESE; end
							6'd6 :	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][103:96] ; state <= WRITE; state_back <= CHINESE; end
							6'd7 :	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][95:88]  ; state <= WRITE; state_back <= CHINESE; end
							6'd8 :	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][87:80]  ; state <= WRITE; state_back <= CHINESE; end
							6'd9 :	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][79:72]  ; state <= WRITE; state_back <= CHINESE; end
							6'd10:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][71:64]  ; state <= WRITE; state_back <= CHINESE; end 
							6'd11:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][63:56];   state <= WRITE; state_back <= CHINESE; end
							6'd12:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][55:48];   state <= WRITE; state_back <= CHINESE; end
							6'd13:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][47:40];   state <= WRITE; state_back <= CHINESE; end
							6'd14:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][39:32];   state <= WRITE; state_back <= CHINESE; end
							6'd15:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][31:24];   state <= WRITE; state_back <= CHINESE; end
							6'd16:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][23:16];   state <= WRITE; state_back <= CHINESE; end
							6'd17:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][15: 8];   state <= WRITE; state_back <= CHINESE; end
							6'd18:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num][ 7: 0];   state <= WRITE; state_back <= CHINESE; end 
							
							6'd19:	begin oled_dcn <= CMD; char_reg <= y_p+1; state <= WRITE; state_back <= CHINESE; end		//定位列页地址
							6'd20:	begin oled_dcn <= CMD; char_reg <= x_pl; state <= WRITE; state_back <= CHINESE; end	//定位行地址低位
							6'd21:	begin oled_dcn <= CMD; char_reg <= x_ph; state <= WRITE; state_back <= CHINESE; end	//定位行地址高位
							6'd22:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][127:120]; state <= WRITE; state_back <= CHINESE; end
							6'd23:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][119:112]; state <= WRITE; state_back <= CHINESE; end
							6'd24:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][111:104]; state <= WRITE; state_back <= CHINESE; end
							6'd25:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][103:96] ; state <= WRITE; state_back <= CHINESE; end
							6'd26:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][95:88]  ; state <= WRITE; state_back <= CHINESE; end
							6'd27:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][87:80]  ; state <= WRITE; state_back <= CHINESE; end
							6'd28:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][79:72]  ; state <= WRITE; state_back <= CHINESE; end
							6'd29:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][71:64]  ; state <= WRITE; state_back <= CHINESE; end 
							6'd30:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][63:56];   state <= WRITE; state_back <= CHINESE; end
							6'd31:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][55:48];   state <= WRITE; state_back <= CHINESE; end
							6'd32:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][47:40];   state <= WRITE; state_back <= CHINESE; end
							6'd33:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][39:32];   state <= WRITE; state_back <= CHINESE; end
							6'd34:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][31:24];   state <= WRITE; state_back <= CHINESE; end
							6'd35:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][23:16];   state <= WRITE; state_back <= CHINESE; end
							6'd36:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][15: 8];   state <= WRITE; state_back <= CHINESE; end
							6'd37:	begin oled_dcn <= DATA; char_reg <= mem_hanzi[mem_hanzi_num+1][ 7: 0];   state <= WRITE; state_back <= CHINESE; end 
                            
							6'd38:	begin state <= MAIN; end
							default: state <= IDLE;
						endcase
					end
					
					
					
				WRITE:begin	//WRITE状态,将数据按照SPI时序发送给屏幕
						if(cnt_write >= 5'd17) cnt_write <= 1'b0;
						else cnt_write <= cnt_write + 1'b1;
						case(cnt_write)
							5'd 0:	begin oled_csn <= LOW; end	//9位数据最高位为命令数据控制位
							5'd 1:	begin oled_clk <= LOW; oled_dat <= char_reg[7]; end	//先发高位数据
							5'd 2:	begin oled_clk <= HIGH; end
							5'd 3:	begin oled_clk <= LOW; oled_dat <= char_reg[6]; end
							5'd 4:	begin oled_clk <= HIGH; end
							5'd 5:	begin oled_clk <= LOW; oled_dat <= char_reg[5]; end
							5'd 6:	begin oled_clk <= HIGH; end
							5'd 7:	begin oled_clk <= LOW; oled_dat <= char_reg[4]; end
							5'd 8:	begin oled_clk <= HIGH; end
							5'd 9:	begin oled_clk <= LOW; oled_dat <= char_reg[3]; end
							5'd10:	begin oled_clk <= HIGH; end
							5'd11:	begin oled_clk <= LOW; oled_dat <= char_reg[2]; end
							5'd12:	begin oled_clk <= HIGH; end
							5'd13:	begin oled_clk <= LOW; oled_dat <= char_reg[1]; end
							5'd14:	begin oled_clk <= HIGH; end
							5'd15:	begin oled_clk <= LOW; oled_dat <= char_reg[0]; end	//后发低位数据
							5'd16:	begin oled_clk <= HIGH; end
							5'd17:	begin oled_csn <= HIGH; state <= DELAY; end	//
							default: state <= IDLE;
						endcase
					end
				DELAY:begin	//延时状态
						if(cnt_delay >= num_delay) begin
							cnt_delay <= 16'd0; state <= state_back; 
						end else cnt_delay <= cnt_delay + 1'b1;
					end
				default:state <= IDLE;
			endcase
		end
	end
	
	//OLED配置指令数据
	always@(posedge rst_n)
		begin
			cmd[0 ] = {8'hae}; 
			cmd[1 ] = {8'hd5}; 
			cmd[2 ] = {8'h80}; 
			cmd[3 ] = {8'ha8}; 
			cmd[4 ] = {8'h3f}; 
			cmd[5 ] = {8'hd3}; 
			cmd[6 ] = {8'h00}; 
			cmd[7 ] = {8'h40}; 
			cmd[8 ] = {8'h8d}; 
			cmd[9 ] = {8'h14}; 
			cmd[10] = {8'h20}; 
			cmd[11] = {8'h02};
			cmd[12] = {8'hc8};
			cmd[13] = {8'ha1};
			cmd[14] = {8'hda};
			cmd[15] = {8'h12};
			cmd[16] = {8'h81};
			cmd[17] = {8'hcf};
			cmd[18] = {8'hd9};
			cmd[19] = {8'hf1};
			cmd[20] = {8'hdb};
			cmd[21] = {8'h40};
			cmd[22] = {8'haf};
			
		end 
		
	//5*8点阵字库数据
	always@(posedge rst_n)
		begin
			mem[  0] = {8'h3E, 8'h51, 8'h49, 8'h45, 8'h3E};   // 48  0
			mem[  1] = {8'h00, 8'h42, 8'h7F, 8'h40, 8'h00};   // 49  1
			mem[  2] = {8'h42, 8'h61, 8'h51, 8'h49, 8'h46};   // 50  2
			mem[  3] = {8'h21, 8'h41, 8'h45, 8'h4B, 8'h31};   // 51  3
			mem[  4] = {8'h18, 8'h14, 8'h12, 8'h7F, 8'h10};   // 52  4
			mem[  5] = {8'h27, 8'h45, 8'h45, 8'h45, 8'h39};   // 53  5
			mem[  6] = {8'h3C, 8'h4A, 8'h49, 8'h49, 8'h30};   // 54  6
			mem[  7] = {8'h01, 8'h71, 8'h09, 8'h05, 8'h03};   // 55  7
			mem[  8] = {8'h36, 8'h49, 8'h49, 8'h49, 8'h36};   // 56  8
			mem[  9] = {8'h06, 8'h49, 8'h49, 8'h29, 8'h1E};   // 57  9
			mem[ 10] = {8'h7C, 8'h12, 8'h11, 8'h12, 8'h7C};   // 65  A
			mem[ 11] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h36};   // 66  B
			mem[ 12] = {8'h3E, 8'h41, 8'h41, 8'h41, 8'h22};   // 67  C
			mem[ 13] = {8'h7F, 8'h41, 8'h41, 8'h22, 8'h1C};   // 68  D
			mem[ 14] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h41};   // 69  E
			mem[ 15] = {8'h7F, 8'h09, 8'h09, 8'h09, 8'h01};   // 70  F

			mem[ 32] = {8'h00, 8'h00, 8'h00, 8'h00, 8'h00};   // 32  sp 
			mem[ 33] = {8'h00, 8'h00, 8'h2f, 8'h00, 8'h00};   // 33  !  
			mem[ 34] = {8'h00, 8'h07, 8'h00, 8'h07, 8'h00};   // 34  
			mem[ 35] = {8'h14, 8'h7f, 8'h14, 8'h7f, 8'h14};   // 35  #
			mem[ 36] = {8'h24, 8'h2a, 8'h7f, 8'h2a, 8'h12};   // 36  $
			mem[ 37] = {8'h62, 8'h64, 8'h08, 8'h13, 8'h23};   // 37  %
			mem[ 38] = {8'h36, 8'h49, 8'h55, 8'h22, 8'h50};   // 38  &
			mem[ 39] = {8'h00, 8'h05, 8'h03, 8'h00, 8'h00};   // 39  '
			mem[ 40] = {8'h00, 8'h1c, 8'h22, 8'h41, 8'h00};   // 40  (
			mem[ 41] = {8'h00, 8'h41, 8'h22, 8'h1c, 8'h00};   // 41  )
			mem[ 42] = {8'h14, 8'h08, 8'h3E, 8'h08, 8'h14};   // 42  *
			mem[ 43] = {8'h08, 8'h08, 8'h3E, 8'h08, 8'h08};   // 43  +
			mem[ 44] = {8'h00, 8'h00, 8'hA0, 8'h60, 8'h00};   // 44  ,
			mem[ 45] = {8'h08, 8'h08, 8'h08, 8'h08, 8'h08};   // 45  -
			mem[ 46] = {8'h00, 8'h60, 8'h60, 8'h00, 8'h00};   // 46  .
			mem[ 47] = {8'h20, 8'h10, 8'h08, 8'h04, 8'h02};   // 47  /
			mem[ 48] = {8'h3E, 8'h51, 8'h49, 8'h45, 8'h3E};   // 48  0
			mem[ 49] = {8'h00, 8'h42, 8'h7F, 8'h40, 8'h00};   // 49  1
			mem[ 50] = {8'h42, 8'h61, 8'h51, 8'h49, 8'h46};   // 50  2
			mem[ 51] = {8'h21, 8'h41, 8'h45, 8'h4B, 8'h31};   // 51  3
			mem[ 52] = {8'h18, 8'h14, 8'h12, 8'h7F, 8'h10};   // 52  4
			mem[ 53] = {8'h27, 8'h45, 8'h45, 8'h45, 8'h39};   // 53  5
			mem[ 54] = {8'h3C, 8'h4A, 8'h49, 8'h49, 8'h30};   // 54  6
			mem[ 55] = {8'h01, 8'h71, 8'h09, 8'h05, 8'h03};   // 55  7
			mem[ 56] = {8'h36, 8'h49, 8'h49, 8'h49, 8'h36};   // 56  8
			mem[ 57] = {8'h06, 8'h49, 8'h49, 8'h29, 8'h1E};   // 57  9
			mem[ 58] = {8'h00, 8'h36, 8'h36, 8'h00, 8'h00};   // 58  :
			mem[ 59] = {8'h00, 8'h56, 8'h36, 8'h00, 8'h00};   // 59  ;
			mem[ 60] = {8'h08, 8'h14, 8'h22, 8'h41, 8'h00};   // 60  <
			mem[ 61] = {8'h14, 8'h14, 8'h14, 8'h14, 8'h14};   // 61  =
			mem[ 62] = {8'h00, 8'h41, 8'h22, 8'h14, 8'h08};   // 62  >
			mem[ 63] = {8'h02, 8'h01, 8'h51, 8'h09, 8'h06};   // 63  ?
			mem[ 64] = {8'h32, 8'h49, 8'h59, 8'h51, 8'h3E};   // 64  @
			mem[ 65] = {8'h7C, 8'h12, 8'h11, 8'h12, 8'h7C};   // 65  A
			mem[ 66] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h36};   // 66  B
			mem[ 67] = {8'h3E, 8'h41, 8'h41, 8'h41, 8'h22};   // 67  C
			mem[ 68] = {8'h7F, 8'h41, 8'h41, 8'h22, 8'h1C};   // 68  D
			mem[ 69] = {8'h7F, 8'h49, 8'h49, 8'h49, 8'h41};   // 69  E
			mem[ 70] = {8'h7F, 8'h09, 8'h09, 8'h09, 8'h01};   // 70  F
			mem[ 71] = {8'h3E, 8'h41, 8'h49, 8'h49, 8'h7A};   // 71  G
			mem[ 72] = {8'h7F, 8'h08, 8'h08, 8'h08, 8'h7F};   // 72  H
			mem[ 73] = {8'h00, 8'h41, 8'h7F, 8'h41, 8'h00};   // 73  I
			mem[ 74] = {8'h20, 8'h40, 8'h41, 8'h3F, 8'h01};   // 74  J
			mem[ 75] = {8'h7F, 8'h08, 8'h14, 8'h22, 8'h41};   // 75  K
			mem[ 76] = {8'h7F, 8'h40, 8'h40, 8'h40, 8'h40};   // 76  L
			mem[ 77] = {8'h7F, 8'h02, 8'h0C, 8'h02, 8'h7F};   // 77  M
			mem[ 78] = {8'h7F, 8'h04, 8'h08, 8'h10, 8'h7F};   // 78  N
			mem[ 79] = {8'h3E, 8'h41, 8'h41, 8'h41, 8'h3E};   // 79  O
			mem[ 80] = {8'h7F, 8'h09, 8'h09, 8'h09, 8'h06};   // 80  P
			mem[ 81] = {8'h3E, 8'h41, 8'h51, 8'h21, 8'h5E};   // 81  Q
			mem[ 82] = {8'h7F, 8'h09, 8'h19, 8'h29, 8'h46};   // 82  R
			mem[ 83] = {8'h46, 8'h49, 8'h49, 8'h49, 8'h31};   // 83  S
			mem[ 84] = {8'h01, 8'h01, 8'h7F, 8'h01, 8'h01};   // 84  T
			mem[ 85] = {8'h3F, 8'h40, 8'h40, 8'h40, 8'h3F};   // 85  U
			mem[ 86] = {8'h1F, 8'h20, 8'h40, 8'h20, 8'h1F};   // 86  V
			mem[ 87] = {8'h3F, 8'h40, 8'h38, 8'h40, 8'h3F};   // 87  W
			mem[ 88] = {8'h63, 8'h14, 8'h08, 8'h14, 8'h63};   // 88  X
			mem[ 89] = {8'h07, 8'h08, 8'h70, 8'h08, 8'h07};   // 89  Y
			mem[ 90] = {8'h61, 8'h51, 8'h49, 8'h45, 8'h43};   // 90  Z
			mem[ 91] = {8'h00, 8'h7F, 8'h41, 8'h41, 8'h00};   // 91  [
			mem[ 92] = {8'h55, 8'h2A, 8'h55, 8'h2A, 8'h55};   // 92  .
			mem[ 93] = {8'h00, 8'h41, 8'h41, 8'h7F, 8'h00};   // 93  ]
			mem[ 94] = {8'h04, 8'h02, 8'h01, 8'h02, 8'h04};   // 94  ^
			mem[ 95] = {8'h40, 8'h40, 8'h40, 8'h40, 8'h40};   // 95  _
			mem[ 96] = {8'h00, 8'h01, 8'h02, 8'h04, 8'h00};   // 96  '
			mem[ 97] = {8'h20, 8'h54, 8'h54, 8'h54, 8'h78};   // 97  a
			mem[ 98] = {8'h7F, 8'h48, 8'h44, 8'h44, 8'h38};   // 98  b
			mem[ 99] = {8'h38, 8'h44, 8'h44, 8'h44, 8'h20};   // 99  c
			mem[100] = {8'h38, 8'h44, 8'h44, 8'h48, 8'h7F};   // 100 d
			mem[101] = {8'h38, 8'h54, 8'h54, 8'h54, 8'h18};   // 101 e
			mem[102] = {8'h08, 8'h7E, 8'h09, 8'h01, 8'h02};   // 102 f
			mem[103] = {8'h18, 8'hA4, 8'hA4, 8'hA4, 8'h7C};   // 103 g
			mem[104] = {8'h7F, 8'h08, 8'h04, 8'h04, 8'h78};   // 104 h
			mem[105] = {8'h00, 8'h44, 8'h7D, 8'h40, 8'h00};   // 105 i
			mem[106] = {8'h40, 8'h80, 8'h84, 8'h7D, 8'h00};   // 106 j
			mem[107] = {8'h7F, 8'h10, 8'h28, 8'h44, 8'h00};   // 107 k
			mem[108] = {8'h00, 8'h41, 8'h7F, 8'h40, 8'h00};   // 108 l
			mem[109] = {8'h7C, 8'h04, 8'h18, 8'h04, 8'h78};   // 109 m
			mem[110] = {8'h7C, 8'h08, 8'h04, 8'h04, 8'h78};   // 110 n
			mem[111] = {8'h38, 8'h44, 8'h44, 8'h44, 8'h38};   // 111 o
			mem[112] = {8'hFC, 8'h24, 8'h24, 8'h24, 8'h18};   // 112 p
			mem[113] = {8'h18, 8'h24, 8'h24, 8'h18, 8'hFC};   // 113 q
			mem[114] = {8'h7C, 8'h08, 8'h04, 8'h04, 8'h08};   // 114 r
			mem[115] = {8'h48, 8'h54, 8'h54, 8'h54, 8'h20};   // 115 s
			mem[116] = {8'h04, 8'h3F, 8'h44, 8'h40, 8'h20};   // 116 t
			mem[117] = {8'h3C, 8'h40, 8'h40, 8'h20, 8'h7C};   // 117 u
			mem[118] = {8'h1C, 8'h20, 8'h40, 8'h20, 8'h1C};   // 118 v
			mem[119] = {8'h3C, 8'h40, 8'h30, 8'h40, 8'h3C};   // 119 w
			mem[120] = {8'h44, 8'h28, 8'h10, 8'h28, 8'h44};   // 120 x
			mem[121] = {8'h1C, 8'hA0, 8'hA0, 8'hA0, 8'h7C};   // 121 y
			mem[122] = {8'h44, 8'h64, 8'h54, 8'h4C, 8'h44};   // 122 z
		end


		
	//16*16	汉字
		always@(posedge rst_n)
		begin
			mem_hanzi[ 0 ] = {8'h04,8'h84,8'hE4,8'h5C,8'h44,8'hC4,8'h00,8'hF2,8'h92,8'h92,8'hFE,8'h92,8'h92,8'hF2,8'h02,8'h00};
			mem_hanzi[ 1 ] = {8'h02,8'h01,8'h7F,8'h10,8'h10,8'h3F,8'h80,8'h8F,8'h54,8'h24,8'h5F,8'h44,8'h84,8'h87,8'h80,8'h00};//"硬",0
			mem_hanzi[ 2 ] = {8'h00,8'h40,8'h44,8'h44,8'h44,8'h44,8'hC4,8'hFC,8'hC2,8'h42,8'h42,8'h43,8'h42,8'h40,8'h00,8'h00};
			mem_hanzi[ 3 ] = {8'h20,8'h20,8'h10,8'h08,8'h04,8'h03,8'h00,8'hFF,8'h00,8'h03,8'h04,8'h08,8'h10,8'h20,8'h20,8'h00};//"禾",1
			mem_hanzi[ 4 ] = {8'h40,8'h30,8'h11,8'h96,8'h90,8'h90,8'h91,8'h96,8'h90,8'h90,8'h98,8'h14,8'h13,8'h50,8'h30,8'h00};
			mem_hanzi[ 5 ] = {8'h04,8'h04,8'h04,8'h04,8'h04,8'h44,8'h84,8'h7E,8'h06,8'h05,8'h04,8'h04,8'h04,8'h04,8'h04,8'h00};//"学",2
			mem_hanzi[ 6 ] = {8'h20,8'h18,8'h08,8'hEA,8'h2C,8'h28,8'h28,8'h2F,8'h28,8'h28,8'h2C,8'hEA,8'h08,8'h28,8'h18,8'h00};
			mem_hanzi[ 7 ] = {8'h40,8'h40,8'h48,8'h49,8'h49,8'h49,8'h49,8'h7F,8'h49,8'h49,8'h49,8'h49,8'h48,8'h40,8'h40,8'h00};//"堂",3
			
			//此处可以导入需要的字模
			
		end 
	/*汉字:硬禾学堂
	以汉字“硬禾学堂”RAM生成步骤为例:
	1、阴码、列行式、逆向 生成字模
	2、然后把生成的字模作为RAM的元素
	*/
endmodule

lut:

module lut(
	input [7:0] address,
	output reg [9:0] cos
);

wire [1:0] section;
reg [5:0] lut_address;
reg [8:0] lut_cos;
assign section = address[7:6]; //Get the sections of cos wave to reduce memory

always@(address)begin
	case(section)
		2'b00: begin
					lut_address = address[5:0];
					cos = 9'h1ff + lut_cos;
			   end
		2'b01: begin
					lut_address = ~address[5:0];
					cos = 9'h1ff + lut_cos;
			   end
		2'b10: begin
					lut_address = address[5:0];
					cos = 9'h1ff - lut_cos;
			   end
		2'b11: begin
					lut_address = ~address[5:0];
					cos = 9'h1ff - lut_cos;
			   end			   
	endcase
end

always @(lut_address) begin
	case(lut_address)	
      6'h0: lut_cos=9'h0;
      6'h1: lut_cos=9'hC;
      6'h2: lut_cos=9'h19;
      6'h3: lut_cos=9'h25;
      6'h4: lut_cos=9'h32;
      6'h5: lut_cos=9'h3E;
      6'h6: lut_cos=9'h4B;
      6'h7: lut_cos=9'h57;
      6'h8: lut_cos=9'h63;
      6'h9: lut_cos=9'h70;
      6'ha: lut_cos=9'h7C;
      6'hb: lut_cos=9'h88;
      6'hc: lut_cos=9'h94;
      6'hd: lut_cos=9'hA0;
      6'he: lut_cos=9'hAC;
      6'hf: lut_cos=9'hB8;
      6'h10: lut_cos=9'hC3;
      6'h11: lut_cos=9'hCF;
      6'h12: lut_cos=9'hDA;
      6'h13: lut_cos=9'hE6;
      6'h14: lut_cos=9'hF1;
      6'h15: lut_cos=9'hFC;
      6'h16: lut_cos=9'h107;
      6'h17: lut_cos=9'h111;
      6'h18: lut_cos=9'h11C;
      6'h19: lut_cos=9'h126;
      6'h1a: lut_cos=9'h130;
      6'h1b: lut_cos=9'h13A;
      6'h1c: lut_cos=9'h144;
      6'h1d: lut_cos=9'h14E;
      6'h1e: lut_cos=9'h157;
      6'h1f: lut_cos=9'h161;
      6'h20: lut_cos=9'h16A;
      6'h21: lut_cos=9'h172;
      6'h22: lut_cos=9'h17B;
      6'h23: lut_cos=9'h183;
      6'h24: lut_cos=9'h18B;
      6'h25: lut_cos=9'h193;
      6'h26: lut_cos=9'h19B;
      6'h27: lut_cos=9'h1A2;
      6'h28: lut_cos=9'h1A9;
      6'h29: lut_cos=9'h1B0;
      6'h2a: lut_cos=9'h1B7;
      6'h2b: lut_cos=9'h1BD;
      6'h2c: lut_cos=9'h1C3;
      6'h2d: lut_cos=9'h1C9;
      6'h2e: lut_cos=9'h1CE;
      6'h2f: lut_cos=9'h1D4;
      6'h30: lut_cos=9'h1D9;
      6'h31: lut_cos=9'h1DD;
      6'h32: lut_cos=9'h1E2;
      6'h33: lut_cos=9'h1E6;
      6'h34: lut_cos=9'h1E9;
      6'h35: lut_cos=9'h1ED;
      6'h36: lut_cos=9'h1F0;
      6'h37: lut_cos=9'h1F3;
      6'h38: lut_cos=9'h1F6;
      6'h39: lut_cos=9'h1F8;
      6'h3a: lut_cos=9'h1FA;
      6'h3b: lut_cos=9'h1FC;
      6'h3c: lut_cos=9'h1FD;
      6'h3d: lut_cos=9'h1FE;
      6'h3e: lut_cos=9'h1FF;
      6'h3f: lut_cos=9'h1FF;
   endcase
end

endmodule

encoder:

module encoder(
	input sys_clk,
	input sys_rst_n,
	input encoder_a,
	input encoder_b,
	input encoder_s,
	
	output reg encoder_left,
	output reg encoder_right,
	output reg encoder_ok
);

parameter CNT_20MS_MAX = 240_000; //To scan keys
parameter CNT_1MS_MAX = 12_000; //To get 1k sample rate 

//To D-reg the S input to sync data
reg r_encoder_s;
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		r_encoder_s <= 1'b0;
	end else begin
		r_encoder_s <= encoder_s;
	end
end

//To provide 20ms counter to filter keys
reg [19:0] cnt_20ms;
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		cnt_20ms <= 20'd0;
	end else if(encoder_s == 1'b0)begin
		cnt_20ms <= 20'd0;
	end else if(cnt_20ms == CNT_20MS_MAX - 1 && encoder_s == 1'b1)begin
		cnt_20ms <= cnt_20ms;
	end else begin
		cnt_20ms <= cnt_20ms + 1'b1;
	end
end
//To provide 1 clock cycle signal
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		encoder_ok <= 1'b0;
	end else if(cnt_20ms == CNT_20MS_MAX - 2)begin
		encoder_ok <= 1'b1;
	end else begin
		encoder_ok <= 1'b0;
	end
end

//The counter of 1k signal
reg [15:0] cnt_1ms;
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		cnt_1ms <= 16'd0;
	end else if(cnt_1ms == CNT_1MS_MAX - 1)begin
		cnt_1ms <= 16'd0;
	end else begin
		cnt_1ms <= cnt_1ms + 1'b1;
	end
end

//To D-reg the A&B input to sync data using 1k clock
reg r_encoder_a,rr_encoder_a;
reg r_encoder_b,rr_encoder_b;
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		r_encoder_a <= 1'b0;
		r_encoder_b <= 1'b0;
		rr_encoder_a <= 1'b0;
		rr_encoder_b <= 1'b0;
	end else if(cnt_1ms == CNT_1MS_MAX - 1)begin
		r_encoder_a <= encoder_a;
		r_encoder_b <= encoder_b;
		rr_encoder_a <= r_encoder_a;
		rr_encoder_b <= r_encoder_b;
	end
end

wire state_a = encoder_a && r_encoder_a && rr_encoder_a;
wire state_b = encoder_b && r_encoder_b && rr_encoder_b;
reg r_state_a;
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		r_state_a <= 1'b0;
	end else begin
		r_state_a <= state_a;
	end
end

//To get the rise_edge and fall_edge
wire encoder_a_rise;
wire encoder_a_fall;
assign encoder_a_rise = (r_state_a | state_a)&(r_state_a == 1'b0);
assign encoder_a_fall = (r_state_a | state_a)&(state_a == 1'b0);
always@(posedge sys_clk or negedge sys_rst_n)begin
	if(!sys_rst_n)begin
		encoder_left <= 1'b0;
		encoder_right <= 1'b0;
	end else if((encoder_a_rise && rr_encoder_b)||(encoder_a_fall && !rr_encoder_b))begin
		encoder_left <= 1'b1;
		encoder_right <= 1'b0;
	end else if((encoder_a_fall && rr_encoder_b)||(encoder_a_rise && !rr_encoder_b))begin
		encoder_right <= 1'b1;
		encoder_left <= 1'b0;
	end else begin
		encoder_left <= 1'b0;
		encoder_right <= 1'b0;
	end
end

endmodule


此项目所占用FPGA内部资源报告:


Design Information

Command line:   map -a MachXO2 -p LCMXO2-4000HC -t CSBGA132 -s 4 -oc Commercial
     dds_freq_meter_impl1.ngd -o dds_freq_meter_impl1_map.ncd -pr
     dds_freq_meter_impl1.prf -mp dds_freq_meter_impl1.mrp -lpf C:/Users/10943/D
     esktop/DDS/XO2-4000HC/project/impl1/dds_freq_meter_impl1_synplify.lpf -lpf
     C:/Users/10943/Desktop/DDS/XO2-4000HC/project/dds_freq_meter.lpf -c 0 -gui
     
Target Vendor:  LATTICE
Target Device:  LCMXO2-4000HCCSBGA132
Target Performance:   4
Mapper:  xo2c00,  version:  Diamond (64-bit) 3.12.0.240.2
Mapped on:  02/25/22  20:31:14


Design Summary
   Number of registers:    355 out of  4635 (8%)
      PFU registers:          349 out of  4320 (8%)
      PIO registers:            6 out of   315 (2%)
   Number of SLICEs:       761 out of  2160 (35%)
      SLICEs as Logic/ROM:    761 out of  2160 (35%)
      SLICEs as RAM:            0 out of  1620 (0%)
      SLICEs as Carry:        154 out of  2160 (7%)
   Number of LUT4s:        1515 out of  4320 (35%)
      Number used as logic LUTs:        1207
      Number used as distributed RAM:     0
      Number used as ripple logic:      308
      Number used as shift registers:     0
   Number of PIO sites used: 20 + 4(JTAG) out of 105 (23%)
   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:  1 out of 2 (50%)
   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:  3
     Net in_clk_c: 1 loads, 1 rising, 0 falling (Driver: PIO in_clk )
     Net sys_clk: 170 loads, 170 rising, 0 falling (Driver: u_pll/PLLInst_0 )

     Net dac_clk_c: 31 loads, 31 rising, 0 falling (Driver: u_pll/PLLInst_0 )
   Number of Clock Enables:  19
     Net u_oled12864.un1_state_22_i: 1 loads, 0 LSLICEs
     Net u_encoder.cnt_1ms8: 3 loads, 1 LSLICEs
     Net u_oled12864.N_827_i: 1 loads, 0 LSLICEs
     Net u_oled12864/N_820_i: 1 loads, 1 LSLICEs
     Net u_oled12864/u_bcd_8421/unit5: 8 loads, 8 LSLICEs
     Net u_oled12864/u_bcd_8421/M_0_sqmuxa: 4 loads, 4 LSLICEs
     Net u_oled12864/u_bcd_8421/un4_i: 27 loads, 27 LSLICEs
     Net u_oled12864/state[6]: 3 loads, 3 LSLICEs
     Net u_oled12864/N_906_i: 3 loads, 3 LSLICEs
     Net u_oled12864.un1_state_54_i: 5 loads, 4 LSLICEs
     Net u_oled12864/un1_state_62_i: 2 loads, 2 LSLICEs
     Net u_oled12864/N_355: 31 loads, 31 LSLICEs
     Net u_oled12864/nume: 4 loads, 4 LSLICEs
     Net u_oled12864/N_872_i: 3 loads, 3 LSLICEs
     Net u_oled12864/N_229_i: 3 loads, 3 LSLICEs
     Net u_oled12864/N_230_i: 2 loads, 2 LSLICEs
     Net u_oled12864/cnt_delaye: 8 loads, 8 LSLICEs
     Net un1_state_53_0: 1 loads, 0 LSLICEs
     Net u_encoder/cnt_20mse: 11 loads, 11 LSLICEs
   Number of LSRs:  3
     Net encoder_a_c: 1 loads, 1 LSLICEs
     Net type_ctrl[0]: 1 loads, 1 LSLICEs
     Net u_encoder/cnt_20ms[16]: 1 loads, 1 LSLICEs
   Number of nets driven by tri-state buffers:  0
   Top 10 highest fanout non-clock nets:
     Net u_oled12864/N_1_i: 214 loads
     Net u_oled12864/N_4_i: 201 loads
     Net u_oled12864/N_476: 185 loads
     Net u_oled12864/N_1_i_0: 159 loads
     Net u_oled12864/N_477: 138 loads
     Net u_oled12864/num[4]: 73 loads
     Net u_oled12864/N_478: 67 loads
     Net u_oled12864/state[0]: 62 loads
     Net u_oled12864/state[1]: 57 loads
     Net u_oled12864/u_bcd_8421/shift_flag: 56 loads




   Number of warnings:  0
   Number of errors:    0
     



遇到的主要难题及解决方法:

由于是第一次接触FPGA,花了一些时间去学习Verilog HDL语言,去学习相关开发软件diamond的使用,学习FPGA的主要开发流程。深深体会到了FPGA的强大,逻辑上的错误可能导致非常严重的结果。

未来的计划或建议:

继续更加深入地学习了解FPGA领域、嵌入式领域相关的知识,可以独立的完成更多有趣、有意义的项目。

 

附件下载
DDS (2).zip
团队介绍
团队成员
damie_EE
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号