diff --git a/doc/hardware_notes.md b/doc/hardware_notes.md new file mode 100644 index 0000000..6e472e9 --- /dev/null +++ b/doc/hardware_notes.md @@ -0,0 +1,14 @@ +This document is for recording notes on measurements done on Upslion +running on actual FPGAs. + +Commit: `9c2731ad8d794d0b3c46999a40f0064f2b020c69` +FPGA: Arty A7-100T +F4PGA commit: `f43bb728b1bd9ef3807ef65bcf6b6629e0fa71f5` + +ADCs: + +SPI clocks take about 10ns to start going up and down from low voltage. They +rise to about 500mV in that time. MISO oscillates up and down up to 50mV with +no data present, rising and stays at that until it oscillates down. Should not +be a problem. Probably capacitance/crosstalk. Ringing of about 40mV on clock +and SS. diff --git a/firmware/Makefile b/firmware/Makefile index c5f66e6..6aeedf3 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -10,6 +10,7 @@ build/digilent_arty/digilent_arty.bit: soc.py python3 soc.py clean: rm -rf build csr.json overlay.config overlay.dts pin_io.h + cd rtl && make clean overlay.dts overlay.cmake: csr.json litex_json2dts_zephyr.py # NOTE: Broken in LiteX 2022.4. $(DEVICETREE_GEN_DIR)/litex_json2dts_zephyr.py --dts overlay.dts --config overlay.cmake csr.json diff --git a/firmware/rtl/control_loop/Makefile b/firmware/rtl/control_loop/Makefile index dface15..9330851 100644 --- a/firmware/rtl/control_loop/Makefile +++ b/firmware/rtl/control_loop/Makefile @@ -49,7 +49,7 @@ obj_dir/Vcontrol_loop_sim_top: obj_dir/Vcontrol_loop_sim_top.mk control_loop_cmd ####### Codegen ######## include ../common.makefile -CODEGEN_FILES=control_loop_cmds.h boothmul.v control_loop_math.v control_loop.v control_loop_cmds.vh +CODEGEN_FILES=control_loop_cmds.h boothmul_preprocessed.v control_loop_math.v control_loop.v control_loop_cmds.vh codegen: ${CODEGEN_FILES} control_loop_cmds.vh: control_loop_cmds.m4 m4 -P control_loop_cmds.vh.m4 > control_loop_cmds.vh diff --git a/firmware/rtl/control_loop/boothmul.v.m4 b/firmware/rtl/control_loop/boothmul.v.m4 deleted file mode 100644 index a5ceffa..0000000 --- a/firmware/rtl/control_loop/boothmul.v.m4 +++ /dev/null @@ -1,146 +0,0 @@ -m4_changequote(`⟨', `⟩') -m4_changecom(⟨/*⟩, ⟨*/⟩) -/* Booth Multiplication v1.0 - * Written by Peter McGoron, 2022. - * - * This source describes Open Hardware and is licensed under the - * CERN-OHL-W v2. - * You may redistribute and modify this documentation and make products using - * it under the terms of the CERN-OHL-W v2 (https:/cern.ch/cern-ohl), or, at - * your option, any later version. - * - * This documentation is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, - * INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR - * A PARTICULAR PURPOSE. Please see the CERN-OHL-W v2 for applicable - * conditions. - * - * Source location: https://software.mcgoron.com/peter/boothmul - */ - -module boothmul -#( - parameter A1_LEN = 32, - parameter A2_LEN = 32, - // AZLEN_SIZ = floor(log2(A2_LEN + 2) + 1). - // It must be able to store A2_LEN + 2. - parameter A2LEN_SIZ = 6 -) -( - input clk, - input arm, - input [A1_LEN-1:0] a1, - input [A2_LEN-1:0] a2, -m4_define(M4_OUT_LEN, (A1_LEN + A2_LEN)) - output [M4_OUT_LEN-1:0] outn, -`ifdef DEBUG - 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 -); - -/*********************** - * Booth Parameters - **********************/ - -m4_define(M4_REG_LEN, (M4_OUT_LEN + 2)) - -/* The Booth multiplication algorithm is a sequential algorithm for - * twos-compliment integers. - * - * Let REG_LEN be equal to 1 + len(a1) + len(a2) + 1. - * Let P, S, and A be of length REG_LEN. - * Let A = a1 << len(a2) + 1, where a1 sign extends to the upper bit. - * Let S = -a1 << len(a2) + 1, where a1 sign extens to the upper bit. - * Let P = a2 << 1. - * - * Repeat the following len(a2) times: - * case(P[1:0]) - * 2'b00, 2'b11: P <= P >>> 1; - * 2'b01: P <= (P + A) >>> 1; - * 2'b10: P <= (P + S) >>> 1; - * endcase - * The final value is P[REG_LEN-2:1]. - * - * Wires and registers of REG_LEN length are organized like: - * - * /Overflow bit - * [M][ REG_LEN ][0] - * [M][ A1_LEN ][ A2_LEN ][0] - */ - -reg [A1_LEN-1:0] a1_reg; - -wire [M4_REG_LEN-1:0] a; -assign a[A2_LEN:0] = 0; -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 [M4_REG_LEN-1:0] s; -assign s[A2_LEN:0] = 0; -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 [M4_REG_LEN-1:0] p; -wire signed [M4_REG_LEN-1:0] p_signed; -assign p_signed = p; - -assign outn = p[M4_REG_LEN-2:1]; - -/********************** - * Loop Implementation - *********************/ - -reg[A2LEN_SIZ-1:0] loop_accul = 0; - -`ifdef DEBUG -assign debug_a = a; -assign debug_s = s; -assign debug_p = p; -assign debug_state = loop_accul; -`endif - -always @ (posedge clk) begin - if (!arm) begin - loop_accul <= 0; - fin <= 0; - end else if (loop_accul == 0) begin - p[0] <= 0; - p[A2_LEN:1] <= a2; - p[M4_REG_LEN-1:A2_LEN+1] <= 0; - - a1_reg <= a1; - - loop_accul <= loop_accul + 1; - /* verilator lint_off WIDTH */ - end else if (loop_accul < A2_LEN + 1) begin - /* verilator lint_on WIDTH */ - /* The loop counter starts from 1, so it must go to - * A2_LEN + 1 exclusive. - * (i = 0; i < len; i++) - * becomes (i = 1; i < len + 1; i++) - */ - loop_accul <= loop_accul + 1; - case (p[1:0]) - 2'b00, 2'b11: p <= p_signed >>> 1; - 2'b10: p <= (p_signed + s_signed) >>> 1; - 2'b01: p <= (p_signed + a_signed) >>> 1; - endcase - end else begin - fin <= 1; - end -end - -`ifdef BOOTH_SIM -initial begin - $dumpfile("booth.vcd"); - $dumpvars; -end -`endif - -endmodule diff --git a/firmware/soc.py b/firmware/soc.py index 2ffa2c4..74d6398 100644 --- a/firmware/soc.py +++ b/firmware/soc.py @@ -30,7 +30,7 @@ io = [ ("test_clock", 0, Pins("P18"), IOStandard("LVCMOS33")) ] -# TODO: Generate widths based off of include files (m4 generated) +# TODO: Assign widths to ADCs here using parameters class Base(Module, AutoCSR): """ The subclass AutoCSR will automatically make CSRs related @@ -190,7 +190,7 @@ class CryoSNOM1SoC(SoCCore): platform.add_source("rtl/spi/spi_master_ss_no_read_preprocessed.v") platform.add_source("rtl/control_loop/sign_extend.v") platform.add_source("rtl/control_loop/intsat.v") - platform.add_source("rtl/control_loop/boothmul.v") + platform.add_source("rtl/control_loop/boothmul_preprocessed.v") platform.add_source("rtl/control_loop/control_loop_math.v") platform.add_source("rtl/control_loop/control_loop.v") platform.add_source("rtl/waveform/bram_interface_preprocessed.v")