1// 2// Copyright 2011 Ettus Research LLC 3// Copyright 2018 Ettus Research, a National Instruments Company 4// 5// SPDX-License-Identifier: LGPL-3.0-or-later 6// 7 8 9// First halfband iterpolator 10// Implements impulse responses of the form [A 0 B 0 C .. 0 H 0.5 H 0 .. C 0 B 0 A] 11// Strobe in cannot come faster than every 4th clock cycle, 12// Strobe out cannot come faster than every 2nd clock cycle 13 14// These taps designed by halfgen4 from ldoolittle 15// myfilt = round(2^18 * halfgen4(.7/4,8)) 16 17module hb_interp 18 #(parameter IWIDTH=18, OWIDTH=18, ACCWIDTH=24) 19 (input clk, 20 input rst, 21 input bypass, 22 input [7:0] cpo, // Clocks per output, must be at least 2 23 input stb_in, 24 input [IWIDTH-1:0] data_in, 25 input stb_out, 26 output reg [OWIDTH-1:0] data_out); 27 28 localparam MWIDTH = ACCWIDTH-2; 29 localparam CWIDTH = 18; 30 31 reg [CWIDTH-1:0] coeff1, coeff2; 32 reg [3:0] addr_a, addr_b, addr_c, addr_d, addr_e; 33 wire [IWIDTH-1:0] data_a, data_b, data_c, data_d, data_e, sum1, sum2; 34 wire [35:0] prod1, prod2; 35 36 reg [2:0] phase, phase_d1, phase_d2, phase_d3, phase_d4, phase_d5; 37 38 always @(posedge clk) 39 if(rst) 40 phase <= 0; 41 else 42 if(stb_in) 43 phase <= 1; 44 else if(phase==4) 45 phase <= 0; 46 else if(phase!=0) 47 phase <= phase + 1; 48 always @(posedge clk) phase_d1 <= phase; 49 always @(posedge clk) phase_d2 <= phase_d1; 50 always @(posedge clk) phase_d3 <= phase_d2; 51 always @(posedge clk) phase_d4 <= phase_d3; 52 always @(posedge clk) phase_d5 <= phase_d4; 53 54 srl #(.WIDTH(IWIDTH)) srl_a 55 (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_a),.out(data_a)); 56 srl #(.WIDTH(IWIDTH)) srl_b 57 (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_b),.out(data_b)); 58 srl #(.WIDTH(IWIDTH)) srl_c 59 (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_c),.out(data_c)); 60 srl #(.WIDTH(IWIDTH)) srl_d 61 (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_d),.out(data_d)); 62 srl #(.WIDTH(IWIDTH)) srl_e 63 (.clk(clk),.rst(rst),.write(stb_in),.in(data_in),.addr(addr_e),.out(data_e)); 64 65 always @* 66 case(phase) 67 1 : begin addr_a = 0; addr_b = 15; end 68 2 : begin addr_a = 1; addr_b = 14; end 69 3 : begin addr_a = 2; addr_b = 13; end 70 4 : begin addr_a = 3; addr_b = 12; end 71 default : begin addr_a = 0; addr_b = 15; end 72 endcase // case(phase) 73 74 always @* 75 case(phase) 76 1 : begin addr_c = 4; addr_d = 11; end 77 2 : begin addr_c = 5; addr_d = 10; end 78 3 : begin addr_c = 6; addr_d = 9; end 79 4 : begin addr_c = 7; addr_d = 8; end 80 default : begin addr_c = 4; addr_d = 11; end 81 endcase // case(phase) 82 83 always @* 84 case(cpo) 85 2 : addr_e <= 9; 86 3,4,5,6,7,8 : addr_e <= 8; 87 default : addr_e <= 7; // This case works for 256, which = 0 due to overflow outside this block 88 endcase // case(cpo) 89 90 always @* // Outer coeffs 91 case(phase_d1) 92 1 : coeff1 = -107; 93 2 : coeff1 = 445; 94 3 : coeff1 = -1271; 95 4 : coeff1 = 2959; 96 default : coeff1 = -107; 97 endcase // case(phase) 98 99 always @* // Inner coeffs 100 case(phase_d1) 101 1 : coeff2 = -6107; 102 2 : coeff2 = 11953; 103 3 : coeff2 = -24706; 104 4 : coeff2 = 82359; 105 default : coeff2 = -6107; 106 endcase // case(phase) 107 108 add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add1 (.clk(clk),.in1(data_a),.in2(data_b),.sum(sum1)); 109 add2_reg /*_and_round_reg*/ #(.WIDTH(IWIDTH)) add2 (.clk(clk),.in1(data_c),.in2(data_d),.sum(sum2)); 110 // sum1, sum2 available on phase_d1 111 112 wire do_mult = 1; 113 MULT18X18S mult1(.C(clk), .CE(do_mult), .R(rst), .P(prod1), .A(coeff1), .B(sum1) ); 114 MULT18X18S mult2(.C(clk), .CE(do_mult), .R(rst), .P(prod2), .A(coeff2), .B(sum2) ); 115 // prod1, prod2 available on phase_d2 116 117 wire [MWIDTH-1:0] sum_of_prod; 118 119 add2_and_round_reg #(.WIDTH(MWIDTH)) 120 add3 (.clk(clk),.in1(prod1[35:36-MWIDTH]),.in2(prod2[35:36-MWIDTH]),.sum(sum_of_prod)); 121 // sum_of_prod available on phase_d3 122 123 wire [ACCWIDTH-1:0] acc_out; 124 125 wire clear = (phase_d3 == 1); 126 wire do_acc = (phase_d3 != 0); 127 128 acc #(.IWIDTH(MWIDTH),.OWIDTH(ACCWIDTH)) //IJB rst 129 acc (.clk(clk),.clear(rst|clear),.acc(do_acc),.in(sum_of_prod),.out(acc_out)); 130 // acc_out available on phase_d4 131 132 wire [ACCWIDTH-6:0] clipped_acc; 133 clip #(.bits_in(ACCWIDTH),.bits_out(ACCWIDTH-5)) final_clip(.in(acc_out),.out(clipped_acc)); 134 135 reg [ACCWIDTH-6:0] clipped_reg; 136 always @(posedge clk) 137 if (rst) 138 clipped_reg <= 0; 139 else if(phase_d4 == 4) 140 clipped_reg <= clipped_acc; 141 // clipped_reg available on phase_d5 142 143 wire [OWIDTH-1:0] data_out_round; 144 round #(.bits_in(ACCWIDTH-5),.bits_out(OWIDTH)) final_round (.in(clipped_reg),.out(data_out_round)); 145 146 reg odd; 147 always @(posedge clk) 148 if(rst) 149 odd <= 0; 150 else if(stb_in) 151 odd <= 0; 152 else if(stb_out) 153 odd <= 1; 154 155 always @(posedge clk) 156 if (rst) 157 data_out <= 0; 158 else if(bypass) 159 data_out <= data_in; 160 else if(stb_out) 161 if(odd) 162 data_out <= data_e; 163 else 164 data_out <= data_out_round; 165 166 // data_out available on phase_d6 167 168endmodule // hb_interp 169