Bucle de retroalimentación en Verilog

2

Tengo un problema con la escritura del código Verilog HDL. Quiero diseñar un controlador PID simple en FPGA. Estoy usando la familia Cyclone II. Quiero retroalimentar mi valor de salida como una entrada en una etapa previa de cálculos. La ecuación se ve así: u (n) = u (n-1) + x (x se calcula correctamente), así que creé un registro para guardar el valor de salida y lo conecté a una etapa anterior en mi diseño.

Lamentablemente, esta solución no funciona cuando simulo esto. Obtengo un valor 'desconocido' en el registro en el que estoy guardando el valor de salida y el valor de salida en sí mismo también es 'desconocido' (por desconocido quiero decir 'x') .

¿Es posible crear un circuito de retroalimentación entre ciertos componentes en el diseño HDL? ¿Cómo puede hacerse esto? ¿Debo intentar resolver este problema haciendo los cálculos paso a paso en un FSM?

EDITAR: Este es mi código según lo solicitado

Módulo PID

module pid(clk,rst_n,Kp_in, Kd_in, Ki_in,temp_data_in,setpoint,pwm_out);


parameter N = 8;
parameter M = 16;

input   clk;
input   rst_n;
input   [N-1:0]temp_data_in;
input   [N-1:0]setpoint;    
input [N-1:0]Kp_in;
input [N-1:0]Kd_in;
input [N-1:0]Ki_in;

output [N-1:0]pwm_out;

wire    clk;
wire    rst_n;

reg [N-1:0]temp_data_reg;
reg [N-1:0]setpoint_reg;
reg [N-1:0]pwm_out_reg;

localparam [1:0] idle = 2'b00, load = 2'b01, run= 2'b10;
localparam k = 2;

reg [1:0] state_reg, state_next;

always@(posedge clk, negedge rst_n) begin
    if(!rst_n) begin
        state_reg <= idle;
    end else
        state_reg <= state_next;
    end

reg sum_out_old_reg_en;

reg     [N-1:0]K0;
reg [N-1:0]K1;
reg [N-1:0]K2;

wire [N-1:0] ex0;
wire [N-1:0] ex1;
wire [N-1:0] ex2;

wire [2*N-1:0] out0;
wire [2*N-1:0] out1;
wire [2*N-1:0] out2;

wire [2*N-1:0] sum1;
wire [2*N-1:0] sum2;
wire [2*N-1:0] sum_out_old;
wire [2*N-1:0] sum_out;

register e0(clk,rst_n,(temp_data_in-setpoint),ex0);
register e1(clk,rst_n,ex0,ex1);
register e2(clk,rst_n,ex1,ex2);
mult u_mult1(ex0,K0,out0);
mult u_mult2(ex1,K1,out1);
mult u_mult3(ex2,K2,out2);
adder u_adder1(out0,out1,sum1);
adder u_adder2(out2,sum_out_old,sum2);
adder u_adder3(sum1,sum2,sum_out);  

register16b u_old(clk,rst_n,sum_out,sum_out_old);

always@(posedge clk) begin
    state_next = state_reg; 
    case(state_reg)
        idle: begin
                    state_next = load;
                end
        load: begin
                    K0 = Kp_in + Kd_in + Ki_in;
                    K1 = -Kp_in + (-2)*Kd_in;
                    K2 = Kd_in;         
                    state_next = run;
                end
        run: begin

                state_next = run;
              end
    endcase
end

endmodule
    
pregunta zdun8

2 respuestas

3

No veo ningún código que restablezca K0 , K1 y K2 , hasta que se use el estado de carga.

Esto significa que en el inicio, estos registros tienen un valor de X .

Por lo tanto, las salidas de u_mult1 , u_mult2 y u_mult3 tienen el valor de X .

Por lo tanto, la salida de u_adder1 , u_adder2 y u_adder3 obtiene el valor X .

Por lo tanto, en el siguiente borde del reloj, sum_out_old obtiene el valor de X . Probablemente al mismo tiempo, las variables K se cargan con sus valores desde las entradas del módulo. Pero es muy tarde. Como sum_out se calcula a partir de sum_out_old , entonces se convierte en X y sum_out_old queda atrapado en el estado X .

La forma fácil de resolver esto es tener K0 , K1 y K2 restablecidos a 0 cuando se afirma (%) rst_n , pero debe considerar si esto es correcto para su situación. / p>     

respondido por el The Photon
2

Para la simulación, necesita restablecer sus valores a un estado conocido al principio. Puede usar la línea de reinicio para esto, pero esto se sintetiza como lo menciona The Photon (no suele ser un problema)

Otra forma de hacerlo es establecer el valor cuando codifique el registro, como:

reg [N-1:0]K0 = 8'b00000000;
reg [N-1:0]K1 = 8'b00000000;
reg [N-1:0]K2 = 8'b00000000;

Dependiendo de sus herramientas, esto puede o no funcionar (yo uso las herramientas Xilinx), y en realidad puede terminar sintetizándose (es decir, los registros se configuran durante la corriente de bits que se está cargando en el FPGA), pero pruébelo sabemos.

    
respondido por el Oli Glaser

Lea otras preguntas en las etiquetas