`timescale 1ns / 1ns // Ultra-simple (2-tap) interpolating FIR filter // Input sig_in comes in clocked by clk40 // Output dac_out goes out clocked by clk80 // The single coefficient must be adjusted by the dkcm_bus. // The nominal value for the LLRF system is -1.414, but other values // are interesting for test purposes (e.g., +1.414 will deliver // 10/70 MHz instead of 30/50 MHz output). // You get a coefficient of -1.414 by pushing -1.414*1024 = -1448 into // the 12-bit signed coefficient of dkcm. // Proper phase relationship of clk40 and clk80 is essential. // Input is assumed signed. Output is also signed, so the // high order bit needs flipping before it actually gets sent // to the DAC902. module afterburner(clk40, sig_in, clk80, dac_out, clk_host, dkcm_bus); input clk40, clk80, clk_host; input [11:0] sig_in; output [11:0] dac_out; reg [11:0] dac_out; input [20:0] dkcm_bus; reg [11:0] prev_sig_in, prev_product; wire [23:0] product; // sign-extend before adding wire [12:0] average = {sig_in[11],sig_in} + {prev_sig_in[11],prev_sig_in}; // var, product, clk, dkcm_bus, ident dkcm_bussed scale(average[12:1], product, clk_host, dkcm_bus, 3'b000); always @(posedge clk40) begin prev_sig_in <= sig_in; // clip prev_product <= ((product[23:21]==3'b000) | (product[23:21]==3'b111)) ? product[21:10] : (product[23]? 12'b100000000000 : 12'b011111111111 ); end always @(posedge clk80) dac_out <= clk40 ? prev_product : prev_sig_in; endmodule