Quartus模拟仿真实现简单的CPU逻辑运算单元

本文介绍了如何使用Verilog语言实现数字电路中的高阻态和四运算逻辑单元。通过行为建模和结构化建模,详细展示了如何设计一个能够进行加、减、与、或、异或运算的逻辑单元,并提供了仿真波形图验证了设计的正确性。代码中包含了使能信号控制的高阻态输出和异常情况处理。
摘要由CSDN通过智能技术生成

题目要求:

看到题目,很多小伙伴可能不知道高阻态是个啥玩意咧(尤其是我们计院这些不懂硬件的学生),这里普及一下高阻态的概念:

高阻态是数字电路三态门中输出状态的一种,它的输出既不是高电平也不是低电平,相当于浮空状态。如果高阻态再输入下一级电路的话,对下级电路无任何影响,等同于没接入上级电路。如果用万用表测的话,有可能是高电平也有可能是低电平。

在verilog中,高阻态用z表示,比如4位寄存器,如果想使其每一位输出无效(即高阻态),则赋值语句是: v = 4'bzzz

其余的功能就非常好实现了,这里采用行为建模的方式,类似于C语言的算法,便于各位计院大佬理解;且代码简洁,干净利落!

代码如下:

module Unidad_Logica_de_Algoritmo(op0, op1, s, oe, clk, r);
	input clk, oe; // OE是使能信号,低电平有效
	input[3:0] op0; // 第一个操作数
	input[3:0] op1; // 第二个操作数
	input[2:0] s; // 选择开关,不同的值(具体见题目描述)进行不同的运算
	output[3:0] r; // 输出值
	
	reg[3:0] r; // 因为r在always代码块中被赋值,所以需要定义为寄存器类型
	
	always @(posedge clk) // D触发器上升沿触发
	begin
		if(oe == 1'b1)
		begin
			r = 4'bzzzz; // 输出高阻态
		end
		else
		begin
			if(s == 3'b000) // PLUS
			begin
				r <= op0 + op1;
			end
			else if(s == 3'b001) // MINUS
			begin
				r <= op0 - op1;
			end
			else if(s == 3'b100) // AND
			begin
				r <= op0 & op1;
			end
			else if(s == 3'b101) // OR
			begin
				r <= op0 | op1;
			end
			else if(s == 3'b110) // XOR
			begin
				r <= op0 ^ op1;
			end
		end
	end
endmodule

波形图模拟仿真如下:

1. 高阻态情况:

 2. 异或:

3. 按位或:

4. 按位与:

 

5. 加法和减法:

 

2022.08.15更新:

根据逻辑函数表达式推导,我设计了一种结构与行为混合建模的方式。

这里采用带进位的四位全加器,其每一位的运算结果位和进位位通过列真值表
和画卡诺图化简的方式,推导出逻辑递推表达式,然后将它们存入各自的寄存器中,舍
弃掉最后的进位值,只保留四位寄存器中的加减运算结果,并将第一位进位初值设为 0,
表示之前没有进位。

根据第二章的分析,此处应采用带加法/减法切换功能的 4 位全加器实现。首先定义
进位位 𝐶𝑖(0 ≤ 𝑖 ≤ 3) 和最后输出的进位值 𝐶out,再根据 Select 值判断是进行加法运算
还是进行减法运算,最后根据 3.1 小节所述的输入数 op0, op1 和输出运算数 r 来展示运
算结果。Select = 0 时,r 为全加器的求和位,即 r=op0+op1,𝐶out为全加器的高位进位,
𝐶𝑖为全加器低位进位;Select = 1 时,r 为全减器的求差位,即 r=op0-op1,𝐶out为全减器
的高位借位,𝐶𝑖为全减器低位借位。
分析上述定义和功能,对于一位全加器,不难推导出如下表所示的真值表:

根据卡诺图化简,对一位全加/全减运算,可以推导出如下的逻辑表达式:

 

推广到四位全加/全减器,逻辑表达式修改为:

 

根据上述推导,得出如下代码(顺便吐槽一句,csdn代码高亮不支持verilog是真恶心):

module Unidad_Logica_de_Algoritmo(
	input clk, oe, // OE代表使能位
	input[3:0] op0, // 操作数1
	input[3:0] op1, // 操作数2
	input[2:0] s, // 功能选择
	output reg [3:0] r // 运算结果,因需要在D触发器中赋值所以注意标记为寄存器类型
);

	wire cin; // 运算前的初始进位
	reg cfinal; // 运算后的最高位进位
	reg[3:1] c; // 第1~3位运算的进位
	assign cin = 0;
	always @(posedge clk) // 上升沿触发
	begin
		if(oe)
		begin
			r = 4'bzzzz; // 输出高阻态
		end
		else
		begin
			case(s)
				3'b100: r = op0 & op1;
				3'b101: r = op0 | op1;
				3'b110: r = op0 ^ op1;
				default:
				begin
					if(s[2] == 0 && s[1] == 0)
					begin // s[0]为0时进行4位全加,为1时进行4位全减
						// bit 0
						r[0] = ((op0[0]^s[0]) ^ op1[0] ^ cin) ^ s[0];
						c[1] = ((op0[0]^s[0]) & op1[0]) | ((op0[0]^s[0]) | op1[0])&cin;
						// bit 1
						r[1] = ((op0[1]^s[0]) ^ op1[1] ^ c[1]) ^ s[0];
						c[2] = ((op0[1]^s[0]) & op1[1]) | ((op0[1]^s[0]) | op1[1])&c[1];
						// bit 2
						r[2] = ((op0[2]^s[0]) ^ op1[2] ^ c[2]) ^ s[0];
						c[3] = ((op0[2]^s[0]) & op1[2]) | ((op0[2]^s[0]) | op1[2])&c[2];
						// bit 3
						r[3] = ((op0[3]^s[0]) ^ op1[3] ^ c[3]) ^ s[0];
						cfinal = ((op0[3]^s[0]) & op1[3]) | ((op0[3]^s[0]) | op1[2])&c[3];
					end
					else // 处理s不为题目中要求值的异常情况 (i.e. 111, 010, 011, etc.),使 r[3:0] 输出无效
					begin
						r = 4'bzzzz;
					end
				end
			endcase
		end
	end
	
endmodule

综合出的电路如下:

仿真波形图如下:

 

由题意可知,第一个 80ns 周期内,s=3’b000,应进行算术加法运算,1011+0011=1110,
在 40ns 上升沿出现时结果从 zzzz 跳变到 1110,符合预期;
第二个 80ns 周期内,s=3’b001,应进行算术减法运算,1011-0011=1100,在 120ns 时
结果跳变到 1000,符合预期;
第三个 80ns 周期内,s=3’b100,应进行逻辑与运算,1011&0011=0011,在 200ns 时
结果跳变到 0011,符合预期;
第四个 80ns 周期内,s=3’b101,应进行逻辑或运算,1011|0011=1011,在 280ns 时
结果跳变到 1011,符合预期;
第五个 80ns 周期内,s=3’b110,应进行逻辑异或运算,1011^0011=1000,在 360ns
时结果跳变到 1000,符合预期;
第六个 80ns 周期内,s=3’b000,应进行算术减法运算,但在这个周期的开始时期,
OE 电平突然被拉高,输出应该无效,观察波形图发现在 440ns 时结果跳变到 zzzz,符
合预期。 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值