规则之树———ram储存器

介绍

在前面的章节中,我们知道了ram存放着编译完后的cpu指令,就是这些指令让我们完成了一系列工作操作。所以在本章中我们将搭建一个简单的8位ram。

引脚介绍

  • clk 时钟引脚
  • rst 复位引脚
  • we 读写使能引脚 为1时写,0时读
  • data_in 数据输入引脚
  • addr 地址输入引脚
  • data_out 数据输出引脚

功能介绍

这个简单的ram储存器,我们只实现了读和写功能,读功能是读取地址addr所对应的内存中的数据,写功能是向地址addr所对应的内存中写入数据data_in。we控制模式选择,为1时写,为0时读。

代码实现

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
module ram_8bit(
input reg clk, // 时钟信号
input reg rst, // 复位信号
input reg we, // 写使能信号,高电平有效
input reg [7:0] data_in, // 数据输入
input reg [7:0] addr, // 地址总线
output wire [7:0] data_out // 数据输出
);

// 定义一个256x8位的RAM存储空间
reg [7:0] ram[255:0];
reg [7:0] data_out_r;

assign data_out = data_out_r;

integer i; // 用于复位过程中的循环变量

// 同步读写操作,添加异步复位逻辑
always @(posedge clk or posedge rst) begin
if (rst) begin
// 异步复位,将RAM的每个位置清零
for (i = 0; i < 256; i = i + 1) begin
ram[i] <= 8'b0;
end
end else begin
if (we) begin
// 写操作
ram[addr] <= data_in;
data_out_r <= 8'bz; // 写模式时,输出设置为高阻态
end else begin
// 读操作
data_out_r <= ram[addr];
end
end
end
endmodule

测试代码

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

`timescale 1ns / 1ps

module ram_8bit_tb;

reg clk;
reg rst;
reg we;
reg [7:0] data_in;
reg [7:0] addr;
wire [7:0] data_out;

// 实例化ram_8bit模块
ram_8bit uut (
.clk(clk),
.rst(rst),
.we(we),
.data_in(data_in),
.addr(addr),
.data_out(data_out)
);

// 产生时钟信号
always #10 clk = ~clk; // 产生50MHz的时钟信号

// 测试过程
initial begin
// 初始化信号
clk = 0;
rst = 1;
we = 0;
data_in = 0;
addr = 0;

// 复位RAM
#20;
rst = 0; // 释放复位

// 写入数据到RAM的地址0
#20;
we = 1;
data_in = 8'hA5;
addr = 8'h00;
#20;
we = 0;

// 读取数据从RAM的地址0
#20;
addr = 8'h00;

// 写入并读取另一个地址的数据
#20;
we = 1;
data_in = 8'h5A;
addr = 8'h01;
#20;
we = 0;
addr = 8'h01;
end
endmodule

结语

到此为止我们完成了cpu所有模块的verilog实现,在下一章我们会将他们全都拼凑起来,组成一个完整的cpu,敬请期待。

整点二次元

img1