一、实验目的
- 掌握用always实现较大组合逻辑电路的方法;
- 进一步了解assign与always两种组合电路实现方法的区别和注意点;
- 学习测试模块中随机数的产生和应用;
- 学习综合不同层次的仿真,并比较结果。
二、实验原理
使用assign结构来实现组合逻辑电路,如果逻辑关系比较复杂,不容易理解语句的功能。而适当地采用always来设计组合逻辑,使源代码语句的功能容易理解。
下面是一个简单的指令译码电路的设计示例。该电路通过对指令的判断,对输入数据执行相应的操作,包括加、减、与、或和求反,并且无论是指令作用的数据还是指令本身发生变化,结果都要作出及时的反应。显然,这是一个较为复杂的组合逻辑电路,如果采用assign语句,表达起来非常复杂。示例中使用了电平敏感的always块,所谓电平敏感的触发条件,是指在@后的括号内电平列表中的任何一个电平发生变化(与时序逻辑不同,它在@后的括号内没有沿敏感关键词,如posedge或negedge),就能触发always块的动作,并且运用了case结构来进行分支判断,不但设计思想得到直观的体现,而且代码看起来非常整齐、便于理解。
同一组合逻辑电路分别用always块和连续赋值语句assign 描述时,代码的形式大相径庭,但是在always中,若适当运用default(在case结构中)和else(在if…else结构中)语句时,通常可以综合为纯组合逻辑,尽管被赋值的变量一定要定义为reg型;若不使用default或else对默认项进行说明,则易生成意想不到的锁存器,这点一定要加以注意。
模块源代码:
//-------------- alu.v -------------
`define plus 3'd0
`define minus 3'd1
`define band 3'd2
`define bor 3'd3
`define unegate 3'd4
module alu(out,opcode,a,b);
output [7:0] out;
reg [7:0] out;
input [2:0] opcode;
input [7:0] a,b;
always@(opcode or a or b)
begin
case(opcode)
`plus: out=a+b;
`minus: out=a-b;
`band: out=a&b;
`bor: out=a|b;
`unegate: out=~a;
default: out=8'hx;
endcase
end
endmodule
测试模块源代码:
//-------------- alutest.v --------------
`timescale 1ns/1ns
`include "./alu.v"
module alutest;
wire [7:0] out;
reg [7:0] a,b;
reg [2:0] opcode;
parameter times=5;
initial
begin
a={$random}%256;
b={$random}%256;
opcode=3'h0;
repeat(times)
begin
#100 a={$random}%256;
b={$random}%256;
opcode=opcode+1;
end
#100 $stop;
end
alu alu1(out,opcode,a,b);
endmodule
复杂组合逻辑电路的仿真波形(部分)如下所示:
三、实验要求及实验内容
(1)实验内容:
运用always块设计一个8路数据选择器。要求:每路输入数据与输出数据均为4位2进制数,当选择开关(至少3位)或输入数据发送变化时,输出数据也相应地变化。
(2)实验代码:
模块源代码:
//-------------- mux8_to_1.v --------------
`timescale 1ns/1ns
module mux8_to_1(out,opcode,in1,in2,in3,in4,in5,in6,in7,in8);
output [7:0] out;
reg [7:0] out;
input [2:0] opcode;
input [7:0] in1,in2,in3,in4,in5,in6,in7,in8;
always@(opcode or in1 or in2 or in3 or in4 or in5 or in6 or in7 or in8)
begin
case(opcode)
3'b000: out=in1;
3'b001: out=in2;
3'b010: out=in3;
3'b011: out=in4;
3'b100: out=in5;
3'b101: out=in6;
3'b110: out=in7;
3'b111: out=in8;
default: out=8'hx;
endcase
end
endmodule
测试模块源代码:
//-------------- mux8_to_1_Top.v --------------
`timescale 1ns/1ns
`include "./mux8_to_1.v"
module mux8_to_1_Top;
wire [7:0] out;
reg [7:0] in1,in2,in3,in4,in5,in6,in7,in8;
reg [2:0] opcode;
parameter times=8;
initial
begin
in1={$random}%256;
in2={$random}%256;
in3={$random}%256;
in4={$random}%256;
in5={$random}%256;
in6={$random}%256;
in7={$random}%256;
in8={$random}%256;
opcode=3'h0;
repeat(times)
begin
#100 in1={$random}%256;
in2={$random}%256;
in3={$random}%256;
in4={$random}%256;
in5={$random}%256;
in6={$random}%256;
in7={$random}%256;
in8={$random}%256;
opcode=opcode+1;
end
#100 $stop;
end
mux8_to_1 mux8to1(out,opcode,in1,in2,in3,in4,in5,in6,in7,in8);
endmodule
四、实验结果