Attention

This documentation is a work in progress. Expect to see errors and unfinished things.

multiply_accumulate Source File

 1`timescale 1ns / 1ns
 2
 3/// TL;DR
 4/// accumulated += ((constant * signal) >>> downscale) + correction
 5///
 6/// Multiply a `constant` K to input `signal` and accumulate the result on `enable`.
 7///
 8/// Notice `downscale`, this is meant to downscale the input into the accumulator
 9/// Useful in times of high "natural" integration gain: like running with a superconducting cavity
10///
11/// `correction` comes from some externally-supplied feedforward, maybe derived from the previous pulse
12module multiply_accumulate #(
13     parameter CW = 17,
14     parameter KW = 18,  // Constant Width
15     parameter SW = 18,  // Signal Width
16     parameter OW = 21   // OutputWidth: Desired bitwidth of the accumulator
17) (
18     input clk,
19     input reset,
20     input enable,
21     input signed [CW-1:0] correction,
22     input [3:0] downscale,
23     input signed [KW-1:0] constant,
24     input signed [SW-1:0] signal,
25     output signed [OW-1:0] accumulated
26);
27
28`define SAT(x,old,new) ((~|x[old:new] | &x[old:new]) ? x[new:0] : {x[old],{new{~x[old]}}})
29
30reg signed [KW+SW-1: 0] integrator_in_large=0;
31reg signed [OW-1: 0] integrator_sum=0;
32
33wire signed [OW-1: 0] integrator_in = $signed(integrator_in_large[KW+SW-1: KW+SW-1 - 20]) >>> downscale;
34wire signed [OW:0] integrator_sum_pre = (enable? integrator_in + correction : 0) + integrator_sum;
35
36always @ (posedge clk) begin
37     if (reset) integrator_sum <= 0;
38     else begin
39             integrator_in_large <= signal * constant;
40             // TODO: Turning off the bit error for now
41             integrator_sum <= `SAT(integrator_sum_pre, OW, OW-1);
42     end
43end
44
45`undef SAT
46
47assign accumulated = integrator_sum;
48
49endmodule