本文实现可以综合的ROM模块,由verilog实现,该方法可以用于芯片固化程序的存储。

1、基本单元

1.1、最基本cell
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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/06/07 17:27:45
// Design Name:
// Module Name: eand
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module eand (
q,
s,
d
);

parameter WIDTH = 8;

output [WIDTH-1 : 0] q;
input s;
input [WIDTH-1 : 0] d;

assign q = {WIDTH{s}} & d;

endmodule

该模块定义了一个八位(可以通过WIDTH更改数据宽度)的存储单元。

1.2、两个存储单位
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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/06/07 17:27:45
// Design Name:
// Module Name: mux2
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module mux2(
q,
d0,
d1,
a
);

parameter WIDTH = 8;

output [WIDTH-1 : 0] q;
input [WIDTH-1 : 0] d0;
input [WIDTH-1 : 0] d1;

input a;

wire [WIDTH-1 : 0] r0;
wire [WIDTH-1 : 0] r1;

eand #(WIDTH) and0(
.q(r0),
.s(~a),
.d(d0)
);

eand #(WIDTH) and1(
.q(r1),
.s(a),
.d(d1)
);

assign q = r0 r1;

endmodule

这个模块可以存储两个8位的数据,当地址a取0和1时候将对应输出数据d0和d1的值,即只有两个地址。

1.3、八个存储单位
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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/06/07 17:40:42
// Design Name:
// Module Name: mux8
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module mux8(
q,
d0,
d1,
d2,
d3,
d4,
d5,
d6,
d7,
a
);

parameter WIDTH = 8;

output [WIDTH-1 : 0] q;
input [WIDTH-1 : 0] d0,d1,d2,d3,d4,d5,d6,d7;
input [2:0] a;

wire [WIDTH-1 : 0] r0,r1,r2,r3,r4,r5,r6,r7;

eand #(WIDTH) and0(
.q(r0),
.s(~a[2]&~a[1]&~a[0]),
.d(d0)
);

eand #(WIDTH) and1(
.q(r1),
.s(~a[2]&~a[1]&a[0]),
.d(d1)
);

eand #(WIDTH) and2(
.q(r2),
.s(~a[2]&a[1]&~a[0]),
.d(d2)
);

eand #(WIDTH) and3(
.q(r3),
.s(~a[2]&a[1]&a[0]),
.d(d3)
);

eand #(WIDTH) and4(
.q(r4),
.s(a[2]&~a[1]&~a[0]),
.d(d4)
);

eand #(WIDTH) and5(
.q(r5),
.s(a[2]&~a[1]&a[0]),
.d(d5)
);

eand #(WIDTH) and6(
.q(r6),
.s(a[2]&a[1]&~a[0]),
.d(d6)
);

eand #(WIDTH) and7(
.q(r7),
.s(a[2]&a[1]&a[0]),
.d(d7)
);

assign q = r0r1r2r3r4r5r6r7;

endmodule

该模块则可以存储十六个8位数据,即有十六个地址(深度为3)。

1.4、十六个存储单位
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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/06/07 17:55:46
// Design Name:
// Module Name: mux16
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module mux16(
q,
d0,
d1,
d2,
d3,
d4,
d5,
d6,
d7,
d8,
d9,
d10,
d11,
d12,
d13,
d14,
d15,
a
);

parameter WIDTH = 8;

output [WIDTH-1 : 0] q;
input [WIDTH-1 : 0] d0,d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15;
input [3:0] a;

wire [WIDTH-1 : 0] q0,q1;

mux8 #(WIDTH) mux8_0(
.q(q0),
.d0(d0),
.d1(d1),
.d2(d2),
.d3(d3),
.d4(d4),
.d5(d5),
.d6(d6),
.d7(d7),
.a(a[2:0])
);

mux8 #(WIDTH) mux8_1(
.q(q1),
.d0(d8),
.d1(d9),
.d2(d10),
.d3(d11),
.d4(d12),
.d5(d13),
.d6(d14),
.d7(d15),
.a(a[2:0])
);

mux2 #(WIDTH) mux2_0(
.q(q),
.d0(q0),
.d1(q1),
.a(a[3])
);

endmodule

这个模块则存储十六个单位的8位数据,该模块由之前的mux8和mux2组合而成,由此我们可以组合出更多存储量更大的模块,如1K、2K的容量。

2、使用和测试

2.1 使用

使用时候,只需要在数据输入端口写入初始的数据,比如要存储的固化程序等,可以更改WIDTH参数以适应不同的位数;这里以存储十六个数据 1-16为例,调用模块如下:

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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/06/07 18:07:58
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module top(
q,
a
);

parameter WIDTH = 8;
parameter DEPTH = 4;

output [WIDTH-1 : 0] q;
input [DEPTH-1 : 0] a;

mux16 #(WIDTH) rom(
.q(q),
.d0(8'h01),
.d1(8'h02),
.d2(8'h03),
.d3(8'h04),
.d4(8'h05),
.d5(8'h06),
.d6(8'h07),
.d7(8'h08),
.d8(8'h09),
.d9(8'h0a),
.d10(8'h0b),
.d11(8'h0c),
.d12(8'h0d),
.d13(8'h0e),
.d14(8'h0f),
.d15(8'h10),
.a(a)
);

endmodule

当我们需要数据时候给定地址即可获取对应地址处的数据了。

2.2 仿真

编写仿真模块如下:

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
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2021/06/07 17:28:22
// Design Name:
// Module Name: tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module tb();

wire [7:0] q;
reg [3:0] a;

top top_inst(
.q(q),
.a(a)
);

integer cnt = 0;

initial begin
a = 0;
for (cnt = 0; cnt < 16; cnt = cnt + 1) begin
a = cnt;
#100;
end

$finish();
end

endmodule

  • 波形结果如下: