-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathalu.v
137 lines (111 loc) · 2.32 KB
/
alu.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
`ifndef ALU_V
`define ALU_V
`include "header.v"
`include "full_add.v"
`include "mul.v"
`include "shift.v"
`define OP_NOP 3'b000
`define OP_SHL 3'b001
`define OP_SHR 3'b010
`define OP_SHRA 3'b011
`define OP_ADD 3'b100
`define OP_SUB 3'b101
`define OP_MUL 3'b110
`define OP_DIV 3'b111
// Simple single cycle alu
module alu(
input clk,
input reset,
input [`DATA_WIDTH-1:0] i_a, // 1st operand
input [`DATA_WIDTH-1:0] i_b, // 2nd operand
input [2:0] i_cmd, // command
output [`DATA_WIDTH-1:0] o_result,
output o_valid, // result is valid
output o_ready // ready to take input
);
reg [`DATA_WIDTH-1:0] reg_result;
reg reg_valid = 1'b0;
wire [`DATA_WIDTH-1:0] op_a;
wire [`DATA_WIDTH-1:0] op_b;
wire [`DATA_WIDTH-1:0] sum;
wire c_out;
wire [63:0] prod;
wire [`DATA_WIDTH-1:0] shl_out;
wire [`DATA_WIDTH-1:0] shr_out;
wire [`DATA_WIDTH-1:0] shra_out;
// ALU state machine macros
`define ST_RESET 2'h0
`define ST_READY 2'h1
`define ST_BUSY 2'h2
// begin in reset state
reg [1:0] reg_status = `ST_RESET;
// Synchronous reset
always @(posedge clk && reset) begin
reg_status <= `ST_READY;
end
// Assign outputs
assign o_ready = ((reg_status == `ST_READY) && !reset);
assign o_valid = (reg_valid && (reg_status == `ST_READY));
assign o_result = o_valid ? reg_result : 32'hx; // Ternary operator
// Fix inputs
assign op_a = i_a;
assign op_b = i_cmd == `OP_SUB ? -i_b : i_b;
// Main processing loop
always @(posedge clk && !reset) begin
case (reg_status)
`ST_READY: begin
reg_status <= `ST_BUSY;
casez (i_cmd)
`OP_SHL: reg_result = shl_out;
`OP_SHR: reg_result = shr_out;
`OP_SHRA: reg_result = shra_out;
3'b10?: reg_result = {c_out,sum}; // OP_ADD and OP_SUB
`OP_MUL: reg_result = prod;
`OP_DIV: reg_result = i_a / i_b;
default: reg_result = i_a;
endcase
end
`ST_BUSY: begin
reg_valid <= 1'b1;
reg_status <= `ST_READY;
end
default: begin
$display("should not happen");
$finish;
end
endcase
end
full_add my_add_sub
(
.a(op_a),
.b(op_b),
.c_in(1'b0),
.c_out(c_out),
.sum(sum)
);
mul my_mul
(
.a(op_a),
.b(op_b),
.prod(prod)
);
left_shift my_shl
(
.a(op_a),
.b(op_b),
.out(shl_out)
);
log_right_shift my_shr
(
.a(op_a),
.b(op_b),
.out(shr_out)
);
ari_right_shift my_shra
(
.a(op_a),
.b(op_b),
.out(shra_out)
);
endmodule
`endif