(1). 深入了解ALU原理;
(2). 学习使用verilog HDL 进行行为级ALU的设计与仿真;
(1)原理描述
定义输入输出:8位输入A和B,4位输入ALU_Sel,8位输出ALU_Out和1位输出CarryOut。
定义中间变量ALU_Result,用于存储ALU运算的结果。
定义一个临时变量tmp,用于存储A加B的值。
将ALU_Out输出赋值为ALU_Result。
将tmp赋值为{1'b0,A} + {1'b0,B}。
将CarryOut输出赋值为tmp的第8位。
在always @(*)块中使用case语句,根据ALU_Sel的值执行不同的运算。
对于每种情况,将ALU_Result赋值为对应的运算结果。
如果ALU_Sel的值无法匹配任何情况,则默认执行算术加法。
(2)Verilog HDL设计源代码描述(要求:注释)
module alu(
input [7:0] A,B, // ALU 8位 输入
input [3:0] ALU_Sel,// ALU 选择
output [7:0] ALU_Out, // ALU 8位输出
output CarryOut // Carry Out Flag
);
reg [7:0] ALU_Result;
wire [8:0] tmp;
assign ALU_Out = ALU_Result; // ALU
assign tmp = {1'b0,A} + {1'b0,B};
assign CarryOut = tmp[8]; // Carryout flag
always @(*)
begin
case(ALU_Sel)
4'b0000: // 算数加法
ALU_Result = A + B ;
4'b0001: // 算数减法
ALU_Result = A - B ;
4'b0010: // 乘法
ALU_Result = A * B;
4'b0011: // 除法
ALU_Result = A/B;
4'b0100: // shift left逻辑左移
ALU_Result = A<<1;
4'b0101: // shift right 逻辑右移
ALU_Result = A>>1;
4'b0110: // Rotate left 循环左移
ALU_Result = {A[6:0],A[7]};
4'b0111: // Rotate right循环右移
ALU_Result = {A[0],A[7:1]};
4'b1000: // and 逻辑与
ALU_Result = A & B;
4'b1001: // or逻辑或
ALU_Result = A | B;
4'b1010: // xor 异或
ALU_Result = A ^ B;
4'b1011: //nor或非
ALU_Result = ~(A | B);
4'b1100: //nand 与非
ALU_Result = ~(A & B);
4'b1101: //xnor 同或
ALU_Result = ~(A ^ B);
4'b1110: // 比较大小
ALU_Result = (A>B)?8'd1:8'd0 ;
4'b1111: // 比较像等
ALU_Result = (A==B)?8'd1:8'd0 ;
default: ALU_Result = A + B ;
endcase
end
endmodule
(3)TestBeach仿真代码及仿真结果
`timescale 1ns / 1ps
module tb_alu;
//Inputs
reg[7:0] A,B;
reg[3:0] ALU_Sel;
//Outputs
wire[7:0] ALU_Out;
wire CarryOut;
// Verilog code for ALU
integer i;
alu test_unit(
A,B, // ALU 8-bit Inputs
ALU_Sel,// ALU Selection
ALU_Out, // ALU 8-bit Output
CarryOut // Carry Out Flag
);
initial begin
// hold reset state for 100 ns.
A = 8'h0A;
B = 4'h02;
ALU_Sel = 4'h0;
for (i=0;i<=15;i=i+1)
begin
ALU_Sel = ALU_Sel + 8'h01;
#10;
end;
A = 8'hF6;
B = 8'h0A;
end
endmodule
1. 实验目的
(1). 深入了解寄存器原理;
(2). 学习使用verilog HDL 进行行为级寄存器的设计与仿真;
2. 实验内容
(1)原理描述
寄存器文件共有32个寄存器,每个寄存器宽度为32位。
该模块有以下输入:
clk:控制模块操作的时钟信号。
wen:写使能信号。当它为高电平(1)时,执行写操作。
raddr1:第一个要读取的寄存器的地址。
raddr2:第二个要读取的寄存器的地址。
waddr:要写入的寄存器的地址。
wdata:要写入寄存器的数据。
模块输出:
rdata1:从第一个寄存器读取的数据。
rdata2:从第二个寄存器读取的数据。
test_data:从由test_addr输入指定的寄存器读取的数据。
模块输入:
test_addr:用于测试的要读取的寄存器的地址。
该模块有一个用于存储数据的寄存器数组REG_Files。initial块用于将所有寄存器初始化为0。具有正边沿触发的clk输入的always块用于在wen为高电平时执行写操作。
(2)Verilog HDL设计源代码描述(要求:注释)
`timescale 1ns / 1ps
module regfile(
input clk, //时钟控制信号
input wen, //写使能信号,1有效
input [4 :0] raddr1, //第一个读端口的地址
input [4 :0] raddr2, //第二个读端口的地址
input [4 :0] waddr, //一个写端口
input [31:0] wdata, //需要写入的数据
output [31:0] rdata1, //读出的数据1
output [31:0] rdata2, //读出的数据2
input [4 :0] test_addr, //输入的调试地址
output [31:0] test_data //输出调试数据
);
//总共32个寄存器
integer i = 0;
reg [31:0] REG_Files[31:0];
initial//初始化32个寄存器,全为0
for(i = 0;i < 32;i = i + 1)
REG_Files[i]<=0;
always @ (posedge clk)
begin
if(wen)
REG_Files[waddr] <= wdata;
end
assign rdata1 = REG_Files[raddr1] ;
assign rdata2 = REG_Files[raddr2];
assign test_data = REG_Files[test_addr];
endmodule
(3)TestBeach仿真代码及仿真结果
module tb_regfile();
// Inputs
reg clk;
reg wen;
reg [4 :0] raddr1;
reg [4 :0] raddr2;
reg [4 :0] waddr;
reg [31:0] wdata;
reg [4 :0] test_addr;
// Outputs
wire [31:0] rdata1;
wire [31:0] rdata2;
wire [31:0] test_data;
// Instantiate the Unit Under Test (UUT)
regfile rf(
.clk(clk),
.wen(wen),
.raddr1(raddr1),
.raddr2(raddr2),
.waddr(waddr),
.wdata(wdata),
.rdata1(rdata1),
.rdata2(rdata2),
.test_addr(test_addr),
.test_data(test_data)
);
initial begin
// Initialize Inputs
clk = 0;
wen = 0;
raddr1 = 0;
raddr2 = 0;
waddr = 0;
wdata = 0;
test_addr = 0;
// Wait 100 ns for global reset to finish
#100;
waddr = 5'h05;
wdata = 32'h3F;
#400;
wen = 1'b1;
#500;
wen = 1'b0;
#400;
raddr1 = 5'h05;
#500;
raddr2 = 5'h05;
#400;
test_addr = 5'h05;
// Add stimulus here
end
always #5 clk = ~clk;
endmodule