lm32_mc_arithmetic.v

Sun, 04 Apr 2010 22:05:07 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 04 Apr 2010 22:05:07 +0100
changeset 3
b153470d41c5
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rw-r--r--

remove more Lattice-specific fluff

Code now synthesizes properly on Altera Quartus 9.0 build 235

     1 // =============================================================================
     2 //                           COPYRIGHT NOTICE
     3 // Copyright 2006 (c) Lattice Semiconductor Corporation
     4 // ALL RIGHTS RESERVED
     5 // This confidential and proprietary software may be used only as authorised by
     6 // a licensing agreement from Lattice Semiconductor Corporation.
     7 // The entire notice above must be reproduced on all authorized copies and
     8 // copies may only be made to the extent permitted by a licensing agreement from
     9 // Lattice Semiconductor Corporation.
    10 //
    11 // Lattice Semiconductor Corporation        TEL : 1-800-Lattice (USA and Canada)
    12 // 5555 NE Moore Court                            408-826-6000 (other locations)
    13 // Hillsboro, OR 97124                     web  : http://www.latticesemi.com/
    14 // U.S.A                                   email: techsupport@latticesemi.com
    15 // =============================================================================/
    16 //                         FILE DETAILS
    17 // Project          : LatticeMico32
    18 // File             : lm_mc_arithmetic.v
    19 // Title            : Multi-cycle arithmetic unit.
    20 // Dependencies     : lm32_include.v
    21 // Version          : 6.1.17
    22 //                  : Initial Release
    23 // Version          : 7.0SP2, 3.0
    24 //                  : No Change
    25 // Version          : 3.1
    26 //                  : No Change
    27 // =============================================================================
    29 `include "lm32_include.v"
    31 `define LM32_MC_STATE_RNG         2:0
    32 `define LM32_MC_STATE_IDLE        3'b000
    33 `define LM32_MC_STATE_MULTIPLY    3'b001
    34 `define LM32_MC_STATE_MODULUS     3'b010   
    35 `define LM32_MC_STATE_DIVIDE      3'b011 
    36 `define LM32_MC_STATE_SHIFT_LEFT  3'b100
    37 `define LM32_MC_STATE_SHIFT_RIGHT 3'b101
    39 /////////////////////////////////////////////////////
    40 // Module interface
    41 /////////////////////////////////////////////////////
    43 module lm32_mc_arithmetic (
    44     // ----- Inputs -----
    45     clk_i,
    46     rst_i,
    47     stall_d,
    48     kill_x,
    49 `ifdef CFG_MC_DIVIDE_ENABLED
    50     divide_d,
    51     modulus_d,
    52 `endif
    53 `ifdef CFG_MC_MULTIPLY_ENABLED
    54     multiply_d,
    55 `endif
    56 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
    57     shift_left_d,
    58     shift_right_d,
    59     sign_extend_d,
    60 `endif
    61     operand_0_d,
    62     operand_1_d,
    63     // ----- Ouputs -----
    64     result_x,
    65 `ifdef CFG_MC_DIVIDE_ENABLED
    66     divide_by_zero_x,
    67 `endif
    68     stall_request_x
    69     );
    71 /////////////////////////////////////////////////////
    72 // Inputs
    73 /////////////////////////////////////////////////////
    75 input clk_i;                                    // Clock
    76 input rst_i;                                    // Reset
    77 input stall_d;                                  // Stall instruction in D stage
    78 input kill_x;                                   // Kill instruction in X stage
    79 `ifdef CFG_MC_DIVIDE_ENABLED
    80 input divide_d;                                 // Perform divide
    81 input modulus_d;                                // Perform modulus
    82 `endif
    83 `ifdef CFG_MC_MULTIPLY_ENABLED
    84 input multiply_d;                               // Perform multiply
    85 `endif
    86 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
    87 input shift_left_d;                             // Perform left shift
    88 input shift_right_d;                            // Perform right shift
    89 input sign_extend_d;                            // Whether to sign-extend (arithmetic) or zero-extend (logical)
    90 `endif
    91 input [`LM32_WORD_RNG] operand_0_d;
    92 input [`LM32_WORD_RNG] operand_1_d;
    94 /////////////////////////////////////////////////////
    95 // Outputs
    96 /////////////////////////////////////////////////////
    98 output [`LM32_WORD_RNG] result_x;               // Result of operation
    99 reg    [`LM32_WORD_RNG] result_x;
   100 `ifdef CFG_MC_DIVIDE_ENABLED
   101 output divide_by_zero_x;                        // A divide by zero was attempted
   102 reg    divide_by_zero_x;
   103 `endif
   104 output stall_request_x;                         // Request to stall pipeline from X stage back
   105 wire   stall_request_x;
   107 /////////////////////////////////////////////////////
   108 // Internal nets and registers 
   109 /////////////////////////////////////////////////////
   111 reg [`LM32_WORD_RNG] p;                         // Temporary registers
   112 reg [`LM32_WORD_RNG] a;
   113 reg [`LM32_WORD_RNG] b;
   114 `ifdef CFG_MC_DIVIDE_ENABLED
   115 wire [32:0] t;
   116 `endif
   118 reg [`LM32_MC_STATE_RNG] state;                 // Current state of FSM
   119 reg [5:0] cycles;                               // Number of cycles remaining in the operation
   121 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   122 reg sign_extend_x;                              // Whether to sign extend of zero extend right shifts
   123 wire fill_value;                                // Value to fill with for right barrel-shifts
   124 `endif
   126 /////////////////////////////////////////////////////
   127 // Combinational logic
   128 /////////////////////////////////////////////////////
   130 // Stall pipeline while any operation is being performed
   131 assign stall_request_x = state != `LM32_MC_STATE_IDLE;
   133 `ifdef CFG_MC_DIVIDE_ENABLED
   134 // Subtraction
   135 assign t = {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]} - b;
   136 `endif
   138 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   139 // Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
   140 assign fill_value = (sign_extend_x == `TRUE) & b[`LM32_WORD_WIDTH-1];
   141 `endif
   143 /////////////////////////////////////////////////////
   144 // Sequential logic
   145 /////////////////////////////////////////////////////
   147 // Perform right shift
   148 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
   149 begin
   150     if (rst_i == `TRUE)
   151     begin
   152         cycles <= {6{1'b0}};
   153         p <= {`LM32_WORD_WIDTH{1'b0}};
   154         a <= {`LM32_WORD_WIDTH{1'b0}};
   155         b <= {`LM32_WORD_WIDTH{1'b0}};
   156 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   157         sign_extend_x <= 1'b0;
   158 `endif
   159 `ifdef CFG_MC_DIVIDE_ENABLED
   160         divide_by_zero_x <= `FALSE;
   161 `endif
   162         result_x <= {`LM32_WORD_WIDTH{1'b0}};
   163         state <= `LM32_MC_STATE_IDLE;
   164     end
   165     else
   166     begin
   167 `ifdef CFG_MC_DIVIDE_ENABLED
   168         divide_by_zero_x <= `FALSE;
   169 `endif
   170         case (state)
   171         `LM32_MC_STATE_IDLE:
   172         begin
   173             if (stall_d == `FALSE)                 
   174             begin          
   175                 cycles <= `LM32_WORD_WIDTH;
   176                 p <= 32'b0;
   177                 a <= operand_0_d;
   178                 b <= operand_1_d;                    
   179 `ifdef CFG_MC_DIVIDE_ENABLED
   180                 if (divide_d == `TRUE)
   181                     state <= `LM32_MC_STATE_DIVIDE;
   182                 if (modulus_d == `TRUE)
   183                     state <= `LM32_MC_STATE_MODULUS;
   184 `endif                    
   185 `ifdef CFG_MC_MULTIPLY_ENABLED
   186                 if (multiply_d == `TRUE)
   187                     state <= `LM32_MC_STATE_MULTIPLY;
   188 `endif
   189 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   190                 if (shift_left_d == `TRUE)
   191                 begin
   192                     state <= `LM32_MC_STATE_SHIFT_LEFT;
   193                     sign_extend_x <= sign_extend_d;
   194                     cycles <= operand_1_d[4:0];
   195                     a <= operand_0_d;
   196                     b <= operand_0_d;
   197                 end
   198                 if (shift_right_d == `TRUE)
   199                 begin
   200                     state <= `LM32_MC_STATE_SHIFT_RIGHT;
   201                     sign_extend_x <= sign_extend_d;
   202                     cycles <= operand_1_d[4:0];
   203                     a <= operand_0_d;
   204                     b <= operand_0_d;
   205                 end
   206 `endif
   207             end            
   208         end
   209 `ifdef CFG_MC_DIVIDE_ENABLED
   210         `LM32_MC_STATE_DIVIDE:
   211         begin
   212             if (t[32] == 1'b0)
   213             begin
   214                 p <= t[31:0];
   215                 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
   216             end
   217             else 
   218             begin
   219                 p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
   220                 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
   221             end
   222             result_x <= a;
   223             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   224             begin
   225                 // Check for divide by zero
   226                 divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
   227                 state <= `LM32_MC_STATE_IDLE;
   228             end
   229             cycles <= cycles - 1'b1;
   230         end
   231         `LM32_MC_STATE_MODULUS:
   232         begin
   233             if (t[32] == 1'b0)
   234             begin
   235                 p <= t[31:0];
   236                 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
   237             end
   238             else 
   239             begin
   240                 p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
   241                 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
   242             end
   243             result_x <= p;
   244             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   245             begin
   246                 // Check for divide by zero
   247                 divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
   248                 state <= `LM32_MC_STATE_IDLE;
   249             end
   250             cycles <= cycles - 1'b1;
   251         end
   252 `endif        
   253 `ifdef CFG_MC_MULTIPLY_ENABLED
   254         `LM32_MC_STATE_MULTIPLY:
   255         begin
   256             if (b[0] == 1'b1)
   257                 p <= p + a;
   258             b <= {1'b0, b[`LM32_WORD_WIDTH-1:1]};
   259             a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
   260             result_x <= p;
   261             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   262                 state <= `LM32_MC_STATE_IDLE;
   263             cycles <= cycles - 1'b1;
   264         end
   265 `endif     
   266 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   267         `LM32_MC_STATE_SHIFT_LEFT:
   268         begin       
   269             a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
   270             result_x <= a;
   271             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   272                 state <= `LM32_MC_STATE_IDLE;
   273             cycles <= cycles - 1'b1;
   274         end
   275         `LM32_MC_STATE_SHIFT_RIGHT:
   276         begin       
   277             b <= {fill_value, b[`LM32_WORD_WIDTH-1:1]};
   278             result_x <= b;
   279             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   280                 state <= `LM32_MC_STATE_IDLE;
   281             cycles <= cycles - 1'b1;
   282         end
   283 `endif   
   284         endcase
   285     end
   286 end 
   288 endmodule