草庐IT

Verilog设计一个32位ALU,并进行功能验证

ty_:-) 2023-04-13 原文

设计一个32位ALU,并进行功能验证

使用Quartus+modelsim完成设计

文章目录

题目如下,已经给定了端口定义。

分析

ALU需要实现的功能如下:

  • 算术运算
    • 加、减法运算
    • 协助进行串行乘、除法计算
  • 逻辑运算
    • 按位逻辑技术
    • and / nand / or / nor / xor / xnor / buf / not
    • 输出全0,全1值

题目给出了采用行波进位的32位ALU设计,通过分析,认为主体部分为一个32位串行全加器,全加器的输入由原本的a与b替换为组合逻辑电路。故分别设计32位串行加法器以及输入处的组合逻辑电路。

观察发现,令32位串行加法器的p和g进行定义即可。

对于1位ALU而言可以有以下公式来实现,其中的 S 0 , 1 , 2 , 3 S_{0,1,2,3} S0,1,2,3为控制信号:
S = S 3 ⋅ a ⋅ b + S 2 ⋅ a ⋅ b ˉ + S 1 ⋅ a ˉ ⋅ b + S 0 ⋅ a ˉ ⋅ b ˉ \begin{aligned} S=& S_3 \cdot a \cdot b+ S_2 \cdot a \cdot \bar{b}+ S_1 \cdot \bar{a} \cdot b+ S_0 \cdot \bar{a} \cdot \bar{b} \end{aligned} S=S3ab+S2abˉ+S1aˉb+S0aˉbˉ

那么拓展为32位,只需修改控制信号的位数即可

对于具体的选择控制信号以及逻辑和功能,见下表

选择控制信号
{S[3],S[2],S[1],S[0],Ci,M}
逻辑功能
0000100置全0
000110!A & !Bnor
001010!A & Bnotand
001110!Anot A
010010A & !Bandnot
010110!Bnot B
011010A&!B | !A&Bxor
011110!A | !Bnand
100010A & Band
100110A&B | !A & !Bxnor
101010B传送B
101110A&B | !A&B | !A&!Bnotor
110010A传送A
110110A&B | a&!B | !A&!Bor not
111010A&B | A&!B | !A&Bor
1111101置全1
100101A^B^C加法
011011(A~^B)^C减法

代码实现

在always过程块里,需要用到阻塞赋值,因为需要所有的output同时改变。

对于C:输出进位,直接去carry的最高位即可

对于V:溢出,这里采用最高位比较的方法,即 { o p A [ 31 ] , o p B [ 31 ] , D O [ 31 ] } = 3 ′ b 001 或者 3 ′ b 110 \{opA[31],opB[31],DO[31]\} = 3'b001 或者 3'b110 {opA[31],opB[31],DO[31]}=3b001或者3b110判定为溢出

对于N:符号位, D O DO DO的最高位

对于Z:用 ! ( D O ) !(DO) !(DO)判断

//32bit arithmetic and logic unit(ALU)
module ALU32#(
	parameter n =32
	)(
	input [n-1:0] opA,	//INPUT operand A	
	input [n-1:0] opB,	//INPUT operand B
	input [3:0]  S  ,	//INPUT Signal that selects working mode
	input wire   M  ,	//INPUT Signal that controls logical operation
	input wire   Cin,	//INPUT signal that carry
	output reg[n-1:0]DO,//OUTPUT DATA
	output wire C ,		//OUTPUT Carry
	output wire V ,		//Overflow
	output wire N ,		//DO's sign bit
	output wire Z		//if DO is 0
);
	reg [n-1:0] p;
	reg [n-1:0] g;
	reg [n:0] carry;
	//main body
	always@(opA,opB,S,M,Cin)
	//need blocking assignment
		begin
			carry[0] = Cin;
			g = {n{S[3]}}&opA&opB | {n{S[2]}}&opA&(~opB) | {n{(~M)}};
			//Expand bits
			//let every bit is S[3]/S[2]/(~M)
			//by {n{}}
			p = ~({n{S[3]}}&opA&opB | {n{S[2]}}&opA&(~opB) | {n{S[1]}}&(~opA)&opB | {n{S[0]}}&(~opA)&(~opB));
			//Expand bits
			//let every bit is S[3]/S[2]/S[1]/S[0]
			//by {n{}}
			carry[n:1] = g|(p&carry[n-1:0]);
			DO = p^carry[n-1:0];
		end
	
	//CVNZ analysis
	assign C = carry[n];//carry is the MSD of carry[n,0]
	assign V = (opA[n-1]&opB[n-1]&~DO[n-1]) | (~opA[n-1]&~opB[n-1]&DO[n-1]);//1:overflow;0:not
	assign N = DO[n-1];//sign bit is the MSD
	assign Z = (!(DO))?1:0;//if all bits are 0,then Z=1,else Z=0;

endmodule

Testbench

testbench撰写的时候讲分析中的表格中的所有情况进行了罗列,除了直接波形观察,为了更好的查看数据,使用$monitor,来得到所需数据。

`timescale 1 ns/ 1 ns
module ALU32_vlg_tst();
reg [3:0] S;
reg Cin;
reg M;

reg [31:0] opA;
reg [31:0] opB;
// wires      
wire [31:0]  DO;                                         
wire C;
wire V;
wire N;
wire Z;

// assign statements (if any)                          
ALU32 i1 (
// port map - connection between master ports and signals/registers   
	.C(C),
	.Cin(Cin),
	.DO (DO),
	.M(M),
	.N(N),
	.S(S),
	.V(V),
	.Z(Z),
	.opA(opA),
	.opB(opB)
);

//18 kinds of situation
initial                                                
begin    
	{S,Cin,M} = 6'b0000_1_0;opA = 32'h0000_ffff;opB = 32'hff00_ff00;//all bits are 0
#10	{S,Cin,M} = 6'b0001_1_0;//nor
#10	{S,Cin,M} = 6'b0010_1_0;//notand
#10	{S,Cin,M} = 6'b0011_1_0;//notA
#10	{S,Cin,M} = 6'b0100_1_0;//andnot
#10	{S,Cin,M} = 6'b0101_1_0;//notB
#10	{S,Cin,M} = 6'b0110_1_0;//xor
#10	{S,Cin,M} = 6'b0111_1_0;//nand
#10	{S,Cin,M} = 6'b1000_1_0;//and
#10	{S,Cin,M} = 6'b1001_1_0;//xnor
#10	{S,Cin,M} = 6'b1010_1_0;//B
#10	{S,Cin,M} = 6'b1011_1_0;//notor
#10	{S,Cin,M} = 6'b1100_1_0;//A
#10	{S,Cin,M} = 6'b1101_1_0;//or not
#10	{S,Cin,M} = 6'b1110_1_0;//or
#10	{S,Cin,M} = 6'b1111_1_0;//all bits are 1

#10	{S,Cin,M} = 6'b1001_0_1;opA = 32'hffff_ffff;opB = 32'habcd_4321;//add
#10	{S,Cin,M} = 6'b0110_1_1;opA = 32'hffff_ffff;opB = 32'h0000_ffff;//sub

end                                                    
        
initial 
	$monitor($time," -- INPUT: {S,Cin,M}=%b%b%b;opA=%h,opB=%h,\t OUTPUT: DO=%h,C=%b,V=%b,N=%b,Z=%b",S,Cin,M,opA,opB,DO,C,V,N,Z);
endmodule

结果

RTL Viewer,电路综合得到的电路如下图所示:

Wave结果如下图所示:

Transcript中得到的monitor结果如下,其中测试顺序均按照分析中的表格进行。逐项分析验证,该电路正确无误,实现了32位ALU的设计。

有关Verilog设计一个32位ALU,并进行功能验证的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  7. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  8. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

随机推荐