编程语言及工具
使用Verilog描述硬件的基本设计单元是模块(module)。构建复杂的电子电路,主要是通过模块的相互连接调用来实现的。模块被包含在关键字module、endmodule之内。实际的电路元件。Verilog中的模块类似C语言中的函数,它能够提供输入、输出端口,可以实例调用其他模块,也可以被其他模块实例调用。模块中可以包括组合逻辑部分、过程时序部分。例如,四选一的多路选择器,就可以用模块进行描述。它具有两个位选输入信号、四个数据输入,一个输出端,在Verilog中可以表示为:
module mux (out, select, in0, in1, in2, in3);output out;input [1:0] select;input in0, in1, in2, in3;//具体的寄存器传输级代码endmodule
设计人员可以使用一个顶层模块,通过实例调用上面这个模块的方式来进行测试。这个顶层模块常被称为“测试平台(Testbench)”。为了最大程度地对电路的逻辑进行功能验证,测试代码需要尽可能多地覆盖系统所涉及的语句、分支、条件、路径、触发、状态机状态,验证人员需要在测试平台里创建足够多的输入激励,并连接到被测模块的输入端,然后检测其输出端的表现是否符合预期(诸如SystemVerilog的硬件验证语言能够提供针对验证专门优化的数据结构,以随机测试的方式进行验证,这对于高度复杂的集成电路设计验证可以起到关键作用)。实例调用模块时,需要将端口的连接情况按照这个模块声明时的顺序排列。这个顶层模块由于不需要再被外界调用,因此没有输入输出端口:
module tester;reg [1:0] SELECT;reg IN0, IN1, IN2, IN3;wire OUT;mux my_mux (OUT, SELECT, IN0, IN1, IN2, IN3); //实例调用mux模块,这个实例被命名为my_muxinitial //需要仿真的激励代码 begin endendmodule
在这个测试平台模块里,设计人员可以设定仿真时的输入信号以及信号监视程序,然后观察仿真时的输出情况是否符合要求,这样就可以了解设计是否达到了预期。
示例中的对模块进行实例引用时,按照原模块声明时的顺序罗列了输入变量。除此之外,还可以使用或者采用命名端口连接的方式。使用这种方式,端口的排列顺序可以与原模块声明时不同,甚至可以不连接某些端口:
mux my_mux (.out(OUT), .select(SELECT), .in0(IN0), .in1(IN1), .in2(IN2), .in3(IN3));//使用命名端口连接,括号外面是模块声明时的端口,括号内是实际的端口连接//括号外相当于C语言的形式参数,括号内相当于实际参数endmodule
上面所述的情况是,测试平台顶层模块的测试变量直接连接了所设计的功能模块。测试平台还可以是另一种形式,即测试平台并不直接连接所设计的功能模块,而是在这个测试平台之下,将激励模块和功能模块以相同的抽象级别,通过线网相互连接。这两种形式的测试平台都可以完成对功能模块的测试。大型的电路系统,正是由各个层次不同模块之间的连接、调用,来实现复杂的功能的。
Verilog代码
module alarm_block (
input wire rst,
clk,
hrs,
mins,
alarm,
output wire [4:0] alarm_hr,
output wire [5:0] alarm_min
);
wire hour_s, min_s;
alarm_counter counter1 ( rst, hour_s, min_s, clk, alarm_hr, alarm_min );
state_machine alarm_state ( rst, alarm, hrs, mins, clk, hour_s, min_s );
endmodule
module state_machine (
input wire rst,
alarm,
hrs,
mins,
clk,
output reg hrs_out,
mins_out
);
parameter IDLE = 2‘b00,
SET_HRS = 2’b01,
SET_MINS = 2‘b11;
reg[1:0] state, next;
always@( posedge clk or posedge rst )
if( rst )
state 《= IDLE;
else state 《= next;
always@( alarm or hrs or mins or state )
case( state )
IDLE :
if( !alarm ) begin
next = IDLE;
hrs_out = 0;
mins_out = 0;
end else if ( alarm & hrs & !mins ) begin
next = SET_HRS;
hrs_out = 1;
mins_out = 0;
end
else if( alarm & !hrs & mins ) begin
next = SET_MINS;
hrs_out = 0;
mins_out = 1;
end SET_HRS : begin
if( alarm & hrs & !mins ) begin
next = SET_HRS;
hrs_out = 1;
end else begin next = IDLE;
hrs_out = 0;
end
mins_out = 0;
end
SET_MINS : begin
if( alarm & !hrs & mins ) begin
next = SET_MINS;
mins_out = 1;
end
else begin
next = IDLE;
mins_out = 0;
end
hrs_out = 0;
end
default : begin
next = 2‘bx;
hrs_out = 1’bx;
mins_out = 1‘bx;
end
endcase
endmodule
module alarm_counter (
input wire rst,
hr_set,
min_set,
clk,
output reg [4:0] hrs,
output reg [5:0] mins
);
//set alarm minutes
always@ ( posedge clk or posedge rst )
if( rst )
mins 《= 0;
else if( min_set & !hr_set )
if( mins == 6‘b111011 )
mins 《= 6’b0;
else
mins 《= mins + 6‘b000001;
//set alarm hours
always@ ( posedge clk or posedge rst )
if( rst )
hrs 《= 0;
else if( hr_set & !min_set)
if ( hrs == 5’b10111 )
hrs 《= 5‘b0;
else
hrs 《= hrs + 5’b00001;
endmodule
module Alarm_sm_2 (
input wire rst,
clk,
compare_in,
toggle_on,
output reg ring
);
parameter IDLE = 1‘b0,
ACTI = 1’b1;
reg state, next;
always@ ( posedge clk or posedge rst )
if ( rst )
state 《= IDLE;
else
state 《= next;
always@ ( state or compare_in or toggle_on )
case ( state )
IDLE :
if( toggle_on & compare_in ) begin
next 《= ACTI;
ring 《= 1;
end
else begin
next 《= IDLE;
ring 《= 0;
end
ACTI :
if( toggle_on ) begin
next 《= ACTI;
ring 《= 1;
end
else begin
next 《= IDLE;
ring 《= 0;
end
default : begin
next 《= 1‘bx;
ring 《= 1’bx;
end
endcase
endmodule
module comparator (
input wire [4:0] alarm_hr,
time_hr,
input wire [5:0] alarm_min,
time_min,
output reg compare_out );
always@ ( * )
if( ( alarm_hr == time_hr ) && ( alarm_min == time_min ) )
compare_out = 1;
else compare_out = 0;
endmodulemodule convertor_ckt (
input [4:0]hour,
input [5:0]min,
output [13:0]disp1, disp2
);
wire [13:0] disp1_0;
segment_decoder segment_decoder_hr ( {1‘b0, hour}, disp1_0 );
segment_decoder segment_decoder_min ( min , disp2 );
Hours_filter filter ( disp1_0, disp1 );
endmodule
module segment_decoder (
input wire [5:0] num,
output reg [13:0] disp
);
always@ ( num )
case ( num )
6’b000000 : disp = 14‘b0111111_0111111;
6’b000001 : disp = 14‘b0111111_0000110;
6’b000010 : disp = 14‘b0111111_1011011;
6’b000011 : disp = 14‘b0111111_1001111;
6’b000100 : disp = 14‘b0111111_1100110;
6’b000101 : disp = 14‘b0111111_1101101;
6’b000110 : disp = 14‘b0111111_1111101;
6’b000111 : disp = 14‘b0111111_0000111;
6’b001000 : disp = 14‘b0111111_1111111;
6’b001001 : disp = 14‘b0111111_1101111;
6’b001010 : disp = 14‘b0000110_0111111;
6’b001011 : disp = 14‘b0000110_0000110;
6’b001100 : disp = 14‘b0000110_1011011;
6’b001101 : disp = 14‘b0000110_1001111;
6’b001110 : disp = 14‘b0000110_1100110;
6’b001111 : disp = 14‘b0000110_1101101;
6’b010000 : disp = 14‘b0000110_1111101;
6’b010001 : disp = 14‘b0000110_0000111;
6’b010010 : disp = 14‘b0000110_1111111;
6’b010011 : disp = 14‘b0000110_1101111;
6’b010100 : disp = 14‘b1011011_0111111;
6’b010101 : disp = 14‘b1011011_0000110;
6‘b010110 : disp = 14’b1011011_1011011;
6‘b010111 : disp = 14’b1011011_1001111;
6‘b011000 : disp = 14’b1011011_1100110;
6‘b011001 : disp = 14’b1011011_1101101;
6‘b011010 : disp = 14’b1011011_1111101;
6‘b011011 : disp = 14’b1011011_0000111;
6‘b011100 : disp = 14’b1011011_1111111;
6‘b011101 : disp = 14’b1011011_1101111;
6‘b011110 : disp = 14’b1001111_0111111;
6‘b011111 : disp = 14’b1001111_0000110;
6‘b100000 : disp = 14’b1001111_1011011;
6‘b100001 : disp = 14’b1001111_1001111;
6‘b100010 : disp = 14’b1001111_1100110;
6‘b100011 : disp = 14’b1001111_1101101;
6‘b100100 : disp = 14’b1001111_1111101;
6‘b100101 : disp = 14’b1001111_0000111;
6‘b100110 : disp = 14’b1001111_1111111;
6‘b100111 : disp = 14’b1001111_1101111;
6‘b101000 : disp = 14’b1100110_0111111;
6‘b101001 : disp = 14’b1100110_0000110;
6‘b101010 : disp = 14’b1100110_1011011;
6‘b101011 : disp = 14’b1100110_1001111;
6‘b101100 : disp = 14’b1100110_1100110;
6‘b101101 : disp = 14’b1100110_1101101;
6‘b101110 : disp = 14’b1100110_1111101;
6‘b101111 : disp = 14’b1100110_0000111;
6‘b110000 : disp = 14’b1100110_1111111;
6‘b110001 : disp = 14’b1100110_1101111;
6‘b110010 : disp = 14’b1101101_0111111;
6‘b110011 : disp = 14’b1101101_0000110;
6‘b110100 : disp = 14’b1101101_1011011;
6‘b110101 : disp = 14’b1101101_1001111;
6‘b110110 : disp = 14’b1101101_1100110;
6‘b110111 : disp = 14’b1101101_1101101;
6‘b111000 : disp = 14’b1101101_1111101;
6‘b111001 : disp = 14’b1101101_0000111;
6‘b111010 : disp = 14’b1101101_1111111;
6‘b111011 : disp = 14’b1101101_1101111;
default : disp = 14‘bx;
endcase
endmodule
module Hours_filter (
input wire [13:0] num,
output reg [13:0] num_disp
);
always@ ( * )
if ( num[13:7] == 7‘b011_1111 )
num_disp = { 7’b0, num[6:0] };
else
num_disp = num;
endmodule
module Mux (
input wire alarm,
mode,
input wire [4:0]alarm_hr,
time_hr,
input wire [5:0]alarm_min,
time_min,
output reg [1:0]am_pm_display,
output reg [4:0]hours,
output reg [5:0]minutes
);
always@( * ) begin
//output hours and minutes
hours = alarm ? alarm_hr : time_hr
minutes = alarm ? alarm_min : time_min;
//12hours system or 24hours system and set am_pm_display
if ( mode )
case ( hours )
0 : begin am_pm_display = 2‘b10; hours = 5’b01100; end
1 : am_pm_display = 2‘b10;
2 : am_pm_display = 2’b10;
3 : am_pm_display = 2‘b10;
4 : am_pm_display = 2’b10;
5 : am_pm_display = 2‘b10;
6 : am_pm_display = 2’b10;
7 : am_pm_display = 2‘b10;
8 : am_pm_display = 2’b10;
9 : am_pm_display = 2‘b10;
10: am_pm_display = 2’b10;
11: am_pm_display = 2‘b10;
12: am_pm_display = 2’b01;
13: begin am_pm_display = 2‘b01; hours = 5’b00001 end
14: begin am_pm_display = 2‘b01; hours = 5’b00010 end
15: begin am_pm_display = 2‘b01; hours = 5’b00011 end
16: begin am_pm_display = 2‘b01; hours = 5’b00100 end
17: begin am_pm_display = 2‘b01; hours = 5’b00101 end
18: begin am_pm_display = 2‘b01; hours = 5’b00110 end
19: begin am_pm_display = 2‘b01; hours = 5’b00111 end
20: begin am_pm_display = 2‘b01; hours = 5’b01000 end
21: begin am_pm_display = 2‘b01; hours = 5’b01001 end
22: begin am_pm_display = 2‘b01; hours = 5’b01010 end
23: begin am_pm_display = 2‘b01; hours = 5’b01011 end
default: begin am_pm_display = 2‘bx; hours = 5’bx; end
endcase
else
am_pm_display = 2‘b00;
end
endmodule
module time_block (
input wire rst,
clk,
hrs,
mins,
set_time,
output wire [4:0] time_hr,
output wire [5:0] time_min,
time_sec
);
wire hour_s, min_s;
time_counter counter2 ( rst, hour_s, min_s, clk, time_hr, time_min, time_sec );
state_machine time_state ( rst, set_time, hrs, mins, clk, hour_s, min_s );
endmodule
module time_counter (
input wire rst,
hr_set,
min_set,
clk,
output reg [4:0] hrs,
output reg [5:0] mins,
secs
);
always@ ( posedge clk or posedge rst )
if( rst )
secs 《= 0;
else if( secs == 6‘b111011 )
secs 《= 6’b0;
else
secs 《= secs + 6‘b000001;
always@ ( posedge clk or posedge rst )
if( rst )
mins 《= 0;
else if( (min_set & !hr_set) || (!hr_set & !min_set & (secs == 6’b111011)) )
if( mins == 6‘b111011 )
mins 《= 6’b0;
else mins 《= mins + 6‘b000001;
always@ ( posedge clk or posedge rst )
if( rst )
hrs 《= 0;
else if( (hr_set & !min_set) ||(!hr_set & !min_set & (secs == 6’b111011) & (mins == 6‘b111011)) )
if( hrs == 5’b10111 )
hrs 《= 5‘b0;
else
hrs 《= hrs + 5’b00001;
endmodule
module timer (
input wire rst,
clk,
alarm,
set_time,
hrs,
mins,
toggle_switch,
mode,
output wire speaker_out,
output wire [1:0]am_pm_display,
output wire [13:0] disp1,
disp2
);
wire [5:0] time_min, time_sec, alarm_min, min;
wire [4:0] time_hr, alarm_hr, hour;
wire compare;
time_block time_mod ( rst, clk, hrs, mins, set_time, time_hr, time_min, time_sec );
alarm_block alarm_mod ( rst, clk, hrs, mins, alarm, alarm_hr, alarm_min );
comparator comparator_mod ( alarm_hr, time_hr, alarm_min, time_min, compare );
Alarm_sm_2 bell_mod ( rst, clk, compare, toggle_switch, speaker_out );
Mux mux_mod ( alarm, mode, alarm_hr, time_hr, alarm_min, time_min, am_pm_display, hour, min );
convertor_ckt convertor_mod ( hour, min, disp1, disp2 );
endmodule
module top;
reg rst, clk, alarm, set_time, hrs, mins, toggle_switch, mode;
wire [1:0] am_pm_display;
wire speaker_out;
wire [13:0] disp1, disp2;
timer electronic_watch( rst, clk, alarm, set_time, hrs, mins, toggle_switch, mode, speaker_out, am_pm_display, disp1, disp2 );
always begin
clk = 0;
#10 clk = 1;
#10;
end
initial begin
$monitor($time,,,,“disp1=%b disp2=%b am_pm_display=%b speaker_out=%b”, disp1, disp2, am_pm_display, speaker_out );
rst = 0;
alarm = 0;
set_time = 0;
hrs = 0;
mins = 0;
toggle_switch = 0;
mode = 0;
#5 rst = 1;
//reset #4 rst = 0;
#3000 mode = 1;//12hours system display
#3000 mode = 0;//24hours system display
#1200 alarm = 1; mins = 1;//set alarm minutes
#200 mins = 0; toggle_switch = 1;//switch on
#100 alarm = 0;
#10000 toggle_switch = 0;//switch off
#10000 set_time = 1; hrs = 1;//set hours
#40 hrs = 0; #20 mins = 1;//set minutes
#200 set_time = 0; mins =0;
#40 alarm = 1; hrs = 1;//set alarm hours
#40 hrs = 0; #20 mins = 1;//set alarm minutes
#800 mins = 0; toggle_switch = 1;
#300 alarm = 0;
#24000 set_time = 1; hrs = 1;toggle_switch = 0;//set hours
#240 set_time = 0; hrs = 0;
#40 mode = 1; //12hours system display
end
endmodule
全部0条评论
快来发表一下你的评论吧 !