可参数化的带优先级的数据选择器的FPGA实现方式探讨
在FPGA设计中,大部分情况下我们都得使用到数据选择器。并且为了设计参数化,可调,通常情况下我们需要一个参数可调的数据选择器,比如M选1,M是可调的参数。
如果,数据选择器是不带优先级的,我们可以使用 verilog VHDL中的二维数组进行设计 例如,这样综合编译器也是可以正确生成对应的电路。
reg [7:0] din [1:0]; assign dout = din[sel];
当我们,需要设计一个参数化的数据选择器时呢?我们该如何设计呢?
一、当然我们可以通过嵌套if来实现,假设我们的多路选择器,在某些情况下最多位M路,那么我们可以嵌套M个if,这样,我们就设计出了参数可调 2~M的多路选择器。
always@(*)begin if(sel[0])//1 dout = din[0*DATA_SIZE+:DATA_SIZE]; else if(sel[1])//2 dout = din[1*DATA_SIZE+:DATA_SIZE]; else if(sel[2])//3 dout = din[2*DATA_SIZE+:DATA_SIZE]; else if(sel[3])//4 dout = din[3*DATA_SIZE+:DATA_SIZE]; else if(sel[4])//5 dout = din[4*DATA_SIZE+:DATA_SIZE]; else if(sel[5])//6 dout = din[5*DATA_SIZE+:DATA_SIZE]; else if(sel[6])//7 dout = din[6*DATA_SIZE+:DATA_SIZE]; else if(sel[7])//8 dout = din[7*DATA_SIZE+:DATA_SIZE]; else//0 dout = 0; en
这是对应的资源消耗与Timing,RTL试图
二、当然,我们也知道数据选择器,其实是可以通过与门或门搭建起来的。
比如一个二选一的数据选择器应该,这样一个结构。
一个三选一,带优先级的电路结构
也就是说,我们可以通过代码,描述出这样一个电路结构,通过逻辑复制的语句完成参数化的设计。
具体思路是这样的,先把地址信号sel 变成只是优先级高的那位为1,其他信号为0。例如,低位高优先级,sel=1100,变换后sel_prio=0100。然后,将sel_prio与上对应的数据,可以看出来只有1的那个数据才会被选通,其他为0。代码如下,可以看出来代码里用了很多function,很多书都说function综合成电路可能有问题,我的理解是,如果你对电路由足够的理解,并且综合后都去看一下综合器是否综合出你想要的电路。使用function是可以简化代码的。
module mux #( parameter DATA_SIZE = 8, parameter NUM = 8 ) ( input [NUM*DATA_SIZE-1:0] din, input [NUM-1:0] sel, output [DATA_SIZE-1:0] dout ); assign dout = mux_prio(din,sel); function [DATA_SIZE-1:0] mux_prio ; input [NUM*DATA_SIZE-1:0] din; input [NUM-1:0] sel; reg [NUM-1:0] dat; integer i,j; begin for(i=0;i<DATA_SIZE;i=i+1)begin for(j=0;j<NUM;j=j+1)begin dat[j] = din[j*DATA_SIZE+i]; end mux_prio[i] = mux_prio_bit(dat,sel_prio(sel)); end end endfunction function [NUM-1:0] sel_prio ; input [NUM-1:0] sel; reg temp; integer i,j; begin sel_prio[0] = sel[0]; for(i=1;i<NUM;i=i+1) begin temp = 0; for(j=0;j<i;j=j+1) begin temp = temp | sel[j]; end sel_prio[i] = sel[i] && !temp; end end endfunction function mux_prio_bit ; input [NUM-1:0] din; input [NUM-1:0] sel; integer i; begin mux_prio_bit = din[0]&&sel[0]; for(i=1;i<NUM;i=i+1) mux_prio_bit = mux_prio_bit | (din[i]&sel[i]); end endfunction endmodule
同样的,我们观察一下,生成的电路与综合报告
可以看出来,在这样的综合设置下,生成出来的电路就是我们需要的电路,并且和我们所想的是一样的。并且看起来就是一的电路。
三、在前面的设计中我们是根据数据选择器的电路结构,用硬件语言描述出了这样的电路,那么我们能不能只描述其功能,然后让编译器帮我们理解呢?
贴代码
module mux #( parameter DATA_SIZE = 8, parameter NUM = 8 ) ( input [NUM*DATA_SIZE-1:0] din, input [NUM-1:0] sel, output [DATA_SIZE-1:0] dout ); assign dout = mux_prio_a(din,sel); //基于功能,行为级的描述 function [DATA_SIZE-1:0] mux_prio_a ; input [NUM*DATA_SIZE-1:0] din; input [NUM-1:0] sel; reg temp; integer i; begin temp = 1; mux_prio_a = 0; for(i=0;i<NUM;i=i+1)begin if(temp && sel[i])begin temp = 0; mux_prio_a = din[i*DATA_SIZE+:DATA_SIZE]; end end end endfunction endmodule
看综合结果:可以看出来这样的代码,编译器也是可以正确理解这样的设计的。综合出了我们所需要的电路。
总结:
1、首先,这里提供了了三种描述参数可配的带优先级的多路选择器的描述方法。第一种是常规的描述方法,第二种是根据电路结构使用HDL描述,第三种是使用代码描述了其功能。
2、第三种方法从功能描述,看起来描述简单,好理解,不过这样的描述方式是看综合软件的“智能化程度”的,因为FPGA是基于查找表LUT结构的,这样的描述方式在描述比较简单的电路功能,综合器是可以正确理解的。如果比较复杂的电路,不推荐用这样的描述方式。
3、值得注意的是,FPGA设计最重要的是理解低层的电路结构,实现过程最好是 功能--》电路--》HDL描述该电路,这才是最好的设计。使用类似第三种描述方式最好还是掌握理解底层电路结构,然后看综合出来的是不是你需要的电路。