Ich habe ein Problem mit dem Schreiben von Verilog-HDL-Code. Ich möchte einen einfachen PID-Controller in FPGA entwerfen. Ich verwende die Cyclone II-Familie. Ich möchte meinen Ausgabewert als Eingabe in einer vorherigen Berechnungsphase zurückgeben. Die Gleichung sieht folgendermaßen aus: u(n) = u(n-1) + x (x wird korrekt berechnet), also habe ich ein Register erstellt, um den Ausgabewert zu speichern, und es mit einer vorherigen Stufe in meinem Design verbunden.
Leider funktioniert diese Lösung nicht, wenn ich dies simuliere. Ich bekomme einen 'unbekannten' Wert in dem Register, in dem ich den Ausgabewert speichere, und der Ausgabewert selbst ist auch 'unbekannt' (mit unbekannt meine ich 'x').
Ist es möglich, eine Rückkopplungsschleife zwischen bestimmten Komponenten im HDL-Design zu erstellen? Wie kann es gemacht werden? Sollte ich versuchen, dieses Problem zu lösen, indem ich die Berechnungen Schritt für Schritt in einem FSM durchführe?
BEARBEITEN: Dies ist mein angeforderter Code
PID-Modul
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
Ich sehe keinen Code K0
, der K1
, und zurücksetzt K2
, bis der Ladezustand verwendet wird.
Dies bedeutet, dass diese Register beim Start X
einen Wert haben.
Daher haben die Ausgaben von u_mult1
, u_mult2
, und einen Wert.u_mult3
X
Daher erhalten die Ausgaben von u_adder1
, u_adder2
, und Wert.u_adder3
X
sum_out_old
Erhält daher bei der nächsten Taktflanke X
einen Wert. Wahrscheinlich werden gleichzeitig die K-Variablen mit ihren Werten aus den Moduleingängen geladen. Aber es ist zu spät. Da sum_out
aus berechnet wird sum_out_old
, wird es dann zu X
und sum_out_old
ist im X
Zustand gefangen.
Der einfache Weg, dies zu lösen, besteht darin K0
, K1
, , und K2
auf 0 zurückzusetzen, wenn rst_n
behauptet wird (niedrig), aber Sie sollten überlegen, ob dies für Ihre Situation richtig ist.
Für die Simulation müssen Sie Ihre Werte zu Beginn auf einen bekannten Zustand zurücksetzen. Sie können dafür die Reset-Leitung verwenden, aber dies wird synthetisiert, wie The Photon erwähnt (normalerweise kein Problem).
Eine andere Möglichkeit besteht darin, den Wert beim Codieren des Registers festzulegen, z. B.:
reg [N-1:0]K0 = 8'b00000000;
reg [N-1:0]K1 = 8'b00000000;
reg [N-1:0]K2 = 8'b00000000;
Abhängig von Ihren Tools kann dies funktionieren oder nicht (ich verwende Xilinx-Tools) und tatsächlich synthetisiert werden (dh die Register werden gesetzt, während der Bitstrom in das FPGA geladen wird), aber versuchen Sie es und lassen Sie es uns wissen.
Das Photon
zdun8
Das Photon
reset
? Das hört sich so an, als hätten Sie alles richtig gemacht – wenn Sie können, teilen Sie uns Ihren Code mit und wir können nach Tippfehlern oder anderen Problemen suchen.Das Photon
reg reg1 (.CLK(c), .RST(r), .I(x), .O(y))
) kann ich mir bei diesem Teil Ihres Codes nicht sicher sein.