OpenCores
URL https://opencores.org/ocsvn/m1_core/m1_core/trunk

Subversion Repositories m1_core

[/] [m1_core/] [tags/] [first/] [hdl/] [rtl/] [m1_cpu/] [m1_alu.v] - Blame information for rev 54

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 fafa1971
/*
2
 * Simply RISC M1 ALU & Multiplier & Divider
3
 *
4
 * Three modules (alu, multiplier, divider) with Alternating Bit Protocol (ABP) interface.
5
 */
6
 
7
`include "m1_defs.h"
8
 
9
// Combinational ALU with 32-bit operands
10
module alu(a_i, b_i, func_i, signed_i, result_o, carry_o);
11
 
12
  // I/O Ports
13
  input[31:0] a_i, b_i;        // Operands
14
  input[4:0] func_i;           // Function to be performed
15
  input signed_i;              // Operation is signed
16
  output[31:0] result_o;       // Result
17
  output carry_o;              // Carry bit
18
 
19
  // Registers
20
  reg[31:0] result_o;          // Registered output of result  
21
 
22
  // ALU Logic
23
  always @(a_i or b_i or func_i or signed_i) begin
24
    case(func_i)
25
      `ALU_OP_SLL: result_o = a_i << b_i;
26
      `ALU_OP_SRL: result_o = a_i >> b_i;
27
      `ALU_OP_SRA: result_o = {{32{a_i[31]}}, a_i } >> b_i;
28
      `ALU_OP_ADD: result_o = a_i + b_i;
29
      `ALU_OP_SUB: result_o = a_i - b_i;
30
      `ALU_OP_AND: result_o = a_i & b_i;
31
      `ALU_OP_OR:  result_o = a_i | b_i;
32
      `ALU_OP_XOR: result_o = a_i ^ b_i;
33
//      `ALU_OP_NOR: result_o = a_i ~| b_i;
34
      `ALU_OP_SEQ: result_o = (a_i == b_i) ? 32'b1 : 32'b0;
35
      `ALU_OP_SNE: result_o = (a_i != b_i) ? 32'b1 : 32'b0;
36
      `ALU_OP_SLT: if(signed_i) result_o = ({~a_i[31],a_i[30:0]} < {~b_i[31],b_i[30:0]}) ? 32'b1 : 32'b0;
37
                   else result_o = a_i < b_i;
38
      `ALU_OP_SLE: if ((a_i[31] == 1'b1) || (a_i == 32'b0)) result_o = 32'b1;
39
                   else result_o = 32'b0;
40
      `ALU_OP_SGT: if ((a_i[31] == 1'b0) && (a_i != 32'b0)) result_o = 32'b1;
41
                   else result_o = 32'b0;
42
      `ALU_OP_SGE: if(signed_i) result_o = ({~a_i[31],a_i[30:0]} >= {~b_i[31],b_i[30:0]}) ? 32'b1 : 32'b0;
43
                   else result_o = a_i >= b_i;
44
    endcase
45
  end
46
 
47
endmodule
48
 
49
// 32-bit * 32-bit Integer Multiplier (this version is not optimized and always takes 32 cycles)
50
module multiplier(sys_reset_i, sys_clock_i, a_i, b_i, signed_i, product_o, abp_req_i, abp_ack_o);
51
 
52
  // I/O ports
53
  input        sys_reset_i;      // System Reset
54
  input        sys_clock_i;      // System Clock
55
  input[31:0]  a_i, b_i;         // Operands of multiplication
56
  input        signed_i;         // If multiplication is signed
57
  output[63:0] product_o;        // Product of multiplication
58
  input        abp_req_i;        // ABP Request
59
  output       abp_ack_o;        // ABP Acknowledgement
60
 
61
  // Registers
62
  reg[63:0]    a_latched;        // Latched 'a' input
63
  reg[31:0]    b_latched;        // Latched 'b' input
64
  reg[63:0]    product_o;        // Registered output of result
65
  reg[63:0]    product_tmp;      // Temporary result
66
  reg          abp_ack_o;        // Registered output of ABP Ack
67
  reg          negative_output;  // If output is negative
68
  reg[5:0]     count;            // Downward counter (32->0)
69
  reg          abp_last;         // Level of last ABP request
70
 
71
  // Sequential logic
72
  always @(posedge sys_clock_i) begin
73
 
74
    // Initialization
75
    if(sys_reset_i) begin
76
 
77
      product_o = 0;
78
      abp_ack_o = 0;
79
      negative_output = 0;
80
      count = 6'd0;
81
      abp_last = 0;
82
 
83
    // New request
84
    end else if(abp_req_i!=abp_last) begin
85
 
86
      abp_last = abp_req_i;     // Latch level of ABP request
87
      count  = 6'd32;           // Start counter
88
      product_tmp = 0;          // Initialize result
89
      a_latched = (!signed_i || !a_i[31]) ? { 32'd0, a_i } : { 32'd0, (~a_i+1'b1) };
90
      b_latched = (!signed_i || !b_i[31]) ? b_i : (~b_i + 1'b1);
91
      negative_output = signed_i && (a_i[31] ^ b_i[31]);
92
      product_o = (!negative_output) ? product_tmp : (~product_tmp+1);  // Degugging only
93
 
94
    // Calculating
95
    end else if(count>0) begin
96
 
97
      count = count-1;
98
      if(b_latched[0]==1) product_tmp = product_tmp + a_latched;
99
      a_latched = a_latched << 1;
100
      b_latched = b_latched >> 1;
101
      product_o = (!negative_output) ? product_tmp : (~product_tmp + 1);  // Debugging only
102
 
103
    // Return the result
104
    end else if(count==0) begin
105
 
106
      abp_ack_o = abp_req_i;    // Return the result
107
      product_o = (!negative_output) ? product_tmp : (~product_tmp + 1);
108
 
109
    end
110
 
111
  end
112
 
113
endmodule
114
 
115
// 32-bit / 32-bit Integer Divider (this version is not optimized and always takes 32 cycles)
116
module divider(sys_reset_i, sys_clock_i, a_i, b_i, signed_i, quotient_o, remainder_o, abp_req_i, abp_ack_o);
117
 
118
  // I/O ports
119
  input        sys_reset_i;      // System Reset
120
  input        sys_clock_i;      // System Clock
121
  input[31:0]  a_i, b_i;         // Operands of division
122
  input        signed_i;         // If division is signed
123
  output[31:0] quotient_o;       // Quotient of division
124
  output[31:0] remainder_o;      // Remainder of division
125
  input        abp_req_i;        // ABP Request
126
  output       abp_ack_o;        // ABP Acknowledgement
127
 
128
  // Registers
129
  reg[63:0]    a_latched;        // Latched 'a' input
130
  reg[63:0]    b_latched;        // Latched 'b' input
131
  reg[31:0]    quotient_o;       // Registered output of result
132
  reg[31:0]    quotient_tmp;     // Temporary result
133
  reg[31:0]    remainder_o;      // Registered output of result
134
  reg[31:0]    remainder_tmp;    // Temporary result
135
  reg          abp_ack_o;        // Registered output of ABP Ack
136
  reg          negative_output;  // If output is negative
137
  reg[5:0]     count;            // Downward counter (32->0)
138
  reg          abp_last;         // Level of last ABP request
139
  reg[63:0]    diff;             // Difference
140
 
141
  // Sequential logic
142
  always @(posedge sys_clock_i) begin
143
 
144
    // Initialization
145
    if(sys_reset_i) begin
146
 
147
      quotient_o = 0;
148
      remainder_o = 0;
149
      abp_ack_o = 0;
150
      negative_output = 0;
151
      count = 6'd0;
152
      abp_last = 0;
153
 
154
    // New request
155
    end else if(abp_req_i!=abp_last) begin
156
 
157
      abp_last = abp_req_i;     // Latch level of ABP request
158
      count  = 6'd32;           // Start counter
159
      quotient_tmp = 0;         // Initialize result
160
      remainder_tmp = 0;        // Initialize result
161
      a_latched = (!signed_i || !a_i[31]) ? { 32'd0, a_i } : { 32'd0, (~a_i + 1'b1) };
162
      b_latched = (!signed_i || !b_i[31]) ? { 1'b0, b_i, 31'd0 } : { 1'b0, ~b_i + 1'b1, 31'd0 };
163
      negative_output = signed_i && (a_i[31] ^ b_i[31]);
164
      quotient_o = (!negative_output) ? quotient_tmp : (~quotient_tmp+1);  // Debugging only
165
      remainder_o = (!negative_output) ? a_latched[31:0] : (~a_latched[31:0]+1);  // Debugging only
166
 
167
    // Calculating
168
    end else if(count>0) begin
169
 
170
      count = count-1;
171
      diff = a_latched-b_latched;
172
      quotient_tmp = quotient_tmp << 1;
173
      if(!diff[63]) begin
174
        a_latched = diff;
175
        quotient_tmp[0] = 1;
176
      end
177
      b_latched = b_latched >> 1;
178
      quotient_o = (!negative_output) ? quotient_tmp : (~quotient_tmp+1);  // Debugging only
179
      remainder_o = (!negative_output) ? a_latched[31:0] : (~a_latched[31:0]+1);  // Debugging only
180
 
181
    // Return the result
182
    end else if(count==0) begin
183
 
184
      abp_ack_o = abp_req_i;    // Return the result
185
      quotient_o = (!negative_output) ? quotient_tmp : (~quotient_tmp+1);
186
      remainder_o = (!negative_output) ? a_latched[31:0] : (~a_latched[31:0]+1);
187
 
188
    end
189
 
190
  end
191
 
192
endmodule
193
 
194
/*
195
// Testbench
196
module testbench;
197
  reg sys_clock_i, sys_reset_i;
198
  reg[31:0] a_i,b_i;
199
  wire[63:0] product_o;
200
  wire[31:0] quotient_o, remainder_o;
201
  reg signed_i,abp_req_i_mul,abp_req_i_div;
202
  wire abp_ack_o_mul,abp_ack_o_div;
203
 
204
  multiplier mul_0(sys_reset_i, sys_clock_i, a_i, b_i, signed_i, product_o, abp_req_i_mul, abp_ack_o_mul);
205
  divider div_0(sys_reset_i, sys_clock_i, a_i, b_i, signed_i, quotient_o, remainder_o, abp_req_i_div, abp_ack_o_div);
206
 
207
  initial begin
208
 
209
    $dumpfile("trace.vcd");
210
    $dumpvars();
211
 
212
    sys_clock_i = 0;
213
    sys_reset_i = 1;
214
    abp_req_i_mul = 0;
215
    abp_req_i_div = 0;
216
    #100
217
    sys_reset_i = 0;
218
    #100
219
 
220
    a_i = 17;
221
    b_i = 3;
222
    signed_i = 0;
223
    abp_req_i_mul = !abp_req_i_mul;
224
    #100
225
    $display("Try unsigned 17*3: Product is %d", product_o);
226
 
227
    a_i = 20;
228
    b_i = 4;
229
    signed_i = 1;
230
    abp_req_i_div = !abp_req_i_div;
231
    #100
232
    $display("Try signed 20/4: Quotient is %d and remainder is %d", quotient_o, remainder_o);
233
 
234
    a_i = -7;
235
    b_i = 3;
236
    signed_i = 1;
237
    abp_req_i_mul = !abp_req_i_mul;
238
    #100
239
    $display("Try signed -7*3: Product is %d", product_o);
240
 
241
    a_i = 17;
242
    b_i = 5;
243
    signed_i = 0;
244
    abp_req_i_div = !abp_req_i_div;
245
    #100
246
    $display("Try unsigned 17/5: Quotient is %d and remainder is %d", quotient_o, remainder_o);
247
 
248
    $finish();
249
  end
250
 
251
  always #1 sys_clock_i = !sys_clock_i;
252
 
253
endmodule
254
*/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.