¿Cómo dividir un número complejo en VHDL?

0

Sé cómo dividir números en VHDL (o usar uno de los generadores de núcleo IP de Xilinx) pero no sé cómo hacerlo en el caso de que los números sean complejos.

En mi caso, he definido un número complejo como este:

type complex12 is record
    re  : std_logic_vector (11 downto 0);
    im  : std_logic_vector (11 downto 0);
end record;

Por lo tanto, mi número complejo es solo dos vectores de 12 bits, uno para la parte real y otro para la parte imaginaria.

Digamos que ahora tengo los números complejos a y b :

signal A : complex12 := (re => (others=>'0'), im => (others=>'0'));
signal B : complex12 := (re => (others=>'0'), im => (others=>'0'));

Sé que la teoría para dividir en números complejos nos dice dos enfoques para hacer una división:

$$ c = \ frac {a_r + j \ cdot a_i} {b_r + j \ cdot b_i} = \ frac {(a_r + j \ cdot a_i) \ cdot (b_r - j \ cdot b_i)} {b_r ^ 2 + b_i ^ 2} $$

Alternativamente: $$ c = \ frac {| a |} {| b |} \ cdot e ^ {j (\ angle a - \ angle b)} $$

Pero ambos enfoques parecen ser muy difíciles de implementar en VHDL. ¿Cuál sería el enfoque preferido? ¿Hay una manera fácil de dividir números complejos? ¿Hay algún bloque de Xilinx que pueda salvar el día? Estoy un poco perdido sobre cómo abordar esto.

    
pregunta JVGD

2 respuestas

0

Tienes la idea correcta con esa primera ecuación. Solo tienes que hacer un poco más de álgebra:

$$ c = \ frac {a_r + j a_i} {b_r + j b_i} = \ frac {(a_r + j a_i) (b_r - j b_i)} {b_r ^ 2 + b_i ^ 2} $$

$$ c = \ frac {a_r b_r + a_i b_i + j a_i b_r - j a_r b_i} {b_r ^ 2 + b_i ^ 2} $$

$$ c = \ frac {(a_r b_r + a_i b_i) + j (a_i b_r - a_r b_i)} {b_r ^ 2 + b_i ^ 2} $$

$$ c = \ frac {a_r b_r + a_i b_i} {b_r ^ 2 + b_i ^ 2} + j \ frac {a_i b_r - a_r b_i} {b_r ^ 2 + b_i ^ 2} $$

Sí, hay muchas operaciones requeridas. Parece que 6 se multiplica, dos sumas, una resta y dos divisiones. Sí, implementar esto en Verilog / VHDL será bastante complejo. Si no necesita el máximo rendimiento, entonces probablemente pueda salirse con un multiplicador y un divisor y luego secuenciar las operaciones con una máquina de estados. Primero calcule el denominador, guárdelo y luego haga los numeradores, calculando el segundo mientras el divisor está trabajando en la parte real de la salida.

    
respondido por el alex.forencich
0

Alex tiene razón. Es bastante sencillo VHDL, pero tedioso.

Tenga en cuenta que los anchos de palabra crecen bajo operaciones aritméticas; el producto de dos números de 12 bits firmados es efectivamente 23 bits, etc. (¿Por qué 23 no 24? Porque tiene 2 bits de signo).

Si el hardware es escaso, es probable que desee redondear a 12 (o 16 o 18 o 20) bits para limitar un mayor crecimiento en otras operaciones. Así que hay sutilezas y probablemente desee comenzar con un modelo de precisión de bits derivado de sus ecuaciones, y asegúrese de que cumpla con sus especificaciones de precisión / ruido antes de comenzar con el diseño detallado.

(Creo que los tipos de puntos fijos incorporados en Ada son ideales para este modelado, pero elijo el enfoque que mejor se adapte a usted. La simulación de comportamiento utilizando los tipos numeric_std de VHDL también funciona)

Una vez que la matemática es correcta, la conversión a VHDL canalizada es relativamente fácil.

O ... busque otro algoritmo que no implique una división en primer lugar.

    
respondido por el Brian Drummond

Lea otras preguntas en las etiquetas