4.探索定点数+DDS

本文详述了定点数的二补码运算,包括不同长度整数的加法和乘法,以及带小数位的乘加运算,并通过实验进行验证。同时,探讨了DDS(直接数字频率合成)原理,利用SignalTap和Matlab进行仿真分析,设计了一个DDS电路,输出频率为1MHz,并在Matlab中进行了频谱分析。
摘要由CSDN通过智能技术生成

实验 1. 探索定点数

  • 使用二进制表示数字,是计算机科学中最基本的问题之一。
  • 使用FPGA进行数学运算,本质上就是要把数学模型、公式,映射成数字电路。
  • 用FPGA实现定点数运算,对于设计运算单元电路很重要。
  • 请自行设计若干实验,实现和验证课堂上讲过的关于定点数的知识,例如:
    • 2补码的溢出回绕特性
    • 不同长度的2补码数据进行运算时,先进行符号扩展和数据对齐,然后再进行加、减法运算
  • 乘法和加法对字长的影响,验证2补码整数的乘法和加法运算
  • 定点数实验,验证带小数位的定点数的乘加运算
  • 仿真工具,可以使用Modelsim,或是Quartus的波形仿真,也可以使用Matlab辅助
  • 仿真验证通过之后,在Quartus里面编译一下电路,关注你的电路消耗了多少FPGA资源,这是很有用的经验
  • 请把完成的所有实验内容写在一篇博客里,文档尽量条理清楚,便于教师阅读

实验1.1 验证不同长度的2补码整数的乘法和加法运算

实验原理:

  • 整个实验共有三个模块组成:
    • 第一个模块 cnt_0to7是无符号型计数器,字长为3bit,用于实现计数值CNT1从0到7;
    • 第二个模块 cnt_fu7to7是有符号型计数器,字长为4bit,用于实现计数值CNT2从-7到7;
    • 第三个模块adder_cnt是一个加法器和乘法器模块,为防止溢出,加法器和乘法器的字长分别设置为5bit和 8bit,加法器和乘法器的两个输入信号分别是上面两个计数器的输出信号,但是由于计数器CNT1是无符号型,计数器CNT2是有符号型,且两个计数器的计数值字长不同,因此在adder_cnt模块中首先要进行符号扩展,并且对加法器和乘法器的输入信号重新定义为有符号型,并通过对模块一和模块二的例化构成加法器和乘法器的输入信号。
实验代码
//模块一(实现0to7计数)///
module  cnt_0to7(
CLK_1,//时钟,上升沿有效
EN_1,//输入的计数使能,高有效
CNT1);//输出的计数值信号

input CLK_1;
input  EN_1;
output [2:0] CNT1;


reg [2:0] CNT1;
reg [2:0] MAX_CNT=7;

always @ (posedge CLK_1)
begin
         if(EN_1) begin//使能信号开启,执行计数功能
                if(CNT1 < MAX_CNT)
                 CNT1 <= CNT1 +1'b1;
                else begin
                   CNT1 <= 0;//计数到最大值,下一计数值清零                        
                end
            end
           else begin
                CNT1 <= CNT1 ;//当使能信号无效时,计数值保持不变
         end

end
endmodule

//模块二(实现-7to7计数)///
module  cnt_fu7to7(
CLK_2,//时钟,上升沿有效
EN_2,//输入的计数使能,高有效
CNT2);//输出的计数值信号

parameter [3:0] MAX_CNT=4'b0111; 

input CLK_2;
input  EN_2;
output signed[3:0] CNT2;

reg signed [3:0] CNT2 = 4'b1001;


always @ (posedge CLK_2)
begin
         if(EN_2) begin//使能信号开启,执行计数功能
                if(CNT2 == MAX_CNT)    
                 CNT2 <= 1001;   
                else begin
                   //计数到最大值,下一计数值清零
                     CNT2 <= CNT2 + 4'b0001; 
              end                
            end
           else begin
                CNT2 <= CNT2 ;//当使能信号无效时,计数值保持不变
         end

end
endmodule

//模块三(加法器和乘法器)///
module  adder_cnt(
CLK,
EN,
sum,//求和
product);//求积

input CLK;
input EN;
output signed[4:0] sum;
output signed[7:0] product;

reg signed [4:0] sum;
reg signed [7:0] product;
//计数器CNT1是无符号型,CNT2是有符号性,要使两个计数器的的输出值相加必须都定义为有符号性,因此在此模块中重新定义并且调用计数器
wire signed [2:0] CNT_1; 
wire signed [3:0] CNT_2; 

对模块cnt_0to7进行调用//
cnt_0to7 cnt_0to7_signed_1
(CLK,
 EN,
 CNT_1
);

对模块cnt_fu7to7进行调用//
cnt_fu7to7 cnt_fu7to7_signed_2
(CLK,
 EN,
 CNT_2
);

always @ (CNT_1 or CNT_2)
begin  
   if(EN) begin 
       sum <= {
  {CNT_2[3]},CNT_2} + {
  {
  2{
  1'b0}},CNT_1};
         if(CNT_2[3] == 1) 
            product <= {
  {
  4{
  1'b1}}, {
  {
  1'b0},CNT_1} * CNT_2};
         else
             product <= {
  {
  1'b0},CNT_1} * CNT_2;
    end
    else begin
       sum <= sum;
        product <= product;
    end

end
endmodule
SignalTap 仿真分析:

注:sum 和 product 的输出显示方式均为 signed Decimal in Two’s Complement

这里写图片描述


实验1.2 验证带小数位的定点数的乘加运算

(1)定点小数加法
实验原理:

    对于定点数运算,由于小数点的位置是固定的,所以就没有必要储存它,既然没有储存小数点的位置,那么计算机就不知道小数点的位置,所以这个小数点的位置是我们写程序的人要自己牢记的。
   首先定义两个8bit的常量IN1(4.4)和 IN2(4.4),其中整数位和小数位均为4bit,即IN1=00100001(0010.0001),IN2=00111010(0011.1010),SUM=IN1+IN2。

实验代码
/////////定点小数加法/////////////
module adder(
CLK,
SUM);

parameter IN1 = 8'b00100100; // 定义一个8bit的小数0010.0001,整数位和小数位均为4bit,即Q4,IN1=2.25
parameter IN2 = 8'b00111100; // 定义一个8bit的小数0011.1010,整数位和小数位均为4bit,即Q4IN2=3.75

input CLK;
output [7:0] SUM;

assign  SUM = IN1 + IN2;
endmodule
SignalTap 仿真分析:

这里写图片描述

(2)定点小数乘法

实验原理:

   在定点小数乘法中,小数点会发生移动,需要对小数点的位置进行调整。但是既然做定点小数运算,那就说小数点的位置不能动,那就舍弃最低位,这样就得到正确的定点运算的结果了。所以在做定点小数运算时不仅需要牢记小数点的位置,我们把小数点之后有n位叫做Qn,而Q0 就是我们所说的整数。此外还需要记住表达定点小数的有效位数。
    在定点小数乘法的设计中,依然定义两个常量IN1(4.4)和 IN2(4.4) ,即为Q4,定义两个输出 product和product_R,其中product_R字长为16bit,用于显示输出的完整值,由于小数点的位置是不动的,所以将输出结果左移4位后赋给product_R,并且将product_R的低4位舍弃赋给product,而product的输出就是我们想要的结果。

实验代码

/////////定点小数乘法/////////////
module product(
CLK,
product,
product_R);

parameter IN1 = 8'b00100100; // 定义一个8bit的小数0010.0001,整数位和小数位均为4bit,即Q4,IN1=2.25
parameter IN2 = 8'b00111100; // 定义一个8bit的小数0011.1010,整数位和小数位均为4bit,即Q4IN2=3.75

input CLK;
output [7:0] product;
output [15:0] product_R;

reg [7:0] product;
reg [15:0] product_R;

always @ (posedge CLK)
begin
 product_R <= (IN1 * IN2) << 4;
 product <= {product_R[15:12],product_R[11:8]};
end

endmodule
SignalTap 仿真分析:

这里写图片描述


实验 2. 探索 DDS 和 EDA 工具

实验2.1 Signaltap 和 Matlab

实验要求:
建议设计如下:
  • 首先设计一个DDS, 50MHz的时钟速率,输出波形频率自行设定,输出数据格式为2补码
  • DDS的参数配置最好不要和老师给的例子相同
  • 首先在Signaltap里,观察波形的正确性,然后把Signaltap的数据导入到Matlab,分析频域结果
思考题:
  • 如何用 Matlab分析该正弦信号的频率
  • 上面你用的分析方法,其频率分析精度是多少?这个分析精度和那些参数有关系?
  • 如何能验证你的频率分析方法是正确的?我的意思是,假设你要生成1MHz的正弦波,但是实际上,你生成的正弦波的频率是错的,并且你的Matlab分析方法也不对,在这种情况下,即使你生成了正确频率的正弦波,你的分析方法也会告诉你频率不对。
实验设计:
  • 设计一个DDS, 50MHz的时钟速率 , 输出波形频率为1MHZ,输出数据格式为2补码
  • 相位累加器的位数N=32(相位累加器位数N一般为24~32位,因为N越大分辨率越高,故选择相位累加器位数为32位)
  • 频率字(FQWD)字长32位,波表ROM尺寸(RA)为 8bit地址,(RD)12bit进行量化
  • 每个CLK输出一个有效样点
DDS实验原理:

      输出频率公式:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值