diff --git a/verilog/filter/filter.v b/verilog/filter/filter.v index 65af02a..6a923ff 100644 --- a/verilog/filter/filter.v +++ b/verilog/filter/filter.v @@ -44,8 +44,8 @@ module FILTER ( //////////// internal signals ////////// reg signed [9:0] coefmem [0:11]; // coefficient memory / shift register - reg signed [15:0] state1 [0:11]; // state 1 memory / shift register - reg signed [15:0] state2 [0:11]; // state 2 memory / shift register + reg signed [15:0] state1 [0:5]; // state 1 memory / shift register + reg signed [15:0] state2 [0:5]; // state 2 memory / shift register reg signed [15:0] accu; // accumulator reg mul_start; @@ -55,6 +55,7 @@ module FILTER ( reg update_states; reg update_coeffs; reg [3:0] cur_state; + reg unsigned [2:0] section; wire mul_done; wire signed [15:0] mul_result, accu_in, mul_in; @@ -74,8 +75,8 @@ module FILTER ( ); // signal input mux for multipliers - assign mul_in = (state_sel) ? state1[11] : state2[11]; - assign accu_in = (accu_sel) ? sig_in : accu; + assign mul_in = (state_sel) ? state2[5] : state1[5]; + assign accu_in = (accu_sel) ? accu : sig_in; assign mul_coeff = coefmem[11]; assign sig_out = accu; @@ -86,10 +87,13 @@ module FILTER ( // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // reset cycle here .. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - for(i=0; i<12; i=i+1) + for(i=0; i<6; i=i+1) begin state1[i] <= 0; state2[i] <= 0; + end + for(i=0; i<12; i=i+1) + begin coefmem[i] <= 0; end @@ -104,6 +108,7 @@ module FILTER ( mul_start <= 0; cur_state <= 4'b0000; done <= 0; + section <= 0; end else begin @@ -114,13 +119,13 @@ module FILTER ( // update the filter states if necessary if (update_states == 1) begin - for(i=1; i<12; i=i+1) + for(i=1; i<6; i=i+1) begin state1[i] <= state1[i-1]; state2[i] <= state2[i-1]; end state1[0] <= accu; - state2[0] <= state1[11]; + state2[0] <= state1[5]; end // update the coefficients if necessary @@ -135,7 +140,7 @@ module FILTER ( if (coef_load == 1) begin coefmem[0] <= coef_in; - $display("Loaded coefficient: coefmem[0] = %x", coef_in); + //$display("Loaded coefficient: coefmem[0] = %xh", coef_in); end else coefmem[0] <= coefmem[11]; @@ -158,14 +163,15 @@ module FILTER ( state_sel <= 0; accu_sel <= 0; update_states <= 0; - update_coeffs <= 0; + update_coeffs <= 0; case(cur_state) 4'b0000: // IDLE state begin done <= 1; + section <= 0; if (start == 1) begin - // // state1 * coeff[0] + // state1 * coeff[0] state_sel <= 0; // state 1 as mul input mul_start <= 1; // trigger multiplier cur_state <= 4'b0001; @@ -175,18 +181,23 @@ module FILTER ( // to reach a valid state begin cur_state <= 4'b0010; + //for(i=0; i<6; i=i+1) + //begin + // $display("s1[%d] = %x", i, state1[i]); + // $display("s2[%d] = %x", i, state2[i]); + //end end 4'b0010: // wait for multiplier to complete begin if (mul_done == 1) begin cur_state <= 4'b0011; + accu_sel <= 0; // accu = sig_in + mul_result + do_accu <= 1; end end - 4'b0011: // update accu - begin - accu_sel <= 0; // accu = sig_in + mul_result - do_accu <= 1; + 4'b0011: // update accu, 1st section only! + begin cur_state <= 4'b0100; update_coeffs <= 1; // advance to coeff[1] end @@ -205,20 +216,48 @@ module FILTER ( begin if (mul_done == 1) begin + section <= section + 4'b001; // increment section number cur_state <= 4'b0111; + accu_sel <= 1; // accu = accu + mul_result + do_accu <= 1; end end 4'b0111: // update accumulator and filter states begin - accu_sel <= 1; // accu = accu + mul_result - do_accu <= 1; update_coeffs <= 1; // advance to next section.. update_states <= 1; - cur_state <= 4'b0000; + + // check if this is the last section.. + if (section==4'b0110) + cur_state <= 4'b0000; // one complete filter set done.. + else + cur_state <= 4'b1000; // next.. end - 4'b1000: // stop, for now .. + 4'b1000: begin - done <= 1; + // next section: state1 * coeff[0] + cur_state <= 4'b1001; + state_sel <= 0; // state 1 as mul input + mul_start <= 1; // trigger multiplier + end + 4'b1001: // Dummy cycle to wait for mul_done + // to reach a valid state + begin + cur_state <= 4'b1010; + end + 4'b1010: // wait for multiplier to complete + begin + if (mul_done == 1) + begin + cur_state <= 4'b1011; + accu_sel <= 1; // accu = accu + mul_result + do_accu <= 1; + end + end + 4'b1011: // update accu, 2nd..5th section only! + begin + update_coeffs <= 1; // advance to coeff[1] + cur_state <= 4'b0100; end default: cur_state <= 4'b0000; diff --git a/verilog/filter/filter_tb.v b/verilog/filter/filter_tb.v index 4ecda30..1d72da7 100644 --- a/verilog/filter/filter_tb.v +++ b/verilog/filter/filter_tb.v @@ -34,32 +34,59 @@ module FILTER_TB; rst_an = 0; sig_in = 16'h0100; - coef_in = 10'h000; // sign-magnitude + coef_in = 0; coef_load = 0; start = 0; check_finish = 0; #10 rst_an = 1; - #10 - coef_load = 1; - coef_in = 10'h21F; // sign-magnitude // load all the coefficients - for(i=1; i<12; i=i+1) - begin - #10 - coef_load = 1; - coef_in = 10'h00F; // sign-magnitude - end + #10 + coef_load = 1; + // section 1 + coef_in = {1'b0, 9'd128}; // sign-magnitude a1 = -0.25 + #10 + coef_in = {1'b1, 9'd256}; // sign-magnitude a2 = 0.5 + #10 + // section 2 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + // section 3 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + // section 4 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + // section 5 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + // section 6 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; + #10 + coef_in = {1'b0, 9'd0}; // sign-magnitude a1 = 0; #10 coef_load = 0; - #10 start = 1; #50000; check_finish = 1; end + always@(posedge clk) + begin + if ((done == 1) && (coef_load != 1)) + $display("%d", sig_out); + end + always #5 clk = !clk; diff --git a/verilog/filter/results.md b/verilog/filter/results.md new file mode 100644 index 0000000..3b3760e --- /dev/null +++ b/verilog/filter/results.md @@ -0,0 +1,34 @@ +# Results + +The testbench should approximately give the following step response results: + +(leading zeroes are okay) +- 256 +- 320 +- 208 +- 148 +- 189 +- 229 +- 219 +- 196 +- 196 +- 207 +- 210 +- 205 +- 202 +- 204 +- 206 +- 205 +- 204 +- 204 +- 205 +- 205 +- 205 +- 205 +- 205 +- 205 +- 205 +- 205 +- 205 + +Note that there might be a few +/- 1 round-off errors. diff --git a/verilog/spmul/spmul.v b/verilog/spmul/spmul.v index 1a29f15..e3e6004 100644 --- a/verilog/spmul/spmul.v +++ b/verilog/spmul/spmul.v @@ -141,10 +141,11 @@ module SPMUL ( begin domul <= 0; done <= 1; + // correct for the coeff sign bit if (coefreg[9] == 0) result_out <= {1'b0, accumulator[23:9]}; else - result_out <= {1'b1, ~accumulator[23:9]}; + result_out <= {1'b1, ~accumulator[23:9]} + 1; state <= 0; end default: