实验 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,即Q4,IN2=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,即Q4,IN2=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实验原理:
输出频率公式:f=