EDA实验(Quartus Ⅱ+fpga) (六)--基于FPGA的LPM定制波形信号发生器

前言:
本文主要介绍了EDA原理与应用这门课程的相关实验及代码。使用的软件是Quartus Ⅱ,该实验使用fpga芯片为cycloneⅤ 5CSEMA5F31C6。

(一)实验目的

(1)学习复杂数字系统设计;
(2)学习用LPM(Library of Parameterized Modules 参数可设置模块库)进行设计;
(3)了解Verilog产生VGA显示时序的方法;
(4)学习用在线逻辑分析仪SignalTap观察FPGA产生的信号;
(5)培养工程思维及创新思维。

(二)实验要求

自选一个具有创意的数字系统综合应用题目,划分功能模块,设计调试完成。
以信号发生器设计为例------
基本设计要求(每个同学必须完成,独立验收考核)----LPM定制信号发生器:
(1)数字化波形数据存在ROM中,ROM用LPM进行设计;
(2)正弦波或方波、锯齿波波形可选并数码管显示所选波形种类;
(3)信号频率、幅度可调并用数码管显示频率和幅值;
(4)用SignalTap逻辑仪器观察信号波形。

(三)实验过程

1.首先我们安装下面给出的方法配置波形rom文件,方便调用。

rom元件配置方法

从上文可以看出,rom文件的地址代表波形的横坐标即时间,地址里面的内容代表波形的纵坐标即幅度。
因此我们只需要随时钟一个一个地址读过去即可将波形完整的读出来,并且通过修改每个时钟地址的增值变更波形的频率,修改读出地址内容的大小变更波形的幅度。

这儿我们配置好三种形式的波形,分别为正弦波、矩形波、梯形波,然后用顶层文件调用rom例化。

(四)实验仿真

使用modelsim仿真
在这里插入图片描述
更进一步,可以使用SignalTap II嵌入式逻辑分析仪实时查看FPGA输出波形。

(五)实验源码

5.1顶层模块LPM

//顶层模块代码
module LPM(
    input               clk,     /*时钟输入*/ 
    input               rst,      /*低电平置0*/
	input 		        tp,		//调节频率
	input 			    tf,		//调节幅度
	input			    mode_an,    //波形选择
    output reg [7:0]    q ,         /*输出*/    
	output reg [6:0]    SG0,SG1,SG2,SG3,SG4,SG5
);

/***************address generate***************/
wire [5:0]  addr;
wire [7:0]  q1,q2,q3;  //存放三种波形输出
wire tp_flag,tf_flag,mode_an_flag;//按键有效信号

reg [31:0]  cnt;
reg [31:0]  pin;
reg [3:0]   fu;
reg [1:0]	mode;
reg [5:0]	dp;
//幅度,频率调节
always@(posedge clk or negedge rst)
begin
    if(!rst)
       begin cnt <= 32'd0;pin<=32'h10000000;fu<=4'd1; dp<=6'd2;end
    else 
		 begin
			  cnt <= cnt+pin;  
			  if(tp_flag)//每按下一次调频按键,频率大/小一倍
					begin
						dp<=dp*2;pin<=pin<<1;
						if(dp==6'd4)
							dp<=6'd1;
						if(pin==32'h20000000)  
							pin<=32'h08000000;
					end
			  if(tf_flag)//每按下一次调幅按键,幅度大/小一倍
					begin
						fu<=fu<<1; 
						if(fu==8)
							fu<=4'd1;
					end
		end      
end
/***********ROM instance**********************/
assign  addr   = cnt[31:26] ;  //取高六位
//调用三种波形rom
rom_1  ROM_1(
				.address(addr),
				.clock(clk),
				.q(q1)
				);
rom_f  ROM_f(
				.address(addr),
				.clock(clk),
				.q(q2)
				);
rom_j  ROM_j(
				.address(addr),
				.clock(clk),
				.q(q3)
				);
//波形输出选择                
always@(posedge clk or negedge rst)
begin
	if(!rst)
		begin	
			mode<=0;
		end		
	else
		begin
			if(mode_an_flag)//每按下一次波形输出选择按键,改变波形
				begin
					mode<=mode+1;
					if(mode==3)
						mode<=0;
				end
			case(mode)
				0:	begin
						q<=q1*fu/5;
					end
				1:begin	
						q<=q2*fu/5;
					end
				2:begin
						q<=q3*fu/5;
				  end
				default begin mode<=0;q<=q1*fu/5; end
			endcase
		end
end

//按键输入
key key_inst0
(
	.sys_clk   (clk  )  ,
	.sys_rst_n (rst)  ,
	.key_in    (tp      )  ,
	.key_flag  (tp_flag)
);      
key key_inst1
(
	.sys_clk   (clk  )  ,
	.sys_rst_n (rst)  ,
	.key_in    (tf      )  ,
	.key_flag  (tf_flag)
);     
key key_inst2
(
	.sys_clk   (clk  )  ,
	.sys_rst_n (rst)  ,
	.key_in    (mode_an)  ,
	.key_flag  (mode_an_flag)
);                             
//数码管显示
wire [3:0] dpb,dps,dpg;
wire [3:0] dfs,dfg;
assign dpb=dp/100;assign dps=dp%100/10;assign dpg=dp%10;
assign dfs=fu/10;assign dfg=fu%10;
always@(posedge clk)
	begin
		case(mode)
            0:SG5<=7'b1000000; 1:SG5<=7'b1111001;
            2:SG5<=7'b0100100; 3:SG5<=7'b0110000;
            4:SG5<=7'b0011001; 5:SG5<=7'b0010010;
            6:SG5<=7'b0000010; 7:SG5<=7'b1111000;
            8:SG5<=7'b0000000; 9:SG5<=7'b0010000; //7段译码值
		endcase
		case(dpb)
			   0:SG4<=7'b1000000; 1:SG4<=7'b1111001;
            2:SG4<=7'b0100100; 3:SG4<=7'b0110000;
            4:SG4<=7'b0011001; 5:SG4<=7'b0010010;
            6:SG4<=7'b0000010; 7:SG4<=7'b1111000;
            8:SG4<=7'b0000000; 9:SG4<=7'b0010000; //7段译码值
		endcase
		case(dps)
			   0:SG3<=7'b1000000; 1:SG3<=7'b1111001;
            2:SG3<=7'b0100100; 3:SG3<=7'b0110000;
            4:SG3<=7'b0011001; 5:SG3<=7'b0010010;
            6:SG3<=7'b0000010; 7:SG3<=7'b1111000;
            8:SG3<=7'b0000000; 9:SG3<=7'b0010000; //7段译码值
			endcase
		case(dpg)
			   0:SG2<=7'b1000000; 1:SG2<=7'b1111001;
            2:SG2<=7'b0100100; 3:SG2<=7'b0110000;
            4:SG2<=7'b0011001; 5:SG2<=7'b0010010;
            6:SG2<=7'b0000010; 7:SG2<=7'b1111000;
            8:SG2<=7'b0000000; 9:SG2<=7'b0010000; //7段译码值
			endcase
		case(dfs)
			   0:SG1<=7'b1000000; 1:SG1<=7'b1111001;
            2:SG1<=7'b0100100; 3:SG1<=7'b0110000;
            4:SG1<=7'b0011001; 5:SG1<=7'b0010010;
            6:SG1<=7'b0000010; 7:SG1<=7'b1111000;
            8:SG1<=7'b0000000; 9:SG1<=7'b0010000; //7段译码值
			endcase
		case(dfg)
			   0:SG0<=7'b1000000; 1:SG0<=7'b1111001;
            2:SG0<=7'b0100100; 3:SG0<=7'b0110000;
            4:SG0<=7'b0011001; 5:SG0<=7'b0010010;
            6:SG0<=7'b0000010; 7:SG0<=7'b1111000;
            8:SG0<=7'b0000000; 9:SG0<=7'b0010000; //7段译码值
			endcase
	end

endmodule

5.2按键源码:


`timescale  1ns/1ns


//波动开关,只有key_in由0-1才会产生一个时钟高脉冲有效信号,即上升沿有效
module	key  
(
	input		sys_clk     ,
	input		sys_rst_n   ,
	input		key_in      ,
	output	reg	key_flag
);

reg key_now;
reg key_next;

always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
        key_now <= 1'd0;
    else
        key_now <= key_next;

always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		key_next<=1'b0;
	else	if(key_in)
		key_next<=1'b1;
	else
		key_next<=1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
	if(!sys_rst_n)
		key_flag<=1'b0;
	else	if((key_now==0)&&(key_next==1))
		key_flag<=1'b1;
	else
		key_flag<=1'b0;
		
endmodule

5.3仿真源码:


`timescale  1ns/1ns
module  tb_lpm();

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire  define
wire    [7:0]    q        ;/*输出*/ 
       
//reg   define
reg     sys_clk     ;
reg     sys_rst_n   ;
reg     tp   ;
reg     tf   ;
reg     mode_an   ;
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//sys_clk,sys_rst_n初始赋值,模拟触摸按键信号值
initial
    begin
        sys_clk       <=   1'b1 ;
        sys_rst_n    <=   1'b0 ;
        tp    <=   1'b0 ;
        tf    <=   1'b0 ;
        mode_an    <=   1'b0 ;
        #200
        sys_rst_n    <=   1'b1 ;
        #1000
        mode_an <= 1'b1 ;
        #100
        mode_an <= 1'b0 ;
        #1000
        mode_an <= 1'b1 ;
        #100
        mode_an <= 1'b0 ;
        #1000
        tf <= 1'b1 ;
        #100
        tf <= 1'b0 ;
        #1000
        tp <= 1'b1 ;
        #100
        tp <= 1'b0 ;
    end

//clk:产生时钟
always  #10 sys_clk = ~sys_clk ;

//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- touch_ctrl_led_inst -------------
LPM LPM_list(
    .clk    (sys_clk    )    ,     /*时钟输入*/ 
    .rst    (sys_rst_n   )    ,      /*低电平置0*/
	.tp     (tp     )    ,		//调节频率
	.tf     (tf     )    ,		//调节幅度
	.mode_an(mode_an)    , 
    .q      (q      )    /*输出*/ 
);

endmodule


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值