计算机组成实验-第5章_R指令设计实现
2013-04-09 11:26
393 查看
/*主要问题,result=AopB,如果所有的always都是posedge clk触发,则会出现不同步的问题,因为A和B的值从寄存器取出进行运算得到结果之后,结果需要等到下一个时钟周期才能写入result: 第一个时钟周期的操作是解析指令,将A和B的值从寄存器堆中取出,并且计算得到ALUoper的值。 第二个时钟周期:计算result的值。 这样result会比A和B晚一个时钟周期。 因此,将ALUnit中的always改成*触发,这样: 第一个时钟周期的操作是解析指令,将A和B的值从寄存器堆中取出,并且计算得到ALUoper的值,一旦三个值得到,计算结果会立刻写入result(得益于ALUnit中的always循环没有停顿)。 */ //住模块代码 module Rtype(clk, rst, instru, Adat, Bdat, result); input clk; input rst; input [31:0] instru; output[31:0] result, Adat, Bdat;//Adat, Bdat为对应的两个操作数寄存器rs和rt,result对应rd wire [31:0] result; wire [31:0] Wdat, Adat, Bdat, ALUout; wire [2:0] ALUoper; RegFile s1(clk, instru[25:21], instru[20:16], instru[15:11],result, Adat, Bdat, 1);//生成子模块实例 ALUctr s2(clk, 2'b10,instru[5:0],ALUoper); ALUnit s3(clk, Adat, Bdat, ALUoper, result, zero); endmodule module RegFile(clk, rs, rt, rd, result, A, B, RegWrite);//构建寄存器堆,并存取。 input clk; input [4:0] rs, rt, rd; input [31:0] result; input RegWrite; output [31:0] A, B; reg [31:0] A, B; //下边是对应寄存器堆 reg[31:0] Szero, Sat, Sv0, Sv1, Sa0, Sa1, Sa2, Sa3;//0-7 reg[31:0] St0, St1, St2, St3, St4, St5, St6, St7;//8-15, Temp reg[31:0] Ss0, Ss1, Ss2, Ss3, Ss4, Ss5, Ss6, Ss7;//16-23, Saved reg[31:0] St8, St9, Sk0, Sk1, Sgp, Ssp, Sfp, Sra;//24-31 //以下初值仅用于测试 initial begin Szero = 0; Sat=1; Sv0=2; Sv1=3; Sa0=4; Sa1=5; Sa2=6; Sa3=7; St0=8; St1=9; St2=10; St3=11; St4=12; St5=13; St6=14; St7=15; Ss0=16; Ss1=17; Ss2=18; Ss3=19; Ss4=20; Ss5=21; Ss6=22; Ss7=23; St8=24; St9=25; Sk0=26; Sk1=27; Sgp=28; Ssp=29; Sfp=30; Sra=31; end //根据寄存器号取对应寄存器值(rs和rt) always @(posedge clk) begin case (rs) 0:A=0; //$zero 1:A=Sat; 2:A=Sv0; 3:A=Sv1; 4:A=Sa0; 5:A=Sa1; 6:A=Sa2; 7:A=Sa3; 8:A=St0; 9:A=St1; 10:A=St2; 11:A=St3; 12:A=St4; 13:A=St5; 14:A=St6; 15:A=St7; 16:A=Ss0; 17:A=Ss1; 18:A=Ss2; 19:A=Ss3; 20:A=Ss4; 21:A=Ss5; 22:A=Ss6; 23:A=Ss7; 24:A=St8; 25:A=St9; 26:A=Sk0; 27:A=Sk1; 28:A=Sgp; 29:A=Ssp; 30:A=Sfp; 31:A=Sra; endcase case (rt) 0:B=0;//$zero 1:B=Sat; 2:B=Sv0; 3:B=Sv1; 4:B=Sa0; 5:B=Sa1; 6:B=Sa2; 7:B=Sa3; 8:B=St0; 9:B=St1; 10:B=St2; 11:B=St3; 12:B=St4; 13:B=St5; 14:B=St6; 15:B=St7; 16:B=Ss0; 17:B=Ss1; 18:B=Ss2; 19:B=Ss3; 20:B=Ss4; 21:B=Ss5; 22:B=Ss6; 23:B=Ss7; 24:B=St8; 25:B=St9; 26:B=Sk0; 27:B=Sk1; 28:B=Sgp; 29:B=Ssp; 30:B=Sfp; 31:B=Sra; endcase //write reg rd if (RegWrite == 1) case (rd) 0:Szero=0; 1:Sat=result; 2:Sv0=result; 3:Sv1=result; 4:Sa0=result; 5:Sa1=result; 6:Sa2=result; 7:Sa3=result; 8:St0=result; 9:St1=result; 10:St2=result; 11:St3=result; 12:St4=result; 13:St5=result; 14:St6=result; 15:St7=result; 16:Ss0=result; 17:Ss1=result; 18:Ss2=result; 19:Ss3=result; 20:Ss4=result; 21:Ss5=result; 22:Ss6=result; 23:Ss7=result; 24:St8=result; 25:St9=result; 26:Sk0=result; 27:Sk1=result; 28:Sgp=result; 29:Ssp=result; 30:Sfp=result; 31:Sra=result; endcase end endmodule //根据function field的值进行计算 module ALUnit(clk, A, B, ALUoper, result, zero); input clk; input [31:0] A, B; input [2:0] ALUoper; output zero; reg zero; output [31:0] result; reg [31:0] result; always @(*) begin/*always @(posedge clk) begin 会有延迟,计算结果不能立刻写入result,也不能立刻写入寄存器堆。*/ case (ALUoper) 3'b000: result = A & B; 3'b001: result = A | B; 3'b010: result = A + B; 3'b110: result = A - B; 3'b111: result = (A<B)?1:0; default: result = A + B;//Add endcase zero = (A==B)?1:0; end endmodule //为什么有些地方always @ (*)会出问题。。 module ALUctr(clk, ALUop, Func, op); input clk; input [1:0] ALUop; input [5:0] Func; output [2:0] op; reg[2:0] op; always @(posedge clk) begin// 如果改成always @(*) begin会出现不同步的问题。 case (ALUop[1]) 1'b0:case (ALUop[0]) 1'b0:op<=3'b010; 1'b1:op<=3'b110; endcase 1'b1:case (Func) 6'b100000:op<=3'b010; 6'b100010:op<=3'b110; 6'b100100:op<=3'b000; 6'b100101:op<=3'b001; 6'b101010:op<=3'b111; endcase endcase end endmodule //测试代码,可以再仿真中修改数字显示的格式(二进制、十进制等),还可以修改时间窗口的长短。 module test; reg clk = 1'b0; reg rst = 1'b0; reg [31:0] I = 32'b00000000000000000000000000000000; wire [31:0] A; wire [31:0] B; wire [31:0] result; parameter PERIOD = 20;//时钟周期长短 parameter real DUTY_CYCLE = 0.5; parameter OFFSET = 0; initial // Clock process for clk begin #OFFSET; forever//10ns,clk会翻转一次 begin clk = 1'b0; #(PERIOD-(PERIOD*DUTY_CYCLE)) clk = 1'b1; #(PERIOD*DUTY_CYCLE); end end Rtype UUT ( .clk(clk), .rst(rst), .instru(I), .Adat(A), .Bdat(B), .result(result));//将A作为子模块输入,对应子模块里边的Adat initial begin // ------------- Current Time: 105ns #105; rst = 1'b1; // ------------------------------------- // ------------- Current Time: 405ns #300; I = 32'b00000001101010001000000000100000; // ------------------------------------- // ------------- Current Time: 1405ns #1000; I = 32'b00000001110010011000100000100010; // ------------------------------------- // ------------- Current Time: 2405ns #1000; I = 32'b00000001111010101001000000100100; // ------------------------------------- // ------------- Current Time: 3405ns #1000; I = 32'b00000011000010111001100000100101; // ------------------------------------- // ------------- Current Time: 4405ns #1000; I = 32'b00000011001011001010000000101010; // ------------------------------------- end endmodule
相关文章推荐
- [置顶] [计算机组成原理][R-I-J型指令CPU设计实验总结]
- [计算机组成原理][实验十.R-I-J型指令CPU设计实验总结]
- 计算机组成与设计(二)——指令:计算机指令 (一)
- [置顶] 计算机组成原理实验:乘法实现
- SWJTU计算机组成实验C-实验六 运算器的设计
- SWJTU计算机组成实验C-实验八 指令分析与执行
- SWJTU计算机组成实验C-实验四 算术逻辑单元(ALU)设计
- 计算机为什么能实现软关机??? 软关机设计到哪些技术??? 指令??? 电路??
- 计算机组成原理课程设计 Dais CMX16 模型机指令及微指令设计
- 计算机组成原理课程设计实验一:验证74LS181运算和逻辑功能
- 计算机组成原理 实验1 Cache模拟器的实现
- 计算机组成实验-第6章_CPU控制器设计
- 计算机组成实验-第3章-Datapath基本组件设计
- 计算机组成实验-第7章_单时钟数据通路设计
- 计算机组成实验-第4章_ALU与ALU控制器设计实验
- 计算机组成原理课程设计-基本模型机的设计与实现
- 计算机组成原理课程设计(vhdl语言实现)
- 计算机组成原理课程设计 Dais CMX16 模型机指令及微指令设计
- 设计模式之第5章-解释器模式(Java实现)
- 用ModelSim、Mars和Verilog做计算机组成原理CPU实验注意事项