lm32_mc_arithmetic.v

Sat, 06 Aug 2011 01:26:56 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:26:56 +0100
changeset 27
d6c693415d59
parent 26
73de224304c1
permissions
-rwxr-xr-x

remove synthesis delay entities to ease merge

     1 //   ==================================================================
     2 //   >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
     3 //   ------------------------------------------------------------------
     4 //   Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
     5 //   ALL RIGHTS RESERVED 
     6 //   ------------------------------------------------------------------
     7 //
     8 //   IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
     9 //
    10 //   Permission:
    11 //
    12 //      Lattice Semiconductor grants permission to use this code
    13 //      pursuant to the terms of the Lattice Semiconductor Corporation
    14 //      Open Source License Agreement.  
    15 //
    16 //   Disclaimer:
    17 //
    18 //      Lattice Semiconductor provides no warranty regarding the use or
    19 //      functionality of this code. It is the user's responsibility to
    20 //      verify the userís design for consistency and functionality through
    21 //      the use of formal verification methods.
    22 //
    23 //   --------------------------------------------------------------------
    24 //
    25 //                  Lattice Semiconductor Corporation
    26 //                  5555 NE Moore Court
    27 //                  Hillsboro, OR 97214
    28 //                  U.S.A
    29 //
    30 //                  TEL: 1-800-Lattice (USA and Canada)
    31 //                         503-286-8001 (other locations)
    32 //
    33 //                  web: http://www.latticesemi.com/
    34 //                  email: techsupport@latticesemi.com
    35 //
    36 //   --------------------------------------------------------------------
    37 //                         FILE DETAILS
    38 // Project          : LatticeMico32
    39 // File             : lm_mc_arithmetic.v
    40 // Title            : Multi-cycle arithmetic unit.
    41 // Dependencies     : lm32_include.v
    42 // Version          : 6.1.17
    43 //                  : Initial Release
    44 // Version          : 7.0SP2, 3.0
    45 //                  : No Change
    46 // Version          : 3.1
    47 //                  : No Change
    48 // =============================================================================
    50 `include "lm32_include.v"
    52 `define LM32_MC_STATE_RNG         2:0
    53 `define LM32_MC_STATE_IDLE        3'b000
    54 `define LM32_MC_STATE_MULTIPLY    3'b001
    55 `define LM32_MC_STATE_MODULUS     3'b010   
    56 `define LM32_MC_STATE_DIVIDE      3'b011 
    57 `define LM32_MC_STATE_SHIFT_LEFT  3'b100
    58 `define LM32_MC_STATE_SHIFT_RIGHT 3'b101
    60 /////////////////////////////////////////////////////
    61 // Module interface
    62 /////////////////////////////////////////////////////
    64 module lm32_mc_arithmetic (
    65     // ----- Inputs -----
    66     clk_i,
    67     rst_i,
    68     stall_d,
    69     kill_x,
    70 `ifdef CFG_MC_DIVIDE_ENABLED
    71     divide_d,
    72     modulus_d,
    73 `endif
    74 `ifdef CFG_MC_MULTIPLY_ENABLED
    75     multiply_d,
    76 `endif
    77 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
    78     shift_left_d,
    79     shift_right_d,
    80     sign_extend_d,
    81 `endif
    82     operand_0_d,
    83     operand_1_d,
    84     // ----- Ouputs -----
    85     result_x,
    86 `ifdef CFG_MC_DIVIDE_ENABLED
    87     divide_by_zero_x,
    88 `endif
    89     stall_request_x
    90     );
    92 /////////////////////////////////////////////////////
    93 // Inputs
    94 /////////////////////////////////////////////////////
    96 input clk_i;                                    // Clock
    97 input rst_i;                                    // Reset
    98 input stall_d;                                  // Stall instruction in D stage
    99 input kill_x;                                   // Kill instruction in X stage
   100 `ifdef CFG_MC_DIVIDE_ENABLED
   101 input divide_d;                                 // Perform divide
   102 input modulus_d;                                // Perform modulus
   103 `endif
   104 `ifdef CFG_MC_MULTIPLY_ENABLED
   105 input multiply_d;                               // Perform multiply
   106 `endif
   107 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   108 input shift_left_d;                             // Perform left shift
   109 input shift_right_d;                            // Perform right shift
   110 input sign_extend_d;                            // Whether to sign-extend (arithmetic) or zero-extend (logical)
   111 `endif
   112 input [`LM32_WORD_RNG] operand_0_d;
   113 input [`LM32_WORD_RNG] operand_1_d;
   115 /////////////////////////////////////////////////////
   116 // Outputs
   117 /////////////////////////////////////////////////////
   119 output [`LM32_WORD_RNG] result_x;               // Result of operation
   120 reg    [`LM32_WORD_RNG] result_x;
   121 `ifdef CFG_MC_DIVIDE_ENABLED
   122 output divide_by_zero_x;                        // A divide by zero was attempted
   123 reg    divide_by_zero_x;
   124 `endif
   125 output stall_request_x;                         // Request to stall pipeline from X stage back
   126 wire   stall_request_x;
   128 /////////////////////////////////////////////////////
   129 // Internal nets and registers 
   130 /////////////////////////////////////////////////////
   132 reg [`LM32_WORD_RNG] p;                         // Temporary registers
   133 reg [`LM32_WORD_RNG] a;
   134 reg [`LM32_WORD_RNG] b;
   135 `ifdef CFG_MC_DIVIDE_ENABLED
   136 wire [32:0] t;
   137 `endif
   139 reg [`LM32_MC_STATE_RNG] state;                 // Current state of FSM
   140 reg [5:0] cycles;                               // Number of cycles remaining in the operation
   142 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   143 reg sign_extend_x;                              // Whether to sign extend of zero extend right shifts
   144 wire fill_value;                                // Value to fill with for right barrel-shifts
   145 `endif
   147 /////////////////////////////////////////////////////
   148 // Combinational logic
   149 /////////////////////////////////////////////////////
   151 // Stall pipeline while any operation is being performed
   152 assign stall_request_x = state != `LM32_MC_STATE_IDLE;
   154 `ifdef CFG_MC_DIVIDE_ENABLED
   155 // Subtraction
   156 assign t = {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]} - b;
   157 `endif
   159 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   160 // Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
   161 assign fill_value = (sign_extend_x == `TRUE) & b[`LM32_WORD_WIDTH-1];
   162 `endif
   164 /////////////////////////////////////////////////////
   165 // Sequential logic
   166 /////////////////////////////////////////////////////
   168 // Perform right shift
   169 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
   170 begin
   171     if (rst_i == `TRUE)
   172     begin
   173         cycles <= {6{1'b0}};
   174         p <= {`LM32_WORD_WIDTH{1'b0}};
   175         a <= {`LM32_WORD_WIDTH{1'b0}};
   176         b <= {`LM32_WORD_WIDTH{1'b0}};
   177 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   178         sign_extend_x <= 1'b0;
   179 `endif
   180 `ifdef CFG_MC_DIVIDE_ENABLED
   181         divide_by_zero_x <= `FALSE;
   182 `endif
   183         result_x <= {`LM32_WORD_WIDTH{1'b0}};
   184         state <= `LM32_MC_STATE_IDLE;
   185     end
   186     else
   187     begin
   188 `ifdef CFG_MC_DIVIDE_ENABLED
   189         divide_by_zero_x <= `FALSE;
   190 `endif
   191         case (state)
   192         `LM32_MC_STATE_IDLE:
   193         begin
   194             if (stall_d == `FALSE)                 
   195             begin          
   196                 cycles <= `LM32_WORD_WIDTH;
   197                 p <= 32'b0;
   198                 a <= operand_0_d;
   199                 b <= operand_1_d;                    
   200 `ifdef CFG_MC_DIVIDE_ENABLED
   201                 if (divide_d == `TRUE)
   202                     state <= `LM32_MC_STATE_DIVIDE;
   203                 if (modulus_d == `TRUE)
   204                     state <= `LM32_MC_STATE_MODULUS;
   205 `endif                    
   206 `ifdef CFG_MC_MULTIPLY_ENABLED
   207                 if (multiply_d == `TRUE)
   208                     state <= `LM32_MC_STATE_MULTIPLY;
   209 `endif
   210 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   211                 if (shift_left_d == `TRUE)
   212                 begin
   213                     state <= `LM32_MC_STATE_SHIFT_LEFT;
   214                     sign_extend_x <= sign_extend_d;
   215                     cycles <= operand_1_d[4:0];
   216                     a <= operand_0_d;
   217                     b <= operand_0_d;
   218                 end
   219                 if (shift_right_d == `TRUE)
   220                 begin
   221                     state <= `LM32_MC_STATE_SHIFT_RIGHT;
   222                     sign_extend_x <= sign_extend_d;
   223                     cycles <= operand_1_d[4:0];
   224                     a <= operand_0_d;
   225                     b <= operand_0_d;
   226                 end
   227 `endif
   228             end            
   229         end
   230 `ifdef CFG_MC_DIVIDE_ENABLED
   231         `LM32_MC_STATE_DIVIDE:
   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 <= a;
   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         `LM32_MC_STATE_MODULUS:
   253         begin
   254             if (t[32] == 1'b0)
   255             begin
   256                 p <= t[31:0];
   257                 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
   258             end
   259             else 
   260             begin
   261                 p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
   262                 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
   263             end
   264             result_x <= p;
   265             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   266             begin
   267                 // Check for divide by zero
   268                 divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
   269                 state <= `LM32_MC_STATE_IDLE;
   270             end
   271             cycles <= cycles - 1'b1;
   272         end
   273 `endif        
   274 `ifdef CFG_MC_MULTIPLY_ENABLED
   275         `LM32_MC_STATE_MULTIPLY:
   276         begin
   277             if (b[0] == 1'b1)
   278                 p <= p + a;
   279             b <= {1'b0, b[`LM32_WORD_WIDTH-1:1]};
   280             a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
   281             result_x <= p;
   282             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   283                 state <= `LM32_MC_STATE_IDLE;
   284             cycles <= cycles - 1'b1;
   285         end
   286 `endif     
   287 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
   288         `LM32_MC_STATE_SHIFT_LEFT:
   289         begin       
   290             a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
   291             result_x <= a;
   292             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   293                 state <= `LM32_MC_STATE_IDLE;
   294             cycles <= cycles - 1'b1;
   295         end
   296         `LM32_MC_STATE_SHIFT_RIGHT:
   297         begin       
   298             b <= {fill_value, b[`LM32_WORD_WIDTH-1:1]};
   299             result_x <= b;
   300             if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
   301                 state <= `LM32_MC_STATE_IDLE;
   302             cycles <= cycles - 1'b1;
   303         end
   304 `endif   
   305         endcase
   306     end
   307 end 
   309 endmodule