add_minus_multiply

依續輸入4個數字和運算符號,然後計算,輸出結果 example: input: 1234+ output: -0046 input: 1234- output: -022 input: 1234* ouput: 0308 line 49~59: calculate sum, minus, product line 130 ~ 148: distribute sum, minus, product to 4 digit output
mail@pastecode.io avatar
unknown
verilog
3 years ago
5.4 kB
1
Indexable
`include "global.v"
/*
`define STAT_RESET 3'b000
`define STAT_FIRST_INPUT 3'b001
`define STAT_SECOND_INPUT 3'b010
`define STAT_THIRD_INPUT 3'b011
`define STAT_FOURTH_INPUT 3'b100
`define STAT_RESULT_PLUS 3'b101
`define STAT_RESULT_MINUS 3'b110
`define STAT_RESULT_MULTIPLY 3'b111
`define BCD_NUM 4'd10
`define PLUS 4'd11
`define MINUS 4'd12
`define MULTIPLY 4'd13
`define ENTER 4'd14
`define OTHER_INPUT 4'd15
*/

module add_minus_multiply(
    output reg [3:0] out1,  // num1, dig2
    output reg [3:0] out2,  // num1, dig1
    output reg [3:0] out3,  // num2, dig2
    output reg [3:0] out4,  // num2, dig1
    input [2:0] state,
    input [3:0] in,
    input clk,
    input rst_n
);

    reg [3:0] in_delay;
    reg [2 * 4 - 1:0] in_window;       // 2 * BCD_BID_WIDTH
    wire [3:0] in_delay_next;

    reg [3:0] out1_next;
    reg [3:0] out2_next;
    reg [3:0] out3_next;
    reg [3:0] out4_next;
    
    reg [7:0] sum;                     // 0~198, smaller than 2 ^^ 8
    reg [7:0] difference;              // -99~99 -> 0~198(plus 99), smaller than 2 ^^ 8
    reg [13:0] product;                // 0~9801, smaller than 2 ^^ 14

    reg [7:0] sum_next;                // 0~198, smaller than 2 ^^ 8
    reg [7:0] difference_next;         // -99~99 -> 0~198(plus 99), smaller than 2 ^^ 8
    reg [13:0] product_next;           // 0~9801, smaller than 2 ^^ 14



    // sum, difference, product combinational
    always @* begin
        if (state == `STAT_FOURTH_INPUT) begin
            sum_next = (10 * out1 + out2) + (10 * out3 + out4);
            difference_next = (10 * out1 + out2) - (10 * out3 + out4) + 8'd99;
            product_next = (10 * out1 + out2) * (10 * out3 + out4);
        end else begin
            sum_next = sum;
            difference_next = difference;
            product = product;
        end
    end

    // sum, difference, product sequential
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            sum <= 8'd0;
            difference <= 8'd0;
            product <= 14'd0;
        end else begin
            sum <= sum_next;
            difference <= difference_next;
            product <= product_next;
        end
    end


    // in_window shift register
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            in_window = 8'b0;           // 2 * BCD_BID_WIDTH
        end else begin
            in_window = {in_window[3:0], in};
        end
    end

    // in_delay_next
    assign in_delay_next = in_window[7:4];

    // in_delay (delay 1 clk pulse)
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            in_delay <= 4'd0;
        end else begin
            in_delay <= in_delay_next;
        end
    end

    // combinational
    always @* begin
        case (state)
            `STAT_RESET: begin
                out1_next = 4'd0;
                out2_next = 4'd0;
                out3_next = 4'd0;
                out4_next = 4'd0;
            end
            `STAT_FIRST_INPUT: begin
                out1_next = in_delay;
                out2_next = out2;
                out3_next = out3;
                out4_next = out4;
            end
            `STAT_SECOND_INPUT: begin
                out1_next = out1;
                out2_next = in_delay;
                out3_next = out3;
                out4_next = out4;
            end
            `STAT_THIRD_INPUT: begin
                out1_next = out1;
                out2_next = out2;
                out3_next = in_delay;
                out4_next = out4;
            end
            `STAT_FOURTH_INPUT: begin
                out1_next = out1;
                out2_next = out2;
                out3_next = out3;
                out4_next = in_delay;
            end
            `STAT_RESULT_PLUS: begin
                out1_next = 4'd0;
                out2_next = sum / 100;
                out3_next = sum / 10 % 10;
                out4_next = sum % 10;
            end
            `STAT_RESULT_MINUS: begin
                out1_next = (difference < 8'd99) ? `MINUS : 4'd0;
                out2_next = 4'd0;
                out3_next = (difference < 8'd99) ? (8'd99 - difference) / 10
                                                 : (difference - 8'd99) / 10 ;
                out4_next = (difference < 8'd99) ? (8'd99 - difference) % 10
                                                 : (difference - 8'd99) % 10 ;
            end
            `STAT_RESULT_MULTIPLY: begin
                out1_next = product / 1000;
                out2_next = product / 100 % 10;
                out3_next = product / 10 % 10;
                out4_next = product % 10;
            end
            default: begin
                out1_next = 4'd0;
                out2_next = 4'd0;
                out3_next = 4'd0;
                out4_next = 4'd0;
            end
        endcase
    end

    // sequential
    always @(posedge clk or negedge rst_n) begin
        if (~rst_n) begin
            out1 <= 4'd0;
            out2 <= 4'd0;
            out3 <= 4'd0;
            out4 <= 4'd0;
        end else begin
            out1 <= out1_next;
            out2 <= out2_next;
            out3 <= out3_next;
            out4 <= out4_next;
        end
    end

endmodule