(实验环境:Vivado 2017.4)
实验要求:
实验过程:
1.打开Vivado,创建文件,选择xc7a35tcpg236-1核。
2.添加源文件。
ALU模块:
module ALU(OP,A,B,F,CF ); parameter SIZE = 32;//运算位数 input [3:0] OP;//运算操作 input [SIZE-1:0] A;//左运算数 input [SIZE-1:0] B;//右运算数 output [SIZE-1:0] F;//运算结果 output CF; //进位标志位 reg [SIZE-1:0] F; reg C,CF;//C为最高位进位 always@(*) begin C=0; case(OP) 4'b0000:begin F=A&B; end //按位与 4'b0001:begin F=A|B; end //按位或 4'b0010:begin F=A^B; end //按位异或 4'b0011:begin F=~(A|B); end //按位或非 4'b0100:begin {C,F}=A+B; end //加法 4'b0101:begin {C,F}=A-B; end //减法 4'b0110:begin F=A<B; end//A<B则F=1,否则F=0 4'b0111:begin F=B<<A; end //将B左移A位 endcase CF = C; end endmodule
Regester_File模块:
module Regester_File( Clk,Write_Reg,R_Addr_A,R_Addr_B,W_Addr,W_Data,R_Data_A,R_Data_B ); parameter ADDR = 5;//寄存器编码/地址位宽 parameter NUMB = 1<<ADDR;//寄存器个数 parameter SIZE = 32;//寄存器数据位宽 input Clk;//写入时钟信号 input Write_Reg;//写控制信号 input [ADDR-1:0]R_Addr_A;//A端口读寄存器地址 input [ADDR-1:0]R_Addr_B;//B端口读寄存器地址 input [ADDR-1:0]W_Addr;//写寄存器地址 input [SIZE-1:0]W_Data;//写入数据 output [SIZE-1:0]R_Data_A;//A端口读出数据 output [SIZE-1:0]R_Data_B;//B端口读出数据 reg [SIZE-1:0]REG_Files[0:NUMB-1];//寄存器堆本体 integer i;//用于遍历NUMB个寄存器 initial//初始化NUMB个寄存器,全为0 for(i=0;i<NUMB;i=i+1) REG_Files[i]<=i; always@(posedge Clk )//时钟信号或清零信号上升沿 begin if(Write_Reg) REG_Files[W_Addr]<=W_Data; end //读操作没有使能或时钟信号控制, 使用数据流建模(组合逻辑电路,读不需要时钟控制) assign R_Data_A=REG_Files[R_Addr_A]; assign R_Data_B=REG_Files[R_Addr_B]; endmodule
顶层模块:
module top( Clk,Write_Reg,Write_Select,//控制信号 R_Addr_A,R_Addr_B,W_Addr,//读写地址 R_Data_A,R_Data_B, OP,CF,ALU_F//ALU运算 ,W_Data ); parameter ADDR = 5; parameter SIZE = 32; input Clk; input Write_Reg;//写控制信号 input [ADDR-1:0]R_Addr_A;//A读端口寄存器地址 input [ADDR-1:0]R_Addr_B;//B读端口寄存器地址 input [ADDR-1:0]W_Addr;//写寄存器地址 output [SIZE-1:0]R_Data_A;//A端口读出数据 output [SIZE-1:0]R_Data_B;//B端口读出数据 input [3:0] OP; output CF; output [SIZE-1:0] ALU_F;//运算结果F input wire Write_Select;//写入数据选择信号 wire [SIZE-1:0]ALU_F; output reg [SIZE-1:0]W_Data; always@(*) begin case (Write_Select) 1'b0: W_Data=ALU_F; 1'b1: W_Data=32'b101; endcase end Regester_File RF_Test( //输入 .Clk(Clk),//时钟信号 .Write_Reg(Write_Reg),//写入控制 .R_Addr_A(R_Addr_A),//A端口读地址 .R_Addr_B(R_Addr_B),//B端口读地址 .W_Addr(W_Addr),//写入地址 .W_Data(W_Data), .R_Data_A(R_Data_A),//A端口读出数据 .R_Data_B(R_Data_B)//B端口读出数据 ); //实例化ALU模块 ALU ALU_Test( //输入 .OP(OP),//运算符 .A(R_Data_A),//从寄存器读A操作数 .B(R_Data_B),//从寄存器读B操作数 .F(ALU_F), .CF(CF) ); endmodule
测试模块:
module test( ); reg Clk, Write_Reg; reg Write_Select; reg [4:0] R_Addr_A ,R_Addr_B, W_Addr; reg [3:0] OP; wire [31:0] R_Data_A, R_Data_B, ALU_F; wire CF; wire [31:0] W_Data; initial begin Write_Reg=1; R_Addr_A=5'b01001; R_Addr_B=5'b01010; OP=4'b0100; Write_Select=1; W_Addr=5'b01001;Clk=0;#50; Clk=1;#50; W_Addr=5'b01010;Clk=0;#50; Clk=1;#50; W_Addr=5'b01000; Write_Select=0;Clk=0;#50;Clk=1;#50; end top RF_Test( .Clk(Clk), .Write_Reg(Write_Reg), .Write_Select(Write_Select), .R_Addr_A(R_Addr_A), .R_Addr_B(R_Addr_B), .W_Addr(W_Addr), .R_Data_A(R_Data_A), .R_Data_B(R_Data_B), .OP(OP), .CF(CF), .ALU_F(ALU_F), .W_Data(W_Data) ); endmodule
2.本实验采取仿真验证,直接进行仿真。(其实是懒得上板了)
3.观察仿真结果。
可以看到,在寄存器$9($t1)和$10($t2)都存储了5,说明写入存储器值成功;而busW(W_Data)为10,说明加法执行成功;此时W_Addr为$8(没验证写入加法结果成功,但肯定是成功的(确信))。