// // 16bit x 10bit signed serial/parallel multiplier. // // Niels Moseley - Moseley Instruments 2017 // http://www.moseleyinstruments.com // // // module SPMUL ( clk, rst_an, sig_in, coef_in, result_out, start, done ); //////////// CLOCK ////////// input clk; //////////// RESET, ACTIVE LOW ////////// input rst_an; //////////// MULTIPLIER INPUTS ////////// input signed [15:0] sig_in; input signed [9:0] coef_in; input start; //////////// MULTIPLIER OUTPUT ////////// output reg signed [15:0] result_out; output reg done; //////////// internal signals ////////// reg signed [24:0] accumulator; reg signed [9:0] coefreg; reg signed [15:0] sigreg; reg [3:0] state; // state machine state wire signed [15:0] bmul; reg domul,accu_clr; // accumulator always @(posedge clk, negedge rst_an) begin if ((rst_an == 0) || (accu_clr == 1)) begin accumulator <= 0; end else if (domul == 1) begin // note: leave coefreg[9] untouched // as this is the sign bit... if (coefreg[8] == 1'b1) accumulator <= $signed({accumulator[23:0], 1'b0}) + sigreg; else accumulator <= {accumulator[23:0], 1'b0}; coefreg[8:0] <= {coefreg[7:0], 1'b0}; end end always @(posedge clk, negedge rst_an) begin if (rst_an == 0) begin // reset values result_out <= 0; done <= 1; // always be ready to start.. coefreg <= 0; sigreg <= 0; state <= 0; domul <= 0; accu_clr <= 1; end else begin // default values accu_clr <= 0; done <= 0; domul <= 0; state <= state + 4'b0001; case(state) 4'b0000: // IDLE state begin coefreg <= coef_in; sigreg <= sig_in; accu_clr <= 1; if (start == 1) begin state <= 4'b0001; end else begin done <= 1; state <= 4'b0000; end end 4'b0001: begin domul <= 1; end 4'b0010: begin domul <= 1; end 4'b0011: begin domul <= 1; end 4'b0100: begin domul <= 1; end 4'b0101: begin domul <= 1; end 4'b0110: begin domul <= 1; end 4'b0111: begin domul <= 1; end 4'b1000: begin domul <= 1; end 4'b1001: begin domul <= 1; end 4'b1010: begin domul <= 0; end 4'b1011: begin domul <= 0; done <= 1; // correct for the coeff sign bit if (coefreg[9] == 0) result_out <= accumulator[24:9]; else result_out <= $signed(~accumulator[24:9]) + 1; state <= 0; end default: state <= 0; endcase end end endmodule