FPGA从Xilinx的7系列学起(14)

DSP 资源的灵活性远远超过用户认知,加减乘除、累加、计数器、比较器,移位寄存器、复用器、模式匹配等等全部可以使用DSP实现。DSP如何使用复位呢?每一个DSP的Slice有超过250多个寄存器,但是没有一个使用了异步复位。用户使用同步复位可以令综合工具更加容易的推断出使用DSP资源。

这个事情的重要性,需要进一步强调一下。同步复位可以令工具更容易的使用专用的硬件资源。特别对DSP资源来说,用户特别喜欢DSP的输出的寄存器,这样可以增加pipeline,提高系统的性能。只要使用了异步的复位,那么综合工具将无法有效的推断出使用DSP资源。在实际的设计中,我们经常可以看到只要是使用了同步复位,DSP资源将被使用的更有效率。那么只要用户想建立一个算术的系统并且想有效使用DSP资源,那么一定要确保自己使用的同步复位。

Block RAMs可以通过使用输出寄存器,可以获得最小的输出的时间,提高性能。同样输出的寄存器也仅仅有同步服务的接口。没有被使用BlockRAM的资源,那么可以用来作很多功能,例如:ROM、大的LUT、复杂的逻辑、大状态机、深度移位寄存器。使用BlockRAM作为其他的功能,能够解放出大量的寄存器。同样,同步复位可以令工具更容易的推断出Block RAM硬件资源。只要使用了异步的复位,那么综合工具将无法有效的推断出使用Block RAM资源。

另外一个重要的事情,也要说明一下,就是移位寄存器。用户一定要记住要想直接使用LUT作为以为寄存器一定不能有复位端口。只要是在相关的HDL代码中使用了复位的信号,那么这个设计就不可能使用LUT作为SRL寄存器了。综合工具或者把用户的设计放在相关的CLB的寄存器里面了。这个会非常明显的增加使用的寄存器的数量。工具或者建立一个辅助的电路来模拟复位的功能。但是同样的,复位电路也需要大量的消耗资源。设计肯定也会更慢,这个肯定和设计的目的背道而驰。

很多用户可能会有一个疑问,那么这个移位寄存器到底应该怎么在代码中体现呢?给一个例子,当做设计的时候能够仿照这个来实现自己的功能。

VHDL版本的:

library IEEE;
useIEEE.STD_LOGIC_1164.ALL;
entity shifter is
generic (
C_DWIDTH : integer := 8;
C_NUM_CYCLES : integer := 32
);
Port ( Clk : in STD_LOGIC;
En : in STD_LOGIC;
Din : in STD_LOGIC_VECTOR(C_DWIDTH-1 downto 0);
Dout : out STD_LOGIC_VECTOR(C_DWIDTH-1 downto 0));
end shifter;
architecture Behavioral ofshifter is
signal din_d1 :std_logic_vector(C_DWIDTH-1 downto 0); -- Shift register Input
type array_slv is array(C_DWIDTH-1 downto 0) of std_logic_vector(C_NUM_CYCLES-1 downto 0);
signal din_shreg :array_slv;
begin
process (Clk)
begin
if Clk'event and Clk='1' then
if En = '1' then
for i in 0 to C_DWIDTH-1 loop
din_shreg(i) <=din_shreg(i)(C_NUM_CYCLES-2 downto 0) & Din(i);
end loop;
end if;
end if;
end process;
process (din_shreg)
begin
for i in 0 to C_DWIDTH-1 loop
Dout(i) <=din_shreg(i)(C_NUM_CYCLES-1);
end loop;
end process;
end Behavioral;

Verilog版本的:

`timescale 1 ps / 1 ps
module shifter
#(
parameter C_DWIDTH = 8,
parameter C_NUM_CYCLES = 32
)
(
Clk,
En,
Din,
Dout
);
input Clk;
input En;
input [C_DWIDTH-1:0] Din;
output [C_DWIDTH-1:0] Dout;
reg [C_NUM_CYCLES-1:0]din_shreg [C_DWIDTH-1:0];
integer srl_index;
initial
for (srl_index = 0; srl_index din_shreg[srl_index] ={C_NUM_CYCLES{1'b0}};
genvar i;
generate
for (i=0; i < C_DWIDTH; i=i+1)
begin
always @(posedge Clk)
if (En)
din_shreg[i] <={din_shreg[i][C_NUM_CYCLES-2:0], Din[i]};
assign Dout[i] =din_shreg[i][C_NUM_CYCLES-1];
end
endgenerate

endmodule

文章来源:FPGA那点事儿