make values update on the start of the control loop, and make resets only take effect after the control loop has completed an iteration

This commit is contained in:
Peter McGoron 2022-10-21 17:38:07 -04:00
parent 12686391ee
commit f361cac01b
1 changed files with 62 additions and 42 deletions

View File

@ -143,24 +143,38 @@ module control_loop
output reg finish_cmd output reg finish_cmd
); );
/* The loop variables can be modified on the fly. Each
* modification takes effect on the next loop cycle.
* When a caller modifies a variable, the modified
* variable is saved in [name]_buffer and loaded at CYCLE_START.
*/
reg signed [ADC_WID-1:0] setpt = 0; reg signed [ADC_WID-1:0] setpt = 0;
reg signed [ADC_WID-1:0] setpt_buffer = 0;
reg signed [CONSTS_WID-1:0] cl_alpha_reg = 0; reg signed [CONSTS_WID-1:0] cl_alpha_reg = 0;
reg signed [CONSTS_WID-1:0] cl_alpha_reg_buffer = 0;
reg signed [CONSTS_WID-1:0] cl_p_reg = 0; reg signed [CONSTS_WID-1:0] cl_p_reg = 0;
reg [DELAY_WID-1:0] saved_delay = 0; reg signed [CONSTS_WID-1:0] cl_p_reg_buffer = 0;
reg [DELAY_WID-1:0] dely = 0;
reg [DELAY_WID-1:0] dely_buffer = 0;
reg running = 0; reg running = 0;
/* Registers for PI calculations */ /* Registers for PI calculations */
reg signed [ERR_WID-1:0] err_prev = 0; reg signed [ERR_WID-1:0] err_prev = 0;
/****** State machine /****** State machine
* *
* INITIATE_READ_FROM_DAC *
* * INITIATE_READ_FROM_DAC
* WAIT_FOR_DAC_READ *
* * WAIT_FOR_DAC_READ
* WAIT_FOR_DAC_RESPONSE *
* (when value is read) * WAIT_FOR_DAC_RESPONSE (on reset)
* CYCLE_START * (when value is read)
* CYCLE_START
* (wait time delay) * (wait time delay)
* WAIT_ON_ADC * WAIT_ON_ADC
* *
@ -173,7 +187,14 @@ reg signed [ERR_WID-1:0] err_prev = 0;
* There are two systems: the read-write interface and the loop. * There are two systems: the read-write interface and the loop.
* The read-write interface allows another module (i.e. the CPU) * The read-write interface allows another module (i.e. the CPU)
* to access and change constants. When a constant is changed the * to access and change constants. When a constant is changed the
* loop must reset. * loop must reset the values that are preserved between loops
* (previous adjustment and previous delay).
*
* When the loop starts it must find the current value from the
* DAC and write to it. The value from the DAC is then adjusted
* with the output of the control loop. Afterwards it does not
* need to query the DAC for the updated value since it was the one
* that updated the value in the first place.
*/ */
localparam CYCLE_START = 0; localparam CYCLE_START = 0;
@ -185,7 +206,7 @@ localparam WAIT_FOR_DAC_READ = 5;
localparam WAIT_FOR_DAC_RESPONSE = 6; localparam WAIT_FOR_DAC_RESPONSE = 6;
localparam STATESIZ = 3; localparam STATESIZ = 3;
reg [STATESIZ-1:0] state = WAIT_ON_ARM; reg [STATESIZ-1:0] state = INIT_READ_FROM_DAC;
/**** Precision Propogation /**** Precision Propogation
* *
@ -318,15 +339,9 @@ intsat #(
.outp(total_dac_val) .outp(total_dac_val)
); );
/**** Write to DAC ****/
reg [DELAY_WID-1:0] timer = 0; reg [DELAY_WID-1:0] timer = 0;
/* Reset is asserted when any change happens to the inputs.
* It is deasserted when the input pin is deasserted. /**** Read-Write control interface. ****/
* This always takes at least 1 cycle so the loop will
* always halt.
*/
reg reset_from_input = 0;
always @ (posedge clk) begin always @ (posedge clk) begin
if (start_cmd && !finish_cmd) begin if (start_cmd && !finish_cmd) begin
@ -341,23 +356,20 @@ always @ (posedge clk) begin
CONTROL_LOOP_STATUS | CONTROL_LOOP_WRITE_BIT: CONTROL_LOOP_STATUS | CONTROL_LOOP_WRITE_BIT:
running <= word_in[0]; running <= word_in[0];
finish_cmd <= 1; finish_cmd <= 1;
reset_from_input <= 1;
CONTROL_LOOP_SETPT: begin CONTROL_LOOP_SETPT: begin
word_out[DATA_WID-1:ADC_WID] <= 0; word_out[DATA_WID-1:ADC_WID] <= 0;
word_out[ADC_WID-1:0] <= setpt; word_out[ADC_WID-1:0] <= setpt;
finish_cmd <= 1; finish_cmd <= 1;
end end
CONTROL_LOOP_SETPT | CONTROL_LOOP_WRITE_BIT: CONTROL_LOOP_SETPT | CONTROL_LOOP_WRITE_BIT:
setpt <= word_in[ADC_WID-1:0]; setpt_buffer <= word_in[ADC_WID-1:0];
reset_from_input <= 1;
finish_cmd <= 1; finish_cmd <= 1;
CONTROL_LOOP_P: begin CONTROL_LOOP_P: begin
word_out <= cl_p_reg; word_out <= cl_p_reg;
finish_cmd <= 1; finish_cmd <= 1;
end end
CONTROL_LOOP_P | CONTROL_LOOP_WRITE_BIT: begin CONTROL_LOOP_P | CONTROL_LOOP_WRITE_BIT: begin
cl_p_reg <= word_in; cl_p_reg_buffer <= word_in;
reset_from_input <= 1;
finish_cmd <= 1; finish_cmd <= 1;
end end
CONTROL_LOOP_ALPHA: begin CONTROL_LOOP_ALPHA: begin
@ -365,18 +377,16 @@ always @ (posedge clk) begin
finish_cmd <= 1; finish_cmd <= 1;
end end
CONTROL_LOOP_ALPHA | CONTROL_LOOP_WRITE_BIT: begin CONTROL_LOOP_ALPHA | CONTROL_LOOP_WRITE_BIT: begin
cl_alpha_reg <= word_in; cl_alpha_reg_buffer <= word_in;
reset_from_input <= 1;
finish_cmd <= 1; finish_cmd <= 1;
end end
CONTROL_LOOP_DELAY: begin CONTROL_LOOP_DELAY: begin
word_out[DATA_WID-1:DELAY_WID] <= 0; word_out[DATA_WID-1:DELAY_WID] <= 0;
word_out[DELAY_WID-1:0] <= saved_delay; word_out[DELAY_WID-1:0] <= dely;
finish_cmd <= 1; finish_cmd <= 1;
end end
CONTROL_LOOP_DELAY | CONTROL_LOOP_WRITE_BIT: begin CONTROL_LOOP_DELAY | CONTROL_LOOP_WRITE_BIT: begin
saved_delay <= word_in[DELAY_WID-1:0]; dely_buffer <= word_in[DELAY_WID-1:0];
reset_from_input <= 1;
finish_cmd <= 1; finish_cmd <= 1;
end end
CONTROL_LOOP_ERR: begin CONTROL_LOOP_ERR: begin
@ -391,7 +401,6 @@ always @ (posedge clk) begin
end end
end else if (!start_cmd) begin end else if (!start_cmd) begin
finish_cmd <= 0; finish_cmd <= 0;
reset_from_input <= 0;
end end
end end
@ -402,19 +411,16 @@ end
*/ */
always @ (posedge clk) begin always @ (posedge clk) begin
if (reset_from_input) begin case (state)
state <= INIT_READ_FROM_DAC;
adj_prev <= 0;
err_prev <= 0;
timer <= 0;
end else if (running) begin case (state)
INIT_READ_FROM_DAC: begin INIT_READ_FROM_DAC: begin
if (running) begin
/* 1001[0....] is read from dac register */ /* 1001[0....] is read from dac register */
to_dac <= b'1001 << DAC_DATA_WID; to_dac <= b'1001 << DAC_DATA_WID;
dac_ss <= 1; dac_ss <= 1;
dac_arm <= 1; dac_arm <= 1;
state <= WAIT_FOR_DAC_READ; state <= WAIT_FOR_DAC_READ;
end end
end
WAIT_FOR_DAC_READ: begin WAIT_FOR_DAC_READ: begin
if (dac_finished) begin if (dac_finished) begin
state <= WAIT_FOR_DAC_RESPONSE; state <= WAIT_FOR_DAC_RESPONSE;
@ -439,9 +445,23 @@ always @ (posedge clk) begin
end end
end end
CYCLE_START: begin CYCLE_START: begin
if (timer < saved_delay) begin if (!running) begin
state <= INIT_READ_FROM_DAC;
end else if (timer < dely) begin
timer <= timer + 1; timer <= timer + 1;
end else begin end else begin
/* On change of constants, previous values are invalidated. */
if (setpt != setpt_buffer ||
cl_alpha_reg != cl_alpha_reg_buffer ||
cl_p_reg != cl_p_reg_buffer) begin
setpt <= setpt_buffer;
dely <= dely_buf;
cl_alpha_reg <= cl_alpha_reg_buffer;
cl_p_reg <= cl_p_reg_buffer;
adj_prev <= 0;
err_prev <= 0;
end
state <= WAIT_ON_ADC; state <= WAIT_ON_ADC;
timer <= 0; timer <= 0;
adc_arm <= 1; adc_arm <= 1;