diff --git a/GUIDELINES.md b/GUIDELINES.md index 5e9e946..eff83fd 100644 --- a/GUIDELINES.md +++ b/GUIDELINES.md @@ -9,12 +9,8 @@ See also [Dan Gisselquist][1]'s rules for FPGA development. * Stick to Verilog 2005. F4PGA will accept SystemVerilog but yosys sometimes synthesizes it incorrectly. * Do not use parameters that are calculated from other parameters (yosys - will not parse them correctly). Use macros instead. -* Only use Verlog macros for basic expression replacement (replacing calculated - parameters). For more advanced code generation, use m4 (see `base.m4` as an - example). -* Add `undefineall` at the end of *every single module*. If you do not, - you will get many confusing errors. + will not parse them correctly). Use m4 macros instead. +* Do not use Verilog macros. Use m4. * Do all code and test generation in Makefiles. * Simulate *every* module, even the trivial ones using Verilator. Simulation must be simulatable with open-source software (Verilator is diff --git a/firmware/rtl/base/Makefile b/firmware/rtl/base/Makefile index a67c77e..359758f 100644 --- a/firmware/rtl/base/Makefile +++ b/firmware/rtl/base/Makefile @@ -1,5 +1,5 @@ .PHONY: lint -base.v: base.m4 - m4 -P --synclines base.m4 | awk -v filename=base.m4 '/^#line/ {printf("`line %s %d 0\n", filename, $$2); next} {print}' > base.v +include ../common.makefile +base.v: base.v.m4 lint: base.v verilator --lint-only base.v -I../spi -I../control_loop -I../waveform diff --git a/firmware/rtl/base/base.m4 b/firmware/rtl/base/base.v.m4 similarity index 92% rename from firmware/rtl/base/base.m4 rename to firmware/rtl/base/base.v.m4 index 87f3081..07f0b12 100644 --- a/firmware/rtl/base/base.m4 +++ b/firmware/rtl/base/base.v.m4 @@ -135,7 +135,7 @@ m4_define(m4_adc_switch, ⟨ `include "control_loop_cmds.vh" module base #( parameter DAC_PORTS = 2, -`define DAC_PORTS_CONTROL_LOOP (DAC_PORTS + 1) +m4_define(DAC_PORTS_CONTROL_LOOP, (DAC_PORTS + 1)) parameter DAC_NUM = 8, parameter DAC_WID = 24, @@ -156,7 +156,7 @@ module base #( parameter WF_RAM_WORD_INCR = 2, parameter ADC_PORTS = 1, -`define ADC_PORTS_CONTROL_LOOP (ADC_PORTS + 1) +m4_define(ADC_PORTS_CONTROL_LOOP, (ADC_PORTS + 1)) parameter ADC_NUM = 8, /* Three types of ADC. For now assume that their electronics * are similar enough, just need different numbers for the width. @@ -179,8 +179,8 @@ module base #( parameter CL_CONSTS_FRAC = 43, parameter CL_CONSTS_SIZ = 7, parameter CL_DELAY_WID = 16, -`define CL_CONSTS_WID (CL_CONSTS_WHOLE + CL_CONSTS_FRAC) -`define CL_DATA_WID `CL_CONSTS_WID +m4_define(CL_CONSTS_WID, (CL_CONSTS_WHOLE + CL_CONSTS_FRAC)) +m4_define(CL_DATA_WID, CL_CONSTS_WID) parameter CL_READ_DAC_DELAY = 5, parameter CL_CYCLE_COUNT_WID = 18 ) ( @@ -195,7 +195,7 @@ module base #( input [ADC_NUM-1:0] adc_sdo, output [ADC_NUM-1:0] adc_sck, - m4_dac_wires(`DAC_PORTS_CONTROL_LOOP, 0), + m4_dac_wires(DAC_PORTS_CONTROL_LOOP, 0), m4_dac_wires(DAC_PORTS, 1), m4_dac_wires(DAC_PORTS, 2), m4_dac_wires(DAC_PORTS, 3), @@ -204,7 +204,7 @@ module base #( m4_dac_wires(DAC_PORTS, 6), m4_dac_wires(DAC_PORTS, 7), - input [`ADC_PORTS_CONTROL_LOOP-1:0] adc_sel_0, + input [ADC_PORTS_CONTROL_LOOP-1:0] adc_sel_0, m4_adc_wires(ADC_TYPE1_WID, 0), m4_adc_wires(ADC_TYPE1_WID, 1), @@ -217,8 +217,8 @@ module base #( output cl_in_loop, input [`CONTROL_LOOP_CMD_WIDTH-1:0] cl_cmd, - input [`CL_DATA_WID-1:0] cl_word_in, - output reg [`CL_DATA_WID-1:0] cl_word_out, + input [CL_DATA_WID-1:0] cl_word_in, + output reg [CL_DATA_WID-1:0] cl_word_out, input cl_start_cmd, output reg cl_finish_cmd ); @@ -226,7 +226,7 @@ module base #( wire [ADC_NUM-1:0] adc_conv_L; assign adc_conv = ~adc_conv_L; -m4_dac_switch(`DAC_PORTS_CONTROL_LOOP, 0); +m4_dac_switch(DAC_PORTS_CONTROL_LOOP, 0); m4_dac_switch(DAC_PORTS, 1); m4_dac_switch(DAC_PORTS, 2); m4_dac_switch(DAC_PORTS, 3); @@ -237,14 +237,14 @@ m4_dac_switch(DAC_PORTS, 7); /* 1st adc is Type 1 (18 bit) */ -wire [`ADC_PORTS_CONTROL_LOOP-1:0] adc_conv_L_port_0; -wire [`ADC_PORTS_CONTROL_LOOP-1:0] adc_sdo_port_0; -wire [`ADC_PORTS_CONTROL_LOOP-1:0] adc_sck_port_0; -wire [`ADC_PORTS_CONTROL_LOOP-1:0] adc_mosi_port_0_unassigned; +wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_conv_L_port_0; +wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_sdo_port_0; +wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_sck_port_0; +wire [ADC_PORTS_CONTROL_LOOP-1:0] adc_mosi_port_0_unassigned; wire adc_mosi_unassigned; spi_switch #( - .PORTS(`ADC_PORTS_CONTROL_LOOP) + .PORTS(ADC_PORTS_CONTROL_LOOP) ) switch_adc_0 ( .select(adc_sel_0), .mosi(adc_mosi_unassigned), @@ -327,4 +327,3 @@ m4_adc_switch(ADC_TYPE1_WID, 6); m4_adc_switch(ADC_TYPE1_WID, 7); endmodule -`undefineall diff --git a/firmware/rtl/common.makefile b/firmware/rtl/common.makefile new file mode 100644 index 0000000..43d63a6 --- /dev/null +++ b/firmware/rtl/common.makefile @@ -0,0 +1,3 @@ +# Generate verilog from m4 file +%.v: %.v.m4 + m4 -P --synclines $< | awk -v filename=$< '/^#line/ {printf("`line %d %s 0\n", $$2, filename); next} {print}' > $@ diff --git a/firmware/rtl/control_loop/Makefile b/firmware/rtl/control_loop/Makefile index 39a3b97..31f9d45 100644 --- a/firmware/rtl/control_loop/Makefile +++ b/firmware/rtl/control_loop/Makefile @@ -1,11 +1,14 @@ # Makefile for tests and hardware verification. -.PHONY: test clean +.PHONY: test clean codegen all + +all: test codegen ####### Tests ######## COMMON_CPP = control_loop_math_implementation.cpp COMMON= ${COMMON_CPP} control_loop_math_implementation.h +control_loop_math_verilog = control_loop_math.v boothmul.v intsat.v sign_extend.v CONSTS_FRAC=43 E_WID=21 @@ -16,7 +19,7 @@ clean: rm -rf obj_dir *.fst obj_dir/Vcontrol_loop_math.mk: control_loop_math_sim.cpp ${COMMON} \ - control_loop_math.v + ${control_loop_math_verilog} verilator --cc --exe -Wall --trace --trace-fst \ --top-module control_loop_math \ -GCONSTS_FRAC=${CONSTS_FRAC} -DDEBUG_CONTROL_LOOP_MATH \ @@ -31,7 +34,9 @@ obj_dir/Vcontrol_loop_sim_top.mk: control_loop_sim.cpp ${COMMON} \ adc_sim.v dac_sim.v \ ../spi/spi_master_ss.v \ ../spi/spi_slave_no_write.v \ - control_loop_sim_top.v control_loop_sim_top.v + control_loop_sim_top.v control_loop_sim_top.v \ + control_loop_cmds.vh control_loop.v \ + ${control_loop_math_verilog} verilator --cc --exe -Wall --trace --trace-fst \ --top-module control_loop_sim_top \ -GCONSTS_FRAC=${CONSTS_FRAC} \ @@ -45,6 +50,10 @@ obj_dir/Vcontrol_loop_sim_top: obj_dir/Vcontrol_loop_sim_top.mk control_loop_cmd ####### Codegen ######## -control_loop_cmds.h: control_loop_cmds.vh +include ../common.makefile +codegen: control_loop_cmds.h boothmul.v control_loop_math.v control_loop.v control_loop_cmds.vh +control_loop_cmds.vh: control_loop_cmds.m4 + m4 -P control_loop_cmds.vh.m4 > control_loop_cmds.vh +control_loop_cmds.h: control_loop_cmds.m4 echo '#pragma once' > control_loop_cmds.h - sed 's/`define/#define/g; s/`//g' control_loop_cmds.vh >> control_loop_cmds.h + m4 -P control_loop_cmds.h.m4 >> control_loop_cmds.h diff --git a/firmware/rtl/control_loop/boothmul.v b/firmware/rtl/control_loop/boothmul.v.m4 similarity index 81% rename from firmware/rtl/control_loop/boothmul.v rename to firmware/rtl/control_loop/boothmul.v.m4 index f235fb7..a5ceffa 100644 --- a/firmware/rtl/control_loop/boothmul.v +++ b/firmware/rtl/control_loop/boothmul.v.m4 @@ -1,3 +1,5 @@ +m4_changequote(`⟨', `⟩') +m4_changecom(⟨/*⟩, ⟨*/⟩) /* Booth Multiplication v1.0 * Written by Peter McGoron, 2022. * @@ -28,11 +30,12 @@ module boothmul input arm, input [A1_LEN-1:0] a1, input [A2_LEN-1:0] a2, - output [A1_LEN+A2_LEN-1:0] outn, +m4_define(M4_OUT_LEN, (A1_LEN + A2_LEN)) + output [M4_OUT_LEN-1:0] outn, `ifdef DEBUG - output [A1_LEN+A2_LEN+1:0] debug_a, - output [A1_LEN+A2_LEN+1:0] debug_s, - output [A1_LEN+A2_LEN+1:0] debug_p, + output [M4_OUT_LEN+1:0] debug_a, + output [M4_OUT_LEN+1:0] debug_s, + output [M4_OUT_LEN+1:0] debug_p, output [A2LEN_SIZ-1:0] debug_state, `endif output reg fin @@ -42,8 +45,7 @@ module boothmul * Booth Parameters **********************/ -`define OUT_LEN (A1_LEN + A2_LEN) -`define REG_LEN (`OUT_LEN + 2) +m4_define(M4_REG_LEN, (M4_OUT_LEN + 2)) /* The Booth multiplication algorithm is a sequential algorithm for * twos-compliment integers. @@ -71,24 +73,24 @@ module boothmul reg [A1_LEN-1:0] a1_reg; -wire [`REG_LEN-1:0] a; +wire [M4_REG_LEN-1:0] a; assign a[A2_LEN:0] = 0; -assign a[`REG_LEN-2:A2_LEN+1] = a1_reg; -assign a[`REG_LEN-1] = a1_reg[A1_LEN-1]; -wire signed [`REG_LEN-1:0] a_signed; +assign a[M4_REG_LEN-2:A2_LEN+1] = a1_reg; +assign a[M4_REG_LEN-1] = a1_reg[A1_LEN-1]; +wire signed [M4_REG_LEN-1:0] a_signed; assign a_signed = a; -wire [`REG_LEN-1:0] s; +wire [M4_REG_LEN-1:0] s; assign s[A2_LEN:0] = 0; -assign s[`REG_LEN-1:A2_LEN+1] = ~{a1_reg[A1_LEN-1],a1_reg} + 1; -wire signed [`REG_LEN-1:0] s_signed; +assign s[M4_REG_LEN-1:A2_LEN+1] = ~{a1_reg[A1_LEN-1],a1_reg} + 1; +wire signed [M4_REG_LEN-1:0] s_signed; assign s_signed = s; -reg [`REG_LEN-1:0] p; -wire signed [`REG_LEN-1:0] p_signed; +reg [M4_REG_LEN-1:0] p; +wire signed [M4_REG_LEN-1:0] p_signed; assign p_signed = p; -assign outn = p[`REG_LEN-2:1]; +assign outn = p[M4_REG_LEN-2:1]; /********************** * Loop Implementation @@ -110,7 +112,7 @@ always @ (posedge clk) begin end else if (loop_accul == 0) begin p[0] <= 0; p[A2_LEN:1] <= a2; - p[`REG_LEN-1:A2_LEN+1] <= 0; + p[M4_REG_LEN-1:A2_LEN+1] <= 0; a1_reg <= a1; @@ -142,4 +144,3 @@ end `endif endmodule -`undefineall diff --git a/firmware/rtl/control_loop/control_loop.v b/firmware/rtl/control_loop/control_loop.v.m4 similarity index 84% rename from firmware/rtl/control_loop/control_loop.v rename to firmware/rtl/control_loop/control_loop.v.m4 index a4e9f27..de0a6e3 100644 --- a/firmware/rtl/control_loop/control_loop.v +++ b/firmware/rtl/control_loop/control_loop.v.m4 @@ -1,4 +1,7 @@ -`include "control_loop_cmds.vh" +m4_changequote(`⟨', `⟩') +m4_changecom(⟨/*⟩, ⟨*/⟩) +m4_define(generate_macro, ⟨m4_define(M4_$1, $2)⟩) +m4_include(control_loop_cmds.m4) module control_loop #( @@ -17,9 +20,9 @@ module control_loop parameter CONSTS_WHOLE = 21, parameter CONSTS_FRAC = 43, parameter CONSTS_SIZ = 7, -`define CONSTS_WID (CONSTS_WHOLE + CONSTS_FRAC) +m4_define(M4_CONSTS_WID, (CONSTS_WHOLE + CONSTS_FRAC)) parameter DELAY_WID = 16, -`define DATA_WID `CONSTS_WID +m4_define(M4_DATA_WID, M4_CONSTS_WID) parameter READ_DAC_DELAY = 5, parameter CYCLE_COUNT_WID = 18, parameter DAC_WID = 24, @@ -29,7 +32,7 @@ module control_loop */ parameter DAC_WID_SIZ = 5, parameter DAC_DATA_WID = 20, -`define E_WID (DAC_DATA_WID + 1) +m4_define(M4_E_WID, (DAC_DATA_WID + 1)) parameter DAC_POLARITY = 0, parameter DAC_PHASE = 1, parameter DAC_CYCLE_HALF_WAIT = 10, @@ -50,9 +53,9 @@ module control_loop output adc_sck, /* Hacky ad-hoc read-write interface. */ - input [`CONTROL_LOOP_CMD_WIDTH-1:0] cmd, - input [`DATA_WID-1:0] word_in, - output reg [`DATA_WID-1:0] word_out, + input [M4_CONTROL_LOOP_CMD_WIDTH-1:0] cmd, + input [M4_DATA_WID-1:0] word_in, + output reg [M4_DATA_WID-1:0] word_out, input start_cmd, output reg finish_cmd ); @@ -125,12 +128,12 @@ reg signed [ADC_WID-1:0] setpt = 0; reg signed [ADC_WID-1:0] setpt_buffer = 0; /* Integral parameter */ -reg signed [`CONSTS_WID-1:0] cl_I_reg = 0; -reg signed [`CONSTS_WID-1:0] cl_I_reg_buffer = 0; +reg signed [M4_CONSTS_WID-1:0] cl_I_reg = 0; +reg signed [M4_CONSTS_WID-1:0] cl_I_reg_buffer = 0; /* Proportional parameter */ -reg signed [`CONSTS_WID-1:0] cl_p_reg = 0; -reg signed [`CONSTS_WID-1:0] cl_p_reg_buffer = 0; +reg signed [M4_CONSTS_WID-1:0] cl_p_reg = 0; +reg signed [M4_CONSTS_WID-1:0] cl_p_reg_buffer = 0; /* Delay parameter (to make the loop run slower) */ reg [DELAY_WID-1:0] dely = 0; @@ -143,11 +146,11 @@ reg running = 0; reg signed [DAC_DATA_WID-1:0] stored_dac_val = 0; reg [CYCLE_COUNT_WID-1:0] last_timer = 0; reg [CYCLE_COUNT_WID-1:0] counting_timer = 0; -reg [`CONSTS_WID-1:0] adjval_prev = 0; +reg [M4_CONSTS_WID-1:0] adjval_prev = 0; -reg signed [`E_WID-1:0] err_prev = 0; -wire signed [`E_WID-1:0] e_cur; -wire signed [`CONSTS_WID-1:0] adj_val; +reg signed [M4_E_WID-1:0] err_prev = 0; +wire signed [M4_E_WID-1:0] e_cur; +wire signed [M4_CONSTS_WID-1:0] adj_val; wire signed [DAC_DATA_WID-1:0] new_dac_val; reg arm_math = 0; @@ -244,78 +247,78 @@ reg dirty_bit = 0; always @ (posedge clk) begin if (start_cmd && !finish_cmd) begin case (cmd) - `CONTROL_LOOP_NOOP: + M4_CONTROL_LOOP_NOOP: finish_cmd <= 1; - `CONTROL_LOOP_NOOP | `CONTROL_LOOP_WRITE_BIT: + M4_CONTROL_LOOP_NOOP | M4_CONTROL_LOOP_WRITE_BIT: finish_cmd <= 1; - `CONTROL_LOOP_STATUS: begin - word_out[`DATA_WID-1:1] <= 0; + M4_CONTROL_LOOP_STATUS: begin + word_out[M4_DATA_WID-1:1] <= 0; word_out[0] <= running; finish_cmd <= 1; end - `CONTROL_LOOP_STATUS | `CONTROL_LOOP_WRITE_BIT: + M4_CONTROL_LOOP_STATUS | M4_CONTROL_LOOP_WRITE_BIT: if (write_control) begin running <= word_in[0]; finish_cmd <= 1; dirty_bit <= 1; end - `CONTROL_LOOP_SETPT: begin - word_out[`DATA_WID-1:ADC_WID] <= 0; + M4_CONTROL_LOOP_SETPT: begin + word_out[M4_DATA_WID-1:ADC_WID] <= 0; word_out[ADC_WID-1:0] <= setpt; finish_cmd <= 1; end - `CONTROL_LOOP_SETPT | `CONTROL_LOOP_WRITE_BIT: + M4_CONTROL_LOOP_SETPT | M4_CONTROL_LOOP_WRITE_BIT: if (write_control) begin setpt_buffer <= word_in[ADC_WID-1:0]; finish_cmd <= 1; dirty_bit <= 1; end - `CONTROL_LOOP_P: begin + M4_CONTROL_LOOP_P: begin word_out <= cl_p_reg; finish_cmd <= 1; end - `CONTROL_LOOP_P | `CONTROL_LOOP_WRITE_BIT: begin + M4_CONTROL_LOOP_P | M4_CONTROL_LOOP_WRITE_BIT: begin if (write_control) begin cl_p_reg_buffer <= word_in; finish_cmd <= 1; dirty_bit <= 1; end end - `CONTROL_LOOP_I: begin + M4_CONTROL_LOOP_I: begin word_out <= cl_I_reg; finish_cmd <= 1; end - `CONTROL_LOOP_I | `CONTROL_LOOP_WRITE_BIT: begin + M4_CONTROL_LOOP_I | M4_CONTROL_LOOP_WRITE_BIT: begin if (write_control) begin cl_I_reg_buffer <= word_in; finish_cmd <= 1; dirty_bit <= 1; end end - `CONTROL_LOOP_DELAY: begin - word_out[`DATA_WID-1:DELAY_WID] <= 0; + M4_CONTROL_LOOP_DELAY: begin + word_out[M4_DATA_WID-1:DELAY_WID] <= 0; word_out[DELAY_WID-1:0] <= dely; finish_cmd <= 1; end - `CONTROL_LOOP_DELAY | `CONTROL_LOOP_WRITE_BIT: begin + M4_CONTROL_LOOP_DELAY | M4_CONTROL_LOOP_WRITE_BIT: begin if (write_control) begin dely_buffer <= word_in[DELAY_WID-1:0]; finish_cmd <= 1; dirty_bit <= 1; end end - `CONTROL_LOOP_ERR: begin - word_out[`DATA_WID-1:`E_WID] <= 0; - word_out[`E_WID-1:0] <= err_prev; + M4_CONTROL_LOOP_ERR: begin + word_out[M4_DATA_WID-1:M4_E_WID] <= 0; + word_out[M4_E_WID-1:0] <= err_prev; finish_cmd <= 1; end - `CONTROL_LOOP_Z: begin - word_out[`DATA_WID-1:DAC_DATA_WID] <= 0; + M4_CONTROL_LOOP_Z: begin + word_out[M4_DATA_WID-1:DAC_DATA_WID] <= 0; word_out[DAC_DATA_WID-1:0] <= stored_dac_val; finish_cmd <= 1; end - `CONTROL_LOOP_CYCLES: begin - word_out[`DATA_WID-1:CYCLE_COUNT_WID] <= 0; + M4_CONTROL_LOOP_CYCLES: begin + word_out[M4_DATA_WID-1:CYCLE_COUNT_WID] <= 0; word_out[CYCLE_COUNT_WID-1:0] <= last_timer; finish_cmd <= 0; end @@ -403,4 +406,3 @@ always @ (posedge clk) begin end endmodule -`undefineall diff --git a/firmware/rtl/control_loop/control_loop_cmds.m4 b/firmware/rtl/control_loop/control_loop_cmds.m4 new file mode 100644 index 0000000..c561bee --- /dev/null +++ b/firmware/rtl/control_loop/control_loop_cmds.m4 @@ -0,0 +1,11 @@ +generate_macro(CONTROL_LOOP_NOOP, 0) +generate_macro(CONTROL_LOOP_STATUS, 1) +generate_macro(CONTROL_LOOP_SETPT, 2) +generate_macro(CONTROL_LOOP_P, 3) +generate_macro(CONTROL_LOOP_I, 4) +generate_macro(CONTROL_LOOP_ERR, 5) +generate_macro(CONTROL_LOOP_Z, 6) +generate_macro(CONTROL_LOOP_CYCLES, 7) +generate_macro(CONTROL_LOOP_DELAY, 8) +generate_macro(CONTROL_LOOP_CMD_WIDTH, 8) +generate_macro(CONTROL_LOOP_WRITE_BIT, (1 << (M4_CONTROL_LOOP_CMD_WIDTH-1))) diff --git a/firmware/rtl/control_loop/control_loop_cmds.vh b/firmware/rtl/control_loop/control_loop_cmds.vh deleted file mode 100644 index 02b0b07..0000000 --- a/firmware/rtl/control_loop/control_loop_cmds.vh +++ /dev/null @@ -1,11 +0,0 @@ -`define CONTROL_LOOP_NOOP 0 -`define CONTROL_LOOP_STATUS 1 -`define CONTROL_LOOP_SETPT 2 -`define CONTROL_LOOP_P 3 -`define CONTROL_LOOP_I 4 -`define CONTROL_LOOP_ERR 5 -`define CONTROL_LOOP_Z 6 -`define CONTROL_LOOP_CYCLES 7 -`define CONTROL_LOOP_DELAY 8 -`define CONTROL_LOOP_CMD_WIDTH 8 -`define CONTROL_LOOP_WRITE_BIT (1 << (`CONTROL_LOOP_CMD_WIDTH-1)) diff --git a/firmware/rtl/control_loop/control_loop_math.v b/firmware/rtl/control_loop/control_loop_math.v.m4 similarity index 75% rename from firmware/rtl/control_loop/control_loop_math.v rename to firmware/rtl/control_loop/control_loop_math.v.m4 index c3e12f0..2c6dab8 100644 --- a/firmware/rtl/control_loop/control_loop_math.v +++ b/firmware/rtl/control_loop/control_loop_math.v.m4 @@ -1,3 +1,5 @@ +m4_changequote(`⟨', `⟩') +m4_changecom(⟨/*⟩, ⟨*/⟩) /*************** Precision ************** * The control loop is designed around these values, but generally * does not hardcode them. @@ -25,18 +27,18 @@ module control_loop_math #( parameter CONSTS_WHOLE = 21, parameter CONSTS_FRAC = 43, -`define CONSTS_WID (CONSTS_WHOLE + CONSTS_FRAC) +m4_define(M4_CONSTS_WID, (CONSTS_WHOLE + CONSTS_FRAC)) parameter CONSTS_SIZ=7, parameter ADC_WID = 18, - parameter [`CONSTS_WID-1:0] SEC_PER_CYCLE = 'b10101011110011000, + parameter [M4_CONSTS_WID-1:0] SEC_PER_CYCLE = 'b10101011110011000, /* The conversion between the ADC bit (20/2**18) and DAC bit (20.48/2**20) * is 0.256. */ - parameter [`CONSTS_WID-1:0] ADC_TO_DAC = 64'b0100000110001001001101110100101111000110101, + parameter [M4_CONSTS_WID-1:0] ADC_TO_DAC = 64'b0100000110001001001101110100101111000110101, parameter CYCLE_COUNT_WID = 18, parameter DAC_WID = 20 -`define E_WID (DAC_WID + 1) +m4_define(M4_E_WID, (DAC_WID + 1)) ) ( input clk, input arm, @@ -44,23 +46,23 @@ module control_loop_math #( input signed [ADC_WID-1:0] setpt, input signed [ADC_WID-1:0] measured, - input signed [`CONSTS_WID-1:0] cl_P, - input signed [`CONSTS_WID-1:0] cl_I, + input signed [M4_CONSTS_WID-1:0] cl_P, + input signed [M4_CONSTS_WID-1:0] cl_I, input signed [CYCLE_COUNT_WID-1:0] cycles, - input signed [`E_WID-1:0] e_prev, - input signed [`CONSTS_WID-1:0] adjval_prev, + input signed [M4_E_WID-1:0] e_prev, + input signed [M4_CONSTS_WID-1:0] adjval_prev, input signed [DAC_WID-1:0] stored_dac_val, `ifdef DEBUG_CONTROL_LOOP_MATH - output reg [`CONSTS_WID-1:0] dt_reg, - output reg [`CONSTS_WID-1:0] idt_reg, - output reg [`CONSTS_WID-1:0] epidt_reg, - output reg [`CONSTS_WID-1:0] ep_reg, + output reg [M4_CONSTS_WID-1:0] dt_reg, + output reg [M4_CONSTS_WID-1:0] idt_reg, + output reg [M4_CONSTS_WID-1:0] epidt_reg, + output reg [M4_CONSTS_WID-1:0] ep_reg, `endif - output reg signed [`E_WID-1:0] e_cur, + output reg signed [M4_E_WID-1:0] e_cur, output signed [DAC_WID-1:0] new_dac_val, - output signed [`CONSTS_WID-1:0] adj_val + output signed [M4_CONSTS_WID-1:0] adj_val ); /******* @@ -69,16 +71,16 @@ module control_loop_math #( * to be a 64 bit output, according to fixed-point rules. */ -reg signed [`CONSTS_WID-1:0] a1; -reg signed [`CONSTS_WID-1:0] a2; +reg signed [M4_CONSTS_WID-1:0] a1; +reg signed [M4_CONSTS_WID-1:0] a2; /* verilator lint_off UNUSED */ -wire signed [`CONSTS_WID+`CONSTS_WID-1:0] out_untrunc; +wire signed [M4_CONSTS_WID+M4_CONSTS_WID-1:0] out_untrunc; wire mul_fin; reg mul_arm = 0; boothmul #( - .A1_LEN(`CONSTS_WID), - .A2_LEN(`CONSTS_WID), + .A1_LEN(M4_CONSTS_WID), + .A2_LEN(M4_CONSTS_WID), .A2LEN_SIZ(CONSTS_SIZ) ) multiplier ( .a1(a1), @@ -95,11 +97,11 @@ boothmul #( * Q(2X).Y */ -`define OUT_RTRUNC_WID (`CONSTS_WID+`CONSTS_WID-CONSTS_FRAC) -wire signed [`OUT_RTRUNC_WID-1:0] out_rtrunc - = out_untrunc[`CONSTS_WID+`CONSTS_WID-1:CONSTS_FRAC]; +m4_define(M4_OUT_RTRUNC_WID, (M4_CONSTS_WID+M4_CONSTS_WID-CONSTS_FRAC)) +wire signed [M4_OUT_RTRUNC_WID-1:0] out_rtrunc + = out_untrunc[M4_CONSTS_WID+M4_CONSTS_WID-1:CONSTS_FRAC]; -wire signed [`CONSTS_WID-1:0] mul_out; +wire signed [M4_CONSTS_WID-1:0] mul_out; /*************************** * Saturate higher X bits away. @@ -107,7 +109,7 @@ wire signed [`CONSTS_WID-1:0] mul_out; */ intsat #( - .IN_LEN(`OUT_RTRUNC_WID), + .IN_LEN(M4_OUT_RTRUNC_WID), .LTRUNC(CONSTS_WHOLE) ) multiplier_saturate ( .inp(out_rtrunc), @@ -118,11 +120,11 @@ intsat #( * Safely get rid of high bit in addition. ************************/ -reg signed [`CONSTS_WID+1-1:0] add_sat; -wire signed [`CONSTS_WID-1:0] saturated_add; +reg signed [M4_CONSTS_WID+1-1:0] add_sat; +wire signed [M4_CONSTS_WID-1:0] saturated_add; intsat #( - .IN_LEN(`CONSTS_WID + 1), + .IN_LEN(M4_CONSTS_WID + 1), .LTRUNC(1) ) addition_saturate ( .inp(add_sat), @@ -168,8 +170,8 @@ localparam CALCULATE_NEW_DAC_VALUE_PART_2 = 11; localparam WAIT_ON_DISARM = 8; reg [4:0] state = WAIT_ON_ARM; -reg signed [`CONSTS_WID+1-1:0] tmpstore = 0; -wire signed [`CONSTS_WID-1:0] tmpstore_view = tmpstore[`CONSTS_WID-1:0]; +reg signed [M4_CONSTS_WID+1-1:0] tmpstore = 0; +wire signed [M4_CONSTS_WID-1:0] tmpstore_view = tmpstore[M4_CONSTS_WID-1:0]; always @ (posedge clk) begin @@ -185,8 +187,8 @@ always @ (posedge clk) begin end CALCULATE_ERR: begin /* Sign-extend */ - a1[`CONSTS_WID-1:CONSTS_FRAC + ADC_WID + 1] <= - {(`CONSTS_WID-(CONSTS_FRAC + ADC_WID + 1)){a1[ADC_WID+1-1+CONSTS_FRAC]}}; + a1[M4_CONSTS_WID-1:CONSTS_FRAC + ADC_WID + 1] <= + {(M4_CONSTS_WID-(CONSTS_FRAC + ADC_WID + 1)){a1[ADC_WID+1-1+CONSTS_FRAC]}}; a2 <= ADC_TO_DAC; mul_arm <= 1; state <= CALCULATE_DAC_E; @@ -195,7 +197,7 @@ always @ (posedge clk) begin if (mul_fin) begin /* Discard other bits. This works without saturation because * CONSTS_WHOLE = E_WID. */ - e_cur <= mul_out[`CONSTS_WID-1:CONSTS_FRAC]; + e_cur <= mul_out[M4_CONSTS_WID-1:CONSTS_FRAC]; a1 <= SEC_PER_CYCLE; /* No sign extension, cycles is positive */ @@ -228,7 +230,7 @@ always @ (posedge clk) begin idt_reg <= mul_out; `endif - a2 <= {{(CONSTS_WHOLE-`E_WID){e_cur[`E_WID-1]}},e_cur, {(CONSTS_FRAC){1'b0}}}; + a2 <= {{(CONSTS_WHOLE-M4_E_WID){e_cur[M4_E_WID-1]}},e_cur, {(CONSTS_FRAC){1'b0}}}; state <= CALCULATE_EPIDT; end CALCULATE_EPIDT: @@ -237,14 +239,14 @@ always @ (posedge clk) begin mul_arm <= 1; end else if (mul_fin) begin mul_arm <= 0; - tmpstore <= {mul_out[`CONSTS_WID-1],mul_out}; + tmpstore <= {mul_out[M4_CONSTS_WID-1],mul_out}; `ifdef DEBUG_CONTROL_LOOP_MATH epidt_reg <= mul_out; `endif a1 <= cl_P; - a2 <= {{(CONSTS_WHOLE-`E_WID){e_prev[`E_WID-1]}},e_prev, {(CONSTS_FRAC){1'b0}}}; + a2 <= {{(CONSTS_WHOLE-M4_E_WID){e_prev[M4_E_WID-1]}},e_prev, {(CONSTS_FRAC){1'b0}}}; state <= CALCULATE_EP; end CALCULATE_EP: @@ -268,7 +270,7 @@ always @ (posedge clk) begin state <= CALCULATE_NEW_DAC_VALUE_PART_1; end CALCULATE_NEW_DAC_VALUE_PART_1: begin - adj_sat <= saturated_add[`CONSTS_WID-1:CONSTS_FRAC]; + adj_sat <= saturated_add[M4_CONSTS_WID-1:CONSTS_FRAC]; adj_val <= saturated_add; state <= CALCULATE_NEW_DAC_VALUE_PART_2; end @@ -296,4 +298,3 @@ end `endif endmodule -`undefineall diff --git a/firmware/rtl/control_loop/control_loop_sim_top.v b/firmware/rtl/control_loop/control_loop_sim_top.v index ccf4f1e..f77bb3f 100644 --- a/firmware/rtl/control_loop/control_loop_sim_top.v +++ b/firmware/rtl/control_loop/control_loop_sim_top.v @@ -19,6 +19,7 @@ module control_loop_sim_top #( parameter DELAY_WID = 16 )( input clk, + output in_loop, output [DAC_DATA_WID-1:0] curset, output dac_err, @@ -104,6 +105,7 @@ control_loop #( .DAC_PHASE(DAC_PHASE) ) cloop ( .clk(clk), + .in_loop(in_loop), .dac_mosi(dac_mosi), .dac_miso(dac_miso), .dac_ss_L(dac_ss_L),