(實驗環境: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(沒驗證寫入加法結果成功,但肯定是成功的(確信))。