2
\$\begingroup\$

I have a problem with writing Verilog HDL code. I want to design a simple PID controller in FPGA I am using Cyclone II family. I want to feedback my output value as an input in a previous stage of calculations. Equation looks like this u(n) = u(n-1) + x (x is calculated correctly) so I created a register to save the output value and connected it to a previous stage in my design.

Unfortunately this solution doesn't work when I simulate this I get 'unknown' value in the register that I am saving the output value to and the output value itself is also 'unknown' (by unknown I mean 'x').

Is it possible to create a feedback loop between certain components in HDL design? How can it be done? Should I try to resolve this issue by doing the calculations step by step in an FSM?

EDIT: This is my code as requested

PID Module

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
m.Alin
10.9k20 gold badges66 silver badges90 bronze badges
asked Jan 20, 2013 at 19:42
\$\endgroup\$
4
  • \$\begingroup\$ Can you share your code? Did you specify an initial value for the holding register, or use a reset signal to put it in a known state at the start of your simulation? \$\endgroup\$ Commented Jan 20, 2013 at 19:48
  • \$\begingroup\$ Yes, the registers output value is 0 when reset is low. \$\endgroup\$ Commented Jan 20, 2013 at 19:51
  • \$\begingroup\$ And your simulation testbench sets reset low long enough to get all registers into a known state, but then you still see 'X' values reappear once you release reset? That sounds like you did everything right --- if you can, share your code and we can look for typo's or other kinds of problems. \$\endgroup\$ Commented Jan 20, 2013 at 19:57
  • \$\begingroup\$ Are you absolutely sure you got the order of your inputs & outputs for instantiated blocks right? Without explicit connections (like reg reg1 (.CLK(c), .RST(r), .I(x), .O(y)) ), there's no way I can be sure of this part of your code. \$\endgroup\$ Commented Jan 20, 2013 at 20:17

2 Answers 2

4
\$\begingroup\$

I don't see any code that resets K0, K1, and K2, until the load state is used.

This means that on start-up, these registers have X value.

Therefore the outputs of u_mult1, u_mult2, and u_mult3 have X value.

Therefore the outpus of u_adder1, u_adder2, and u_adder3 get X value.

Therefore on the next clock edge, sum_out_old gets X value. Probably at the same time, the K variables get loaded with their values from the module inputs. But it's too late. Since sum_out is calculated from sum_out_old, it then becomes X, and sum_out_old is trapped in the X state.

The easy way to solve this is to have K0, K1, and K2 reset to 0 when rst_n is asserted (low), but you should consider if this is correct for your situation.

answered Jan 20, 2013 at 20:27
\$\endgroup\$
0
2
\$\begingroup\$

For simulation, you need to reset your values to a known state at the beginning. You can use the reset line for this, but this ends up synthesised as The Photon mentions (not usually a problem)

Another way to do it is to set the value when you code the register, such as:

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

Depending on your tools, this may or may not work (I use Xilinx tools), and actually may end up being synthesised (i.e. the registers are set during the bitstream being loaded into the FPGA) but give it a go and let us know.

answered Jan 20, 2013 at 20:41
\$\endgroup\$
2
  • \$\begingroup\$ My memory is that some version of Xilinx tools that I used once wouldn't respect this in synthesis. Because of that, I habitually don't code it this way. But I think it's good in recent tools. \$\endgroup\$ Commented Jan 20, 2013 at 21:39
  • \$\begingroup\$ Yes, I think you have the choice for it to synthesise now - In any case I just use it for simulation when I don't have a reset line (and I don't mind whether the synthesis tools respect it or not, as in most cases you don't mind what the register starts out at) \$\endgroup\$ Commented Jan 20, 2013 at 22:07

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.