FPGA搭积木之复数乘法器以及ModelSim自动化仿真的技巧

目录

1.前言

在数字信号处理种复数乘法去使用的非常多,今天分享一个自己设计的复数乘法器,并将设计参数化,放入自己的代码库,供有需要时直接使用。相比于官方提供的封闭的IP核,自己设计的IP核虽然性能比不过,但是更灵活,方便进行个性化修改。FPGA其实就像搭积木一样,只要自己的代码库够丰富,设计只会越来越轻松!今天学习了在testbench中自动化对比仿真的技巧,对比错误将信息打印出来,方便回到波形中去查看,对比通过输出pass。

2.原理

两个复数相乘有:
C A ⋅ C B = ( a + b j ) ( c + d j ) C_A \cdot C_B = (a + bj)(c + dj) CA⋅CB=(a+bj)(c+dj) = ( a c − b d ) + ( a d + b c ) j =(ac - bd) + (ad + bc)j =(ac−bd)+(ad+bc)j

那么,
R e = a c − b d Re = ac - bd Re=ac−bd
I m = a d + b c Im = ad + bc Im=ad+bc

如果直接计算需要使用四个乘法器,外加两个加法器。为了减少资源使用:


m 1 = d ( a − b ) m_1 = d(a-b) m1=d(a−b)
m 2 = a ( c − d ) m_2 = a(c-d) m2=a(c−d)
m 3 = b ( c + d ) m_3 = b(c+d) m3=b(c+d)

代入上面式子可得
R e = a c − b d = m 1 + m 2 Re = ac - bd = m_1 + m_2 Re=ac−bd=m1+m2
I m = a d + b c = m 1 + m 3 Im = ad + bc = m_1 + m_3 Im=ad+bc=m1+m3

这样变换之后改为使用3个乘法器,5个加法器,相比减少了1个乘法器的使用,虽然多使用了3个加法器,但是3个加法器所消耗的资源远远不及一个乘法器。

电路结构如下:

3.代码

将设计参数化,形成自己的IP核,参考如下:

c 复制代码
module complexX #(

	parameter WIDTH1 = 16,
	parameter WIDTH2 = 16
	
)(
	input clk,
//输入(a+bj)(c+dj)	
	input signed	[WIDTH1-1:0]	a,
	input signed	[WIDTH1-1:0]	b,
	input signed	[WIDTH2-1:0]	c,
	input signed	[WIDTH2-1:0]	d,
	
	output  signed	[WIDTH1+WIDTH2-1:0]	Re,
	output  signed	[WIDTH1+WIDTH2-1:0]	Im 
    );
//m1 = d(a-b)
//m2 = a(c-d)
//m3 = b(c+d)
//Re = ac - bd = m1 + m2
//Im = ad + bc = m1 + m3
	wire	[WIDTH1:0]	aSb;
	wire	[WIDTH2:0]	cSd;
	wire	[WIDTH2:0]	cAd;
	
	reg 	[WIDTH1+WIDTH2-1:0]		m1 = 'd0;
	reg 	[WIDTH1+WIDTH2-1:0]		m2 = 'd0;
	reg 	[WIDTH1+WIDTH2-1:0]		m3 = 'd0;
	
	assign	aSb	= $signed(a) - $signed(b);
	assign	cSd	= $signed(c) - $signed(d);
	assign	cAd	= $signed(c) + $signed(d);
	
	always@(posedge clk)begin
		m1 <= $signed(d) * $signed(aSb);
		m2 <= $signed(a) * $signed(cSd);
		m3 <= $signed(b) * $signed(cAd);
	end
	
	assign	Re	= $signed(m1) + $signed(m2);
	assign	Im	= $signed(m1) + $signed(m3);
	
endmodule

4.仿真

编写仿真代码,遍历范围内的数据对乘法器进行验证。在testbench中有一些技巧可以提高仿真效率,自动化对比仿真,对比错误将信息打印出来再回到波形中去查看,对比通过输出pass。因为遍历16位宽的数据仿真时间太长,这里将参数改为4位。

c 复制代码
module complexX_tb;
parameter T = 10;
parameter WIDTH1 = 4;
parameter WIDTH2 = 4;
reg 							clk		;
reg 	signed	[WIDTH1 -1 : 0]			a,b		;
reg		signed	[WIDTH2 -1 : 0]			c,d		;
wire 	signed	[WIDTH1+WIDTH2-1 : 0]	Re,Im	;
     
complexX 
#(.WIDTH1(WIDTH1),	
  .WIDTH2(WIDTH2))
  u_complexX(
	.clk(clk),
	.a		(a	),
	.b		(b	),
	.c		(c	),
	.d		(d	),
	.Re		(Re	),
	.Im		(Im	)
);

always #(T/2) clk = ~clk;

reg signed	[WIDTH1 -1 : 0]		i;
reg signed	[WIDTH2 -1 : 0]		j;

initial begin
	clk = 1'b0;
	#(10*T);
    for(i = -$pow(2,WIDTH1-1); i < $pow(2,WIDTH1-1)-1; i= i+1)begin
        for(j = -$pow(2,WIDTH2-1); j < $pow(2,WIDTH2-1)-1; j = j+1)begin
            a = $signed(i);
            b = $signed(j);
            c = $signed(i);
            d = $signed(j);
            #(T);
			if ((Re != ((a * c) - (b * d)))||(Im != ((a * d) + (b * c))) ) begin
				$display("***ERROR at time = %0d ***", $time);
				$display("a =%d, b =%d, c =%d, d =%d, Re =%d, Im =%d",a, b, c, d, Re, Im);
     
				$stop;
			end
			#(T);
		end
	end
     
    $display("****** Testbench Successfully completed!  ****** ");
                                                               
    $display("***   ######      ###       #####    #####   *** ");
    $display("***  #      #   ##   ##    #        #        *** ");  
    $display("***  #      #   #     #    #        #        *** ");
    $display("***  ########   #######     #####    #####   *** ");
    $display("***  #          #     #          #        #  *** ");
    $display("***  #          #     #          #        #  *** ");
    $display("***  #          #     #     #####    #####   *** ");
    $stop;
end

endmodule

如果仿真出现计算错误,会立即停止仿真,并显示下图所示的信息:

如果仿真完全正确,则会打印如下信息:

最终仿真结果如下图所示:

学习FPGA的时候很多常用的模块可以将其参数化,形成自己的ip,以后方便调用。做FPGA设计是一个逐渐积累的过程。相比于官方提供的封闭的IP核,自己设计的IP核虽然性能比不过,但是更灵活,方便进行个性化修改。FPGA其实就像搭积木一样,只要自己的代码库够丰富,设计只会越来越轻松!点击下面链接查看合集

此合集持续分享一些笔者自己设计的可复用硬件模块点击进入:FPGA搭积木

相关推荐
小沈熬夜秃头中୧⍤⃝8 分钟前
【贪心算法】No.1---贪心算法(1)
算法·贪心算法
木向40 分钟前
leetcode92:反转链表||
数据结构·c++·算法·leetcode·链表
阿阿越42 分钟前
算法每日练 -- 双指针篇(持续更新中)
数据结构·c++·算法
skaiuijing1 小时前
Sparrow系列拓展篇:对调度层进行抽象并引入IPC机制信号量
c语言·算法·操作系统·调度算法·操作系统内核
Star Patrick1 小时前
算法训练(leetcode)二刷第十九天 | *39. 组合总和、*40. 组合总和 II、*131. 分割回文串
python·算法·leetcode
乌恩大侠1 小时前
O-RAN Fronthual CU/Sync/Mgmt 平面和协议栈
5g·平面·fpga开发·架构
武子康2 小时前
大数据-214 数据挖掘 机器学习理论 - KMeans Python 实现 算法验证 sklearn n_clusters labels
大数据·人工智能·python·深度学习·算法·机器学习·数据挖掘
pianmian17 小时前
python数据结构基础(7)
数据结构·算法
好奇龙猫9 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_202410 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘