# 實驗目的 - 熟悉並掌握 MIPS 電腦中寄存器堆的原理和設計方法 - 理解源操作數/目的操作數的概念 # 實驗環境 * Vivado 集成開發環境 # MIPS寄存器 ![](https://pic.imgdb.cn/item/64f40fab661c6c8e5400bf9a.jpg) * ...
實驗目的
- 熟悉並掌握 MIPS 電腦中寄存器堆的原理和設計方法
- 理解源操作數/目的操作數的概念
實驗環境
- Vivado 集成開發環境
MIPS寄存器
- 寄存器R0的值恆為0。
模塊介面設計
1個寫埠和2個讀埠
名稱 | 寬度 | 方向 | 描述 |
---|---|---|---|
clk | 1 | IN | 時鐘信號 |
raddr1 | 5 | IN | 寄存器堆讀地址1 |
rdata1 | 32 | OUT | 寄存器堆返回數據1 |
raddr2 | 5 | IN | 寄存器堆讀地址2 |
rdata2 | 32 | OUT | 寄存器堆返回數據2 |
we | 1 | IN | 寄存器堆寫使能 |
waddr | 5 | IN | 寄存器堆寫地址 |
wdata | 32 | IN | 寄存器堆寫數據 |
寄存器堆(regfile)實現了32個32位通用寄存器。
- 可以同時進行兩個寄存器的讀操作和一個寄存器的寫操作。
- 寫:寫使能信號(we)為1時寫有效,為0時無效。(write enable)
- 讀:讀操作可以同時讀兩個寄存器。
- 同時對同一個寄存器進行讀寫時,讀的數據為舊的數據。
- 讀寫均為同步。
- 0號寄存器恆為0。
設計代碼
`define REG_DATA_WIDTH 31:0
`define REG_NUM 31:0
`define REG_ADDR_WIDTH 4:0
`define REG_ADDR_BIT 5 // 地址線寬
`define REG_DATA_BIT 32 // 數據線寬
module regfile(
input clk,
input [`REG_ADDR_WIDTH] raddr1,
input [`REG_ADDR_WIDTH] raddr2,
input we, // 寫使能
input [`REG_ADDR_WIDTH] waddr, // 寫地址
input [`REG_DATA_WIDTH] wdata, // 寫數據
output reg [`REG_DATA_WIDTH] rdata1,
output reg [`REG_DATA_WIDTH] rdata2
);
// 數組表示寄存器堆
reg [`REG_DATA_WIDTH] mips_regfile [`REG_NUM];
// 讀1
always @(posedge clk) begin
if (raddr1 == {`REG_ADDR_BIT{1'b0}}) begin
rdata1 <= {`REG_DATA_BIT{1'b0}};
end
else begin
rdata1 <= mips_regfile[raddr1];
end
end
// 讀2
always @(posedge clk) begin
if (raddr2 == {`REG_ADDR_BIT{1'b0}}) begin
rdata2 <= {`REG_DATA_BIT{1'b0}};
end
else begin
rdata2 <= mips_regfile[raddr2];
end
end
// 寫
always @(posedge clk) begin
if (we == 1'b1 ) begin
if (waddr == {`REG_ADDR_BIT{1'b0}}) begin
mips_regfile[0] <= {`REG_DATA_BIT{1'b0}};
end
else begin
mips_regfile[waddr] <= wdata;
end
end
else begin
mips_regfile[0] <= {`REG_DATA_BIT{1'b0}};
end
end
endmodule
測試
測試代碼
`timescale 1ns / 1ps
`define REG_DATA_WIDTH 31:0
`define REG_NUM 31:0
`define REG_ADDR_WIDTH 4:0
`define REG_ADDR_BIT 5
`define REG_DATA_BIT 32
module sim();
reg clk;
reg [`REG_ADDR_WIDTH] raddr1;
reg [`REG_ADDR_WIDTH] raddr2;
reg we; // 寫使能
reg [`REG_ADDR_WIDTH] waddr; // 寫地址
reg [`REG_DATA_WIDTH] wdata; // 寫數據
wire [`REG_DATA_WIDTH] rdata1;
wire [`REG_DATA_WIDTH] rdata2;
integer i;
regfile u0 (
.clk(clk),
.raddr1(raddr1),
.raddr2(raddr2),
.we(we),
.waddr(waddr),
.wdata(wdata),
.rdata1(rdata1),
.rdata2(rdata2)
);
initial begin
clk = 1;
forever begin
#10 clk = ~clk;
end
end
initial begin
raddr1 = `REG_ADDR_BIT'd0;
raddr2 = `REG_ADDR_BIT'd0;
we = 1'b0;
waddr = `REG_ADDR_BIT'd0;
wdata = `REG_DATA_BIT'd0;
// 寫數據
#100
we = 1'b1;
wdata = `REG_DATA_BIT'hFF;
for (i = 0; i < `REG_DATA_BIT; i = i + 1) begin
waddr = i;
wdata = wdata + `REG_DATA_BIT'h100;
#20;
end
// 讀數據
we = 1'b0;
for (i = 0; i < `REG_DATA_BIT; i = i + 1) begin
raddr1 = i;
raddr2 = `REG_DATA_BIT - raddr1 - 1;
#20;
end
// 讀寫相同
// 讀到的數據是舊數據
we = 1'b1;
wdata = `REG_DATA_BIT'h100;
for (i = 0; i < `REG_DATA_BIT; i = i + 1) begin
raddr1 = i;
raddr2 = i;
waddr = i;
wdata = wdata - `REG_DATA_BIT'h1;
#20;
end
we = 1'b0;
#100 $finish;
end
endmodule
測試波形
寫數據:
從 0號寄存器開始到 31號寄存器,分別寫入 01ff到 20ff。
讀數據:
讀地址 1和讀地址 2分別讀寄存器值,0號寄存器讀得值為 0。其餘寄存器讀值正確。
結果分析
先進行寫數據測試,從 0號寄存器開始到 31號寄存器,分別寫入 01ff到 20ff。然後進行讀數據測試,發現 0號寄存器值為 0,其餘寄存器的值符合預期。當同時寫和讀,即寫地址和讀地址相同,且寫使能時,發現讀到的數據為舊數據,而寫入的數據不會衝突。
本文來自博客園,作者:江水為竭,轉載請註明原文鏈接:https://www.cnblogs.com/Az1r/p/17674985.html