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