📜 ⬆️ ⬇️

Vhdl Reconfigurable Design

Good day.

I would like to share a useful example that I use in practice in different variations. When designing digital devices in the VHDL language, there was a need to make the design of the module more flexible than just resizing the input vectors.

Problem


For example, there is a designed digital filter whose coefficients are represented by floating point numbers . But within the framework of the problem to be solved, it is necessary to build a system operating with fixed-point numbers , I would also like to be able to change the bit length without having to recalculate the coefficients.
In order to get deeper into the problem, let us imagine a situation when we have a module with the following parameters:
component FIRCustomizeDesign is
generic (
SizeD : integer : = 16 ; - The dimension of the input vectors.
- The number format assumes 1 bit per integer part and SizeD-1 for fractional, i.e. interval [-1; 1].
')
- The number of parameters is reduced for clarity.
P01 : integer : = - 32768 ; - = (-0.5) * 2 ^ SizeD - (depends on the size of SizeD)
- Filter coefficients will be passed to Integer,
- then from it will perform type conversions. So it is more convenient and to
- to connect the module there is no need to add additional libraries.
P02 : integer : = 22016 ; - = (43/64) * 2 ^ SizeD
P03 : integer : = - 4352 ; - = -0.0664
-- and so on...
) ;
port (
rst, sclk : in std_logic ;
data_ready : in std_logic ; - readiness of input data

- we consider the 0th bit as the youngest meaningful.
i_data : in std_logic_vector ( SizeD- 1 downto 0 ) ;

pipeline_ready : out std_logic ;
ready : out std_logic ; - readiness output

o_data : out std_logic_vector ( SizeD- 1 downto 0 ) ;
) ;
Where the parameters P0 (0-n) transfer any values ​​that may change with the change in the width of the input data, and it is necessary to recalculate them correctly. In this case, it is convenient to operate with the integer type (if its dimensions are sufficient), in the module architecture it is easily converted into signed / unsigned :
VAL <= to_signed ( P0, SizeD ) + to_signed ( P1, SizeD ) ; - to check correct calculations
- in the selected capacity,
outdata <= std_logic_vector ( VAL ) ; - as well as transparent output.
Thus, when we want to experiment with the digit capacity and change the size of the SizeD , all filter coefficients will have to be recalculated. Agree, many times it is not very convenient to do this. Of course, one could write an external generator, but the solution would not be lightweight and would require additional movements each time.
My goal is to use the standard VHDL libraries and describe the parameters so that when you change SizeD, all P0 (1-n) are recalculated automatically.

Decision


The sticking point is that, in general, the initial coefficients are in the form of floating-point numbers, the floatfixlib library, which is already included in the VHDL 200x , was found for this purpose, and there is a support page for stimulators and synthesizers that support only VHDL-93 .

The following is an example of connecting to the test, there are no fundamental differences from using it in the top-end module.
LIBRARY ieee ;
use ieee . std_logic_1164 . all ;
use ieee . numeric_std . all ;
use ieee .std_logic_textio. all ;
use ieee .math_real. all ;
LIBRARY floatfixlib ;
use floatfixlib.fixed_pkg. all ;
LIBRARY std ;
use std.textio. all ;

entity FIRCustomizeDesign_tb is
- empty
end FIRCustomizeDesign_tb ;

architecture DUT of FIRCustomizeDesign_tb is

- Function for converting type sfixed (Signed Fixed Point) to Interger
function sFix2Int ( r : UNRESOLVED_sfixed )
return integer is
begin
- Convert sfixed by selecting the type UNRESOLVED_sfixed to make the value unique,
- then we translate it into std_logic_vector, then indicating that it is signed in SIGNED,
- the necessary value has already been received, but still it is necessary to cast to integer.
return ( to_integer ( SIGNED ( to_Std_Logic_Vector ( r ) ) ) ) ;
end function sFix2Int ;

constant SizeD : integer : = 16 ;
constant clk_period : time : = 100 ns ;
- Determine the filter coefficients.

- In order to divide the numbers you need to explicitly define them as real,
- so regulates the syntax of VHDL.
constant P01 : real : = - real ( 17 ) / real ( 128 ) ;
constant P02 : real : = sqrt ( real ( 0.675 ) ) ; - We produce any
- Mathematical actions with high accuracy.
constant P03 : real : = real ( 0 ) ; - Everything is hard typed.
-- etc.
- Signed fixed point numbers
constant Decimal_Length : integer : = 1 ; - The length of the whole part.
- As an example, the format is fixed:
constant Fractional_Length : integer : = SizeD-Decimal_Length ;
- Let's put the boundaries of the number in a format understandable for the to_sfixed function.
constant fx_left : integer : = Decimal_Length- 1 ;
constant fx_right : integer : = - ( Fractional_Length ) ;
- Define the subtype for a more elegant entry.
subtype qfixed is sfixed ( fx_left downto fx_right ) ;
- Now everything is converted to the target format.
constant fP01 : qfixed : = to_sfixed ( aP21, fx_left, fx_right ) ;
constant fP02 : qfixed : = to_sfixed ( aP22, fx_left, fx_right ) ;
constant fP03 : qfixed : = to_sfixed ( aP23, fx_left, fx_right ) ;
begin

FIRDUT : FIRCustomizeDesign generic map (
SizeD => SizeD,
P01 => sFix2Int ( fP01 ) - translate sfixed to integer
P02 => sFix2Int ( fP02 ) ,
P03 => sFix2Int ( fP03 )
)
port map (
rst => rst, clk => clk, data_ready => data_ready,
i_data => i_data, ready => ready, pipeline_ready => pipeline_ready,
o_data0 => o_data0
) ;

- Then everything is standard.
test_reactor :
process ...

end DUT ;

Advantages:


Disadvantages:


A fairly narrow example of the capabilities of generic parameters is given, but even in it there is a large enough potential for creating universal solutions.

Thanks for attention.

Source: https://habr.com/ru/post/128974/


All Articles