Root/lm32/logic/sakc/rtl/lm32/lm32_mc_arithmetic.v

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// =============================================================================
23
24`include "lm32_include.v"
25           
26`define LM32_MC_STATE_RNG 2:0
27`define LM32_MC_STATE_IDLE 3'b000
28`define LM32_MC_STATE_MULTIPLY 3'b001
29`define LM32_MC_STATE_MODULUS 3'b010
30`define LM32_MC_STATE_DIVIDE 3'b011
31`define LM32_MC_STATE_SHIFT_LEFT 3'b100
32`define LM32_MC_STATE_SHIFT_RIGHT 3'b101
33
34/////////////////////////////////////////////////////
35// Module interface
36/////////////////////////////////////////////////////
37
38module lm32_mc_arithmetic (
39    // ----- Inputs -----
40    clk_i,
41    rst_i,
42    stall_d,
43    kill_x,
44`ifdef CFG_MC_DIVIDE_ENABLED
45    divide_d,
46    modulus_d,
47`endif
48`ifdef CFG_MC_MULTIPLY_ENABLED
49    multiply_d,
50`endif
51`ifdef CFG_MC_BARREL_SHIFT_ENABLED
52    shift_left_d,
53    shift_right_d,
54    sign_extend_d,
55`endif
56    operand_0_d,
57    operand_1_d,
58    // ----- Ouputs -----
59    result_x,
60`ifdef CFG_MC_DIVIDE_ENABLED
61    divide_by_zero_x,
62`endif
63    stall_request_x
64    );
65
66/////////////////////////////////////////////////////
67// Inputs
68/////////////////////////////////////////////////////
69
70input clk_i; // Clock
71input rst_i; // Reset
72input stall_d; // Stall instruction in D stage
73input kill_x; // Kill instruction in X stage
74`ifdef CFG_MC_DIVIDE_ENABLED
75input divide_d; // Perform divide
76input modulus_d; // Perform modulus
77`endif
78`ifdef CFG_MC_MULTIPLY_ENABLED
79input multiply_d; // Perform multiply
80`endif
81`ifdef CFG_MC_BARREL_SHIFT_ENABLED
82input shift_left_d; // Perform left shift
83input shift_right_d; // Perform right shift
84input sign_extend_d; // Whether to sign-extend (arithmetic) or zero-extend (logical)
85`endif
86input [`LM32_WORD_RNG] operand_0_d;
87input [`LM32_WORD_RNG] operand_1_d;
88
89/////////////////////////////////////////////////////
90// Outputs
91/////////////////////////////////////////////////////
92
93output [`LM32_WORD_RNG] result_x; // Result of operation
94reg [`LM32_WORD_RNG] result_x;
95`ifdef CFG_MC_DIVIDE_ENABLED
96output divide_by_zero_x; // A divide by zero was attempted
97reg divide_by_zero_x;
98`endif
99output stall_request_x; // Request to stall pipeline from X stage back
100wire stall_request_x;
101
102/////////////////////////////////////////////////////
103// Internal nets and registers
104/////////////////////////////////////////////////////
105
106reg [`LM32_WORD_RNG] p; // Temporary registers
107reg [`LM32_WORD_RNG] a;
108reg [`LM32_WORD_RNG] b;
109`ifdef CFG_MC_DIVIDE_ENABLED
110wire [32:0] t;
111`endif
112
113reg [`LM32_MC_STATE_RNG] state; // Current state of FSM
114reg [5:0] cycles; // Number of cycles remaining in the operation
115
116`ifdef CFG_MC_BARREL_SHIFT_ENABLED
117reg sign_extend_x; // Whether to sign extend of zero extend right shifts
118wire fill_value; // Value to fill with for right barrel-shifts
119`endif
120
121/////////////////////////////////////////////////////
122// Combinational logic
123/////////////////////////////////////////////////////
124
125// Stall pipeline while any operation is being performed
126assign stall_request_x = state != `LM32_MC_STATE_IDLE;
127
128`ifdef CFG_MC_DIVIDE_ENABLED
129// Subtraction
130assign t = {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]} - b;
131`endif
132
133`ifdef CFG_MC_BARREL_SHIFT_ENABLED
134// Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
135assign fill_value = (sign_extend_x == `TRUE) & b[`LM32_WORD_WIDTH-1];
136`endif
137
138/////////////////////////////////////////////////////
139// Sequential logic
140/////////////////////////////////////////////////////
141
142// Perform right shift
143always @(posedge clk_i `CFG_RESET_SENSITIVITY)
144begin
145    if (rst_i == `TRUE)
146    begin
147        cycles <= {6{1'b0}};
148        p <= {`LM32_WORD_WIDTH{1'b0}};
149        a <= {`LM32_WORD_WIDTH{1'b0}};
150        b <= {`LM32_WORD_WIDTH{1'b0}};
151`ifdef CFG_MC_BARREL_SHIFT_ENABLED
152        sign_extend_x <= 1'b0;
153`endif
154`ifdef CFG_MC_DIVIDE_ENABLED
155        divide_by_zero_x <= `FALSE;
156`endif
157        result_x <= {`LM32_WORD_WIDTH{1'b0}};
158        state <= `LM32_MC_STATE_IDLE;
159    end
160    else
161    begin
162`ifdef CFG_MC_DIVIDE_ENABLED
163        divide_by_zero_x <= `FALSE;
164`endif
165        case (state)
166        `LM32_MC_STATE_IDLE:
167        begin
168            if (stall_d == `FALSE)
169            begin
170                cycles <= `LM32_WORD_WIDTH;
171                p <= 32'b0;
172                a <= operand_0_d;
173                b <= operand_1_d;
174`ifdef CFG_MC_DIVIDE_ENABLED
175                if (divide_d == `TRUE)
176                    state <= `LM32_MC_STATE_DIVIDE;
177                if (modulus_d == `TRUE)
178                    state <= `LM32_MC_STATE_MODULUS;
179`endif
180`ifdef CFG_MC_MULTIPLY_ENABLED
181                if (multiply_d == `TRUE)
182                    state <= `LM32_MC_STATE_MULTIPLY;
183`endif
184`ifdef CFG_MC_BARREL_SHIFT_ENABLED
185                if (shift_left_d == `TRUE)
186                begin
187                    state <= `LM32_MC_STATE_SHIFT_LEFT;
188                    sign_extend_x <= sign_extend_d;
189                    cycles <= operand_1_d[4:0];
190                    a <= operand_0_d;
191                    b <= operand_0_d;
192                end
193                if (shift_right_d == `TRUE)
194                begin
195                    state <= `LM32_MC_STATE_SHIFT_RIGHT;
196                    sign_extend_x <= sign_extend_d;
197                    cycles <= operand_1_d[4:0];
198                    a <= operand_0_d;
199                    b <= operand_0_d;
200                end
201`endif
202            end
203        end
204`ifdef CFG_MC_DIVIDE_ENABLED
205        `LM32_MC_STATE_DIVIDE:
206        begin
207            if (t[32] == 1'b0)
208            begin
209                p <= t[31:0];
210                a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
211            end
212            else
213            begin
214                p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
215                a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
216            end
217            result_x <= a;
218            if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
219            begin
220                // Check for divide by zero
221                divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
222                state <= `LM32_MC_STATE_IDLE;
223            end
224            cycles <= cycles - 1'b1;
225        end
226        `LM32_MC_STATE_MODULUS:
227        begin
228            if (t[32] == 1'b0)
229            begin
230                p <= t[31:0];
231                a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
232            end
233            else
234            begin
235                p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
236                a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
237            end
238            result_x <= p;
239            if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
240            begin
241                // Check for divide by zero
242                divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
243                state <= `LM32_MC_STATE_IDLE;
244            end
245            cycles <= cycles - 1'b1;
246        end
247`endif
248`ifdef CFG_MC_MULTIPLY_ENABLED
249        `LM32_MC_STATE_MULTIPLY:
250        begin
251            if (b[0] == 1'b1)
252                p <= p + a;
253            b <= {1'b0, b[`LM32_WORD_WIDTH-1:1]};
254            a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
255            result_x <= p;
256            if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
257                state <= `LM32_MC_STATE_IDLE;
258            cycles <= cycles - 1'b1;
259        end
260`endif
261`ifdef CFG_MC_BARREL_SHIFT_ENABLED
262        `LM32_MC_STATE_SHIFT_LEFT:
263        begin
264            a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
265            result_x <= a;
266            if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
267                state <= `LM32_MC_STATE_IDLE;
268            cycles <= cycles - 1'b1;
269        end
270        `LM32_MC_STATE_SHIFT_RIGHT:
271        begin
272            b <= {fill_value, b[`LM32_WORD_WIDTH-1:1]};
273            result_x <= b;
274            if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
275                state <= `LM32_MC_STATE_IDLE;
276            cycles <= cycles - 1'b1;
277        end
278`endif
279        endcase
280    end
281end
282
283endmodule
284

Archive Download this file

Branches:
master



interactive