底层原理,  技术人生

Verilog组合设计:ALU算术逻辑单元

本文使用Verilog实现一个简单的16位算术逻辑单元ALU的组合设计,并完成相应的测试工作。组合设计属于Verilog行为设计的范畴,是将结构化功能进行抽象表示后完成的逻辑设计。

ALU功能需求定义如下:

ALU符号化表示

输入:16位X和Y作为计算操作数,2位M作为控制信号

输出:16位Q

控制信号功能模式:

M操作
00Y
01X+Y
10X+1
11X-Y

Verilog实现ALU模块:

// MU0 ALU design 

`timescale 1ns/100ps

// for simulation purposes
`default_nettype none

// module header

module mu0_alu(input  wire [15:0]  X, 
               input  wire [15:0]  Y, 
               input  wire [1:0]   M, 
               output reg  [15:0]  Q);

// behavioural description
always @ (*)
begin
	case (M)
		2'b00:	Q = Y;
		2'b01:	Q = X + Y;
		2'b10:	Q = X + 1;
		2'b11:	Q = X - Y;
		default:	Q = 16'hxxxx;
	endcase
end


endmodule 

// for simulation purposes
`default_nettype wire

输入参数使用wire类型,表示物理连线,输入内容始终直接由外部给定,无条件相等;输出参数使用reg类型,表示其值需要一定信号触发该变量才会被赋值,即通过触发才能使输出信号反映输入信号的状态,否则其值未定义。

使用always block和阻塞赋值语句对输出Q赋值(reg类型变量仅能在always块中被赋值)。整个区块对任意输入变量敏感,X、Y或M的变化都会触发ALU重新计算输出Q。区块中使用switch语句判断控制信号M,并根据功能需求完成相应的运算。default表示M未定义时输出Q未定义。

下面编写测试脚本(testbench)。

// MU0 ALU testbench 

// #1 = 1ns
`timescale 1ns/100ps 

module mu0_alu_tb();

// Internal connections
reg [15:0] X;
reg [15:0] Y;
reg [1:0]  M;
wire [15:0] Q;

// Instantiate mu0_alu as dut (device under test)
mu0_alu dut(X, Y, M, Q);

// Test vectors
initial
begin

// connectivity test, test if all inputs and output are normally connected, use Q=X+Y
#100 X=16'h0000; Y=16'h0000; M=2'b01;
// sensitivity test
// test if the output will response to the change of X
#100 X=16'h0001;
// test if the output will response to the change of Y
#100 Y=16'h0001;
// test different control signals M and corresponding functions, use identifiable X and Y
// test M=b00, Q=Y
#100 X=16'h3333; Y=16'h2222; M=2'b00;
// test M=b01, Q=X+Y
#100 M=2'b01;
// test M=b10, Q=X+1
#100 M=2'b10;
// test M=b11, Q=X-Y
#100 M=2'b11;
// test undefined control signal M
#100 M=2'bxx;


#100 $finish;   // end the simulation
end
 
// Save results as VCD file
initial
 begin
  $dumpfile("mu0_alu_tb_results.vcd");  // Save simulation waveforms in this file
  $dumpvars; // Capture all simulation waveforms
 end

endmodule

测试传入变量的类型恰好相反,输入变量为reg,输出变量为wire。因为输入变量会在测试过程中被主动更新,而输出直接获取模块的原始输出,无附加组合逻辑操作。

测试需要涵盖连接性测试,检测所有位的输入输出是否正常连通;感知列表测试,测试模块是否对各个输入变量的变化敏感,正常输出;控制逻辑测试,测试每一种控制信号M是否使程序正确完成相应算术操作。

在控制逻辑测试中,需要使用可辨识的X和Y,使X和Y的各类算术操作结果具有独特性,从而判断程序是否正确运作。控制逻辑测试包括控制信号M未定义的情况。

使用以下命令编译代码、执行并使用gtkwave可视化结果。(操作系统:Linux Mint)

iverilog -y. -o mu0_alu_output mu0_alu_tb.v
vvp mu0_alu_output
gtkwave mu0_alu_tb_results.vcd
ALU测试输出波形结果

A WindRunner. VoyagingOne

一条评论

  • copper

    学长你好,我是曼大大一cs的新生,在查资料的时候发现了你的网址,太nb了 !!!!
    很想认识一下你,交流交流

留言

您的邮箱地址不会被公开。 必填项已用 * 标注