以always與case多工器設計一個簡單的ALU電路。
Introduction
使用環境:Quartus II 7.2 SP3 + ModelSim-Altera 6.1g + DE2(Cyclone II EP2C35F672C6)
Method 1:
使用Verilog
alu.v / Verilog
1 /*
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : alu.v
5 Compiler : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g
6 Description : Demo how to write simple ALU
7 Release : 07/12/2008 1.0
8 */
9 module alu (
10 input [2:0] a,
11 input [2:0] b,
12 input [2:0] sel,
13 output reg [7:0] y
14 );
15
16 always@(a or b or sel) begin
17 case(sel)
18 3'b000: y = a + b;
19 3'b001: y = a - b;
20 3'b010: y = a * b;
21 3'b011: begin
22 y[7:4] = a / b;
23 y[3:0] = a % b;
24 end
25 3'b100: y = a & b;
26 3'b101: y = a | b;
27 3'b110: y = ~a;
28 3'b111: y = a ^ b;
29 endcase
30 end
31
32 endmodule
Method 2:
使用Megafunction
alu_mf.v / Verilog
1 /*
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : alu_mf.v
5 Compiler : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g
6 Description : Demo how to write simple ALU
7 Release : 07/12/2008 1.0
8 */
9 module alu_mf (
10 input [2:0] a,
11 input [2:0] b,
12 input [2:0] sel,
13 output [7:0] y
14 );
15
16 wire [2:0] add_sum;
17 wire add_cout;
18 wire [7:0] add = {{4'h0}, add_cout, add_sum};
19 wire [7:0] sub;
20 wire [7:0] mul;
21 wire [3:0] quotient;
22 wire [3:0] remain;
23 wire [7:0] w_and;
24 wire [7:0] w_or;
25 wire [7:0] inv;
26 wire [7:0] w_xor;
27 wire [63:0] w_mux = {w_xor, inv, w_or, w_and, {quotient, remain}, mul, sub, add};
28
29 lpm_add_sub # (.lpm_width(3),.lpm_direction("add"))
30 u0 (
31 .dataa(a),
32 .datab(b),
33 .result(add_sum),
34 .cout(add_cout)
35 );
36
37 lpm_add_sub # (.lpm_width(3),.lpm_direction("sub"))
38 u1 (
39 .dataa(a),
40 .datab(b),
41 .result(sub)
42 );
43
44 lpm_mult # (.lpm_widtha(3),.lpm_widthb(3),.lpm_widthp(8))
45 u2 (
46 .dataa(a),
47 .datab(b),
48 .result(mul)
49 );
50
51 lpm_divide # (.lpm_widthn(3),.lpm_widthd(3))
52 u3 (
53 .numer(a),
54 .denom(b),
55 .quotient(quotient),
56 .remain(remain)
57 );
58
59 lpm_inv # (.lpm_width(8))
60 u4 (
61 .data(a),
62 .result(inv)
63 );
64
65 lpm_mux # (.lpm_width(8), .lpm_widths(3), .lpm_size(8))
66 u5 (
67 .data(w_mux),
68 .sel(sel),
69 .result(y)
70 );
71
72 assign w_and = and_2(a,b);
73 assign w_or = or_2(a, b);
74 assign w_xor = xor_2(a, b);
75
76 function [7:0] and_2(input [2:0] a, input [2:0] b);
77 and_2 = a & b;
78 endfunction
79
80 function [7:0] or_2(input [2:0] a, input [2:0] b);
81 or_2 = a | b;
82 endfunction
83
84 function [7:0] xor_2(input [2:0] a, input [2:0] b);
85 xor_2 = a ^ b;
86 endfunction
87
88 endmodule
testbench
alu_tb.v / Verilog
1 /*
2 (C) OOMusou 2008 http://oomusou.cnblogs.com
3
4 Filename : alu_tb.v
5 Compiler : Quartus II 7.2 SP3 + ModelSim-Altera 6.1g
6 Description : Demo how to write simple ALU testbench
7 Release : 07/12/2008 1.0
8 */
9 `timescale 1ns/10ps
10 module alu_tb;
11 reg [2:0] a;
12 reg [2:0] b;
13 reg [2:0] sel;
14 wire [7:0] y;
15
16 alu u0 (
17 .a(a),
18 .b(b),
19 .sel(sel),
20 .y(y)
21 );
22
23 initial begin
24 a = 3'b111;
25 b = 3'b010;
26 sel = 3'b000;
27 end
28
29 always #50 sel = sel + 1;
30
31 endmodule
執行結果
pins.tcl
1 cmp add_assignment "alu" "" "a[2]" "LOCATION" "PIN_AD13"
2 cmp add_assignment "alu" "" "a[1]" "LOCATION" "PIN_AF14"
3 cmp add_assignment "alu" "" "a[0]" "LOCATION" "PIN_AE14"
4 cmp add_assignment "alu" "" "b[2]" "LOCATION" "PIN_P25"
5 cmp add_assignment "alu" "" "b[1]" "LOCATION" "PIN_N26"
6 cmp add_assignment "alu" "" "b[0]" "LOCATION" "PIN_N25"
7 cmp add_assignment "alu" "" "y[7]" "LOCATION" "PIN_AC21"
8 cmp add_assignment "alu" "" "y[6]" "LOCATION" "PIN_AD21"
9 cmp add_assignment "alu" "" "y[5]" "LOCATION" "PIN_AD23"
10 cmp add_assignment "alu" "" "y[4]" "LOCATION" "PIN_AD22"
11 cmp add_assignment "alu" "" "y[3]" "LOCATION" "PIN_AC22"
12 cmp add_assignment "alu" "" "y[2]" "LOCATION" "PIN_AB21"
13 cmp add_assignment "alu" "" "y[1]" "LOCATION" "PIN_AF23"
14 cmp add_assignment "alu" "" "y[0]" "LOCATION" "PIN_AE23"
15 cmp add_assignment "alu" "" "sel[2]" "LOCATION" "PIN_V2"