杭电计算机组成原理实验RISC-V 实验 寄存器堆与运算器设计实验实验报告
- 一、实验目的与要求
- 1、 实验目的:
- a) 学习寄存器堆的结构传送原理,掌握三端寄存器堆的设计方法
- b) 掌握运算器的结构与工作原理,能将寄存器堆与暂存器ALU进行正确连接,构成运算器
- 2、 实验要求:首先设计一个RVI321指令集架构的寄存器堆(32*32),然后将其与前述实验中的暂存器A、B、F和ALU进行链接,构成一个完整的运算器。
- 二、实验设计与程序代码
- 1、 模块设计说明
- 2、 实验程序源代码及注释等
- 1、 仿真波形
- 2、 仿真结果分析
- 四、电路图
- 五、引脚配置
- 六、思考与探索
- 1、实验结果记录:
- 2、实验结论:
- 3、问题与解决方案:
- 4、思考题:
- a) 寄存器堆的判断写入成功,通过写入的寄存器和零号寄存器单元进行加法来计算判断是否写入成功(零号寄寄存器永远为0)
- b) ALU_OP可以为一个部分,CLK_A和CLK_B为一个部分,clk_write为一个部分,这三个部分可以分开写。那么一共只需要10个开关。
- c) 不能,因为clk_RR是将寄存器堆模块的数据打入到寄存器模块中,clk_F是将寄存器模块的A,B计算出F放入到寄存器模块中,而clk_WB是将寄存器的F打入到寄存器堆当中,这其中功能不同,所以不能合并。
- d) 可以将寄存器堆设置一个使能控制,表示单一输出,那么则只需要一个输出接口了,同时还可以加上一个相关的立即数存入B中,再进行后续的计算。
- e) 在这个寄存器堆设计实验中,这个实验理解起来稍微困难,起初已经写好了代码,进行了仿真,出现了波形,但是后来老师要求读操作和写操作输出了不同的数据,在不同的单元。于是我就把仿真代码改了一下,将W_Data,W_Addr等数据做了修改。这个实验也就成功了。通过做这个寄存器堆设计实验,我对寄存器堆的读写操作有了一个新的认识和理解了。也对ISE这个软件的运用更加熟练,对寄存器堆这个概念也有了更深层次的理解,增长了我的只是,强化了我的实践能力以及思考能力。这次实验收获巨大。
一、实验目的与要求
1、 实验目的:
a) 学习寄存器堆的结构传送原理,掌握三端寄存器堆的设计方法
b) 掌握运算器的结构与工作原理,能将寄存器堆与暂存器ALU进行正确连接,构成运算器
2、 实验要求:首先设计一个RVI321指令集架构的寄存器堆(32*32),然后将其与前述实验中的暂存器A、B、F和ALU进行链接,构成一个完整的运算器。
二、实验设计与程序代码
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
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274`timescale 1ns / 1ps // // Company: // Engineer: // // Create Date: 23:38:21 05/07/2021 // Design Name: // Module Name: main // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // // module main( input wire clk_WB,reg_Write, input wire [4:0] R_Addr_A,R_Addr_B,W_Addr, input wire [3:0] ALU_OP, input wire clk_F,res_n, input wire clk_RR, input wire clk_25M, output wire ZF,SF,CF,OF, output wire [3:0] AN, output wire [7:0] seg ); wire [31:0] R_DataA,R_DataB,W_Data,R_DataF; wire [31:0] A,B; wire [31:0] F; DataInput mydatainput(res_n,W_Addr,clk_WB,reg_Write,R_Addr_A,R_Addr_B,F,R_DataA,R_DataB);//寄存器堆的区块 ALU myalu(A,B,clk_F,ALU_OP,R_DataF,ZF,SF,CF,OF);//ALU计算的模块 ShowNum myShowNum(clk_25M,F,seg,AN);//数码管显示的模块 ABIPUT myabinput(clk_RR,R_DataA,R_DataB,R_DataF,A,B,F);//AB暂存器赋值模块 endmodule module ABIPUT(//暂存器AB进行赋值模块 input clk_RR, input [31:0] R_DataA,R_DataB,R_DataF, output reg [31:0] A,B,F ); always@(posedge clk_RR) begin A<=R_DataA; B<=R_DataB; end always@(*) begin F<=R_DataF; end endmodule module DataInput(//暂存器堆的重置清零和R_Addr_A,R_Addr_B,的赋值 input wire res_n, input wire [4:0] W_Addr, input wire clk_Regs,reg_Write, input wire [4:0] R_Addr_A,R_Addr_B, input wire [31:0] F, output reg [31:0] R_DataA,R_DataB ); reg [31:0] regs [31:0]; initial begin regs[0]=0; regs[1]=1; regs[2]=2; regs[3]=3; regs[4]=4; regs[5]=5; regs[6]=6; regs[7]=7; regs[8]=8; regs[9]=9; regs[10]=10; regs[11]=11; regs[12]=12; regs[13]=13; regs[14]=14; regs[15]=15; regs[16]=16; regs[17]=17; regs[18]=18; regs[19]=19; regs[20]=20; regs[21]=21; regs[22]=22; regs[23]=23; regs[24]=24; regs[25]=25; regs[26]=26; regs[27]=27; regs[28]=28; regs[29]=29; regs[30]=32'b10000000000000000000000000000000; regs[31]=32'b01111111111111111111111111111111; end always@(posedge clk_Regs or posedge res_n) begin if(res_n) begin regs[0]<=0; regs[1]<=1; regs[2]<=2; regs[3]<=3; regs[4]<=4; regs[5]<=5; regs[6]<=6; regs[7]<=7; regs[8]<=8; regs[9]<=9; regs[10]<=10; regs[11]<=11; regs[12]<=12; regs[13]<=13; regs[14]<=14; regs[15]<=15; regs[16]<=16; regs[17]<=17; regs[18]<=18; regs[19]<=19; regs[20]<=20; regs[21]<=21; regs[22]<=22; regs[23]<=23; regs[24]<=24; regs[25]<=25; regs[26]<=26; regs[27]<=27; regs[28]<=28; regs[29]<=29; regs[30]<=32'b10000000000000000000000000000000; regs[31]<=32'b01111111111111111111111111111111; end else begin if(reg_Write==1'b1) begin if(W_Addr!=0) begin regs[W_Addr]<=F; end end end end always@(*) begin R_DataA<=regs[R_Addr_A]; R_DataB<=regs[R_Addr_B]; end endmodule module ALU(//ALU的计算模块 input [31:0] A,B, input clk_F, input [3:0] ALU_OP, output reg [31:0] F, output reg ZF,SF,CF,OF ); reg F32; always@(posedge clk_F) begin case(ALU_OP) 4'b0000:begin {F32,F}<=A+B;end 4'b0001:begin F<=A<<B;end 4'b0010:begin F<=($signed(A)<$signed(B))?1:0;end 4'b0011:begin F<=(A<B)?1'b1 : 1'b0;end 4'b0100:begin F<=A^B;end 4'b0101:begin F<=A>>B;end 4'b0110:begin F<=A|B;end 4'b0111:begin F<=A&B;end 4'b1000:begin {F32,F}<=A-B;F32<=~F32; end 4'b1001:begin F<=($signed(A))>>>B;end endcase ZF<=(F>0)?1'b0:1'b1; SF<=F[31]; CF<=F32; OF<=A[31]^B[31]^F[31]^F32; end endmodule module ShowNum(//数码管模块用于显示数据 input clk_25M, input [31:0] F, output reg [7:0]seg, output reg [3:0]AN ); parameter count=10000; reg [31:0] clk_num; reg [3:0] digit; reg [2:0] which; initial begin clk_num=0; which=0; digit=0; end always@(posedge clk_25M) begin if(clk_num<count) begin clk_num<=clk_num+1;end else begin clk_num<=0; which<=which+3'b001; case(which) 0: begin digit<=F[3:0];end 1: begin digit<=F[7:4];end 2: begin digit<=F[11:8];end 3: begin digit<=F[15:12];end 4: begin digit<=F[19:16];end 5: begin digit<=F[23:20];end 6: begin digit<=F[27:24];end 7: begin digit<=F[31:28];end endcase end end always@(digit,which) begin case(which) 0: begin AN=4'b1111;end 1: begin AN=4'b1110;end 2: begin AN=4'b1101;end 3: begin AN=4'b1100;end 4: begin AN=4'b1011;end 5: begin AN=4'b1010;end 6: begin AN=4'b1001;end 7: begin AN=4'b1000;end default:AN=4'bzzzz; endcase case(digit) 0:seg[7:0]=8'b00000011; 1:seg[7:0]=8'b10011111; 2:seg[7:0]=8'b00100101; 3:seg[7:0]=8'b00001101; 4:seg[7:0]=8'b10011001; 5:seg[7:0]=8'b01001001; 6:seg[7:0]=8'b01000001; 7:seg[7:0]=8'b00011111; 8:seg[7:0]=8'b00000001; 9:seg[7:0]=8'b00001001; 10:seg[7:0]=8'b00010001; 11:seg[7:0]=8'b11000001; 12:seg[7:0]=8'b01100011; 13:seg[7:0]=8'b10000101; 14:seg[7:0]=8'b01100001; 15:seg[7:0]=8'b01110001; default:seg[7:0]=8'b11111111; endcase end endmodule end initial begin res_n=1; #100 R_Addr_A=8; R_Addr_B=8; #100 clk_RR=1; ALU_OP=0; #100 clk_F=1; #100 R_Addr_A=8; R_Addr_B=8; #100 clk_RR=1; ALU_OP=6; #100 clk_F=1; end endmodule
1、 仿真波形
(运行仿真时,波形截图)
2、 仿真结果分析
(对仿真波形进行分析)
主要是验证寄存器堆里面的存取以及赋值和运算模块的验证
四、电路图
(开发工具中显示的电路模块图)
五、引脚配置
(引脚约束文件的内容,描述主要配置情况)
NET “clk_F” CLOCK_DEDICATED_ROUTE = FALSE;
NET “clk_WB” CLOCK_DEDICATED_ROUTE = FALSE;
#PlanAhead Generated physical constraints
NET “ALU_OP[3]” LOC = T3;
NET “ALU_OP[2]” LOC = U3;
NET “ALU_OP[1]” LOC = T4;
NET “ALU_OP[0]” LOC = V3;
NET “AN[3]” LOC = L21;
NET “AN[2]” LOC = M22;
NET “AN[1]” LOC = M21;
NET “AN[0]” LOC = N22;
NET “R_Addr_A[4]” LOC = V4;
NET “R_Addr_A[3]” LOC = W4;
NET “R_Addr_A[2]” LOC = Y4;
NET “R_Addr_A[1]” LOC = Y6;
NET “R_Addr_A[0]” LOC = W7;
NET “R_Addr_B[4]” LOC = Y8;
NET “R_Addr_B[3]” LOC = Y7;
NET “R_Addr_B[2]” LOC = T1;
NET “R_Addr_B[1]” LOC = U1;
NET “R_Addr_B[0]” LOC = U2;
NET “seg[7]” LOC = H19;
NET “seg[6]” LOC = G20;
NET “seg[5]” LOC = J22;
NET “seg[4]” LOC = K22;
NET “seg[3]” LOC = K21;
NET “seg[2]” LOC = H20;
NET “seg[1]” LOC = H22;
NET “seg[0]” LOC = J21;
NET “W_Addr[4]” LOC = W1;
NET “W_Addr[3]” LOC = W2;
NET “W_Addr[2]” LOC = Y1;
NET “W_Addr[1]” LOC = AA1;
NET “W_Addr[0]” LOC = V2;
NET “clk_RR” LOC = R4;
NET “clk_F” LOC = AA4;
NET “reg_Write” LOC = AB8;
NET “clk_WB” LOC = AB6;
NET “res_n” LOC = T5;
NET “ZF” LOC = R1;
NET “SF” LOC = P2;
NET “CF” LOC = P1;
NET “OF” LOC = N2;
NET “clk_25M” LOC = H4;
#PlanAhead Generated IO constraints
NET “ALU_OP[3]” IOSTANDARD = LVCMOS18;
NET “ALU_OP[2]” IOSTANDARD = LVCMOS18;
NET “ALU_OP[1]” IOSTANDARD = LVCMOS18;
NET “ALU_OP[0]” IOSTANDARD = LVCMOS18;
NET “AN[3]” IOSTANDARD = LVCMOS18;
NET “AN[2]” IOSTANDARD = LVCMOS18;
NET “AN[1]” IOSTANDARD = LVCMOS18;
NET “AN[0]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[4]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[3]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[2]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[1]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[0]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[4]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[3]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[2]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[1]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[0]” IOSTANDARD = LVCMOS18;
NET “seg[7]” IOSTANDARD = LVCMOS18;
NET “seg[6]” IOSTANDARD = LVCMOS18;
NET “seg[5]” IOSTANDARD = LVCMOS18;
NET “seg[4]” IOSTANDARD = LVCMOS18;
NET “seg[3]” IOSTANDARD = LVCMOS18;
NET “seg[2]” IOSTANDARD = LVCMOS18;
NET “seg[1]” IOSTANDARD = LVCMOS18;
NET “seg[0]” IOSTANDARD = LVCMOS18;
NET “W_Addr[0]” IOSTANDARD = LVCMOS18;
NET “W_Addr[1]” IOSTANDARD = LVCMOS18;
NET “W_Addr[2]” IOSTANDARD = LVCMOS18;
NET “W_Addr[3]” IOSTANDARD = LVCMOS18;
NET “W_Addr[4]” IOSTANDARD = LVCMOS18;
NET “CF” IOSTANDARD = LVCMOS18;
NET “clk_25M” IOSTANDARD = LVCMOS18;
NET “clk_WB” IOSTANDARD = LVCMOS18;
NET “clk_RR” IOSTANDARD = LVCMOS18;
NET “clk_F” IOSTANDARD = LVCMOS18;
NET “OF” IOSTANDARD = LVCMOS18;
NET “reg_Write” IOSTANDARD = LVCMOS18;
NET “res_n” IOSTANDARD = LVCMOS18;
NET “SF” IOSTANDARD = LVCMOS18;
NET “ZF” IOSTANDARD = LVCMOS18;
NET “ALU_OP[3]” PULLDOWN;
NET “ALU_OP[2]” PULLDOWN;
NET “ALU_OP[1]” PULLDOWN;
NET “ALU_OP[0]” PULLDOWN;
NET “R_Addr_A[4]” PULLDOWN;
NET “R_Addr_A[3]” PULLDOWN;
NET “R_Addr_A[2]” PULLDOWN;
NET “R_Addr_A[1]” PULLDOWN;
NET “R_Addr_A[0]” PULLDOWN;
NET “R_Addr_B[4]” PULLDOWN;
NET “R_Addr_B[3]” PULLDOWN;
NET “R_Addr_B[2]” PULLDOWN;
NET “R_Addr_B[1]” PULLDOWN;
NET “R_Addr_B[0]” PULLDOWN;
NET “W_Addr[4]” PULLDOWN;
NET “W_Addr[3]” PULLDOWN;
NET “W_Addr[2]” PULLDOWN;
NET “W_Addr[1]” PULLDOWN;
NET “W_Addr[0]” PULLDOWN;
NET “clk_25M” PULLDOWN;
NET “clk_F” PULLDOWN;
NET “clk_RR” PULLDOWN;
NET “clk_WB” PULLDOWN;
NET “reg_Write” PULLDOWN;
NET “res_n” PULLDOWN;
六、思考与探索
1、实验结果记录:
先将reg[FFFFFFFFH]和reg[FFFFFFFEH]相加,再存入reg[1]中,最后对reg[1]与reg[1]相加得到FFFFFFFEH,则实验成功。
(实验操作的过程及结果记录)
2、实验结论:
本实验主要是为了寄存器堆的实现,我们发现寄存器堆的实现需要很多接口的输入和输出。同时也需要很多的时间去验收。
(分析实验结果,给出实验结论)
3、问题与解决方案:
本次实验的书写中我们主要发现问题还是分布在各个模块的关联性上面,同时没有满足相关的模块的逻辑顺序。
解决方案:具体读文件的顺序同时更多了解里面的实验原理。
(整个实验过程中发生了什么问题?你是如何解决的。)
4、思考题:
a) 寄存器堆的判断写入成功,通过写入的寄存器和零号寄存器单元进行加法来计算判断是否写入成功(零号寄寄存器永远为0)
b) ALU_OP可以为一个部分,CLK_A和CLK_B为一个部分,clk_write为一个部分,这三个部分可以分开写。那么一共只需要10个开关。
c) 不能,因为clk_RR是将寄存器堆模块的数据打入到寄存器模块中,clk_F是将寄存器模块的A,B计算出F放入到寄存器模块中,而clk_WB是将寄存器的F打入到寄存器堆当中,这其中功能不同,所以不能合并。
d) 可以将寄存器堆设置一个使能控制,表示单一输出,那么则只需要一个输出接口了,同时还可以加上一个相关的立即数存入B中,再进行后续的计算。
e) 在这个寄存器堆设计实验中,这个实验理解起来稍微困难,起初已经写好了代码,进行了仿真,出现了波形,但是后来老师要求读操作和写操作输出了不同的数据,在不同的单元。于是我就把仿真代码改了一下,将W_Data,W_Addr等数据做了修改。这个实验也就成功了。通过做这个寄存器堆设计实验,我对寄存器堆的读写操作有了一个新的认识和理解了。也对ISE这个软件的运用更加熟练,对寄存器堆这个概念也有了更深层次的理解,增长了我的只是,强化了我的实践能力以及思考能力。这次实验收获巨大。
最后
以上就是义气大米最近收集整理的关于杭电计算机组成原理实验RISC-V 实验 寄存器堆与运算器设计实验实验报告一、实验目的与要求二、实验设计与程序代码四、电路图五、引脚配置六、思考与探索的全部内容,更多相关杭电计算机组成原理实验RISC-V内容请搜索靠谱客的其他文章。
发表评论 取消回复