使用Verilog描述硬件的基本設(shè)計(jì)單元是模塊(module)。構(gòu)建復(fù)雜的電子電路,主要是通過(guò)模塊的相互連接調(diào)用來(lái)實(shí)現(xiàn)的。模塊被包含在關(guān)鍵字module、endmodule之內(nèi)。實(shí)際的電路元件。Verilog中的模塊類(lèi)似C語(yǔ)言中的函數(shù),它能夠提供輸入、輸出端口,可以實(shí)例調(diào)用其他模塊,也可以被其他模塊實(shí)例調(diào)用。模塊中可以包括組合邏輯部分、過(guò)程時(shí)序部分。例如,四選一的多路選擇器,就可以用模塊進(jìn)行描述。它具有兩個(gè)位選輸入信號(hào)、四個(gè)數(shù)據(jù)輸入,一個(gè)輸出端,在Verilog中可以表示為:
module mux (out, select, in0, in1, in2, in3);output out;input [1:0] select;input in0, in1, in2, in3;//具體的寄存器傳輸級(jí)代碼endmodule
設(shè)計(jì)人員可以使用一個(gè)頂層模塊,通過(guò)實(shí)例調(diào)用上面這個(gè)模塊的方式來(lái)進(jìn)行測(cè)試。這個(gè)頂層模塊常被稱(chēng)為“測(cè)試平臺(tái)(Testbench)”。為了最大程度地對(duì)電路的邏輯進(jìn)行功能驗(yàn)證,測(cè)試代碼需要盡可能多地覆蓋系統(tǒng)所涉及的語(yǔ)句、分支、條件、路徑、觸發(fā)、狀態(tài)機(jī)狀態(tài),驗(yàn)證人員需要在測(cè)試平臺(tái)里創(chuàng)建足夠多的輸入激勵(lì),并連接到被測(cè)模塊的輸入端,然后檢測(cè)其輸出端的表現(xiàn)是否符合預(yù)期(諸如SystemVerilog的硬件驗(yàn)證語(yǔ)言能夠提供針對(duì)驗(yàn)證專(zhuān)門(mén)優(yōu)化的數(shù)據(jù)結(jié)構(gòu),以隨機(jī)測(cè)試的方式進(jìn)行驗(yàn)證,這對(duì)于高度復(fù)雜的集成電路設(shè)計(jì)驗(yàn)證可以起到關(guān)鍵作用)。實(shí)例調(diào)用模塊時(shí),需要將端口的連接情況按照這個(gè)模塊聲明時(shí)的順序排列。這個(gè)頂層模塊由于不需要再被外界調(diào)用,因此沒(méi)有輸入輸出端口:
module tester;reg [1:0] SELECT;reg IN0, IN1, IN2, IN3;wire OUT;mux my_mux (OUT, SELECT, IN0, IN1, IN2, IN3); //實(shí)例調(diào)用mux模塊,這個(gè)實(shí)例被命名為my_muxinitial //需要仿真的激勵(lì)代碼 begin endendmodule
在這個(gè)測(cè)試平臺(tái)模塊里,設(shè)計(jì)人員可以設(shè)定仿真時(shí)的輸入信號(hào)以及信號(hào)監(jiān)視程序,然后觀察仿真時(shí)的輸出情況是否符合要求,這樣就可以了解設(shè)計(jì)是否達(dá)到了預(yù)期。
示例中的對(duì)模塊進(jìn)行實(shí)例引用時(shí),按照原模塊聲明時(shí)的順序羅列了輸入變量。除此之外,還可以使用或者采用命名端口連接的方式。使用這種方式,端口的排列順序可以與原模塊聲明時(shí)不同,甚至可以不連接某些端口:
mux my_mux (.out(OUT), .select(SELECT), .in0(IN0), .in1(IN1), .in2(IN2), .in3(IN3));//使用命名端口連接,括號(hào)外面是模塊聲明時(shí)的端口,括號(hào)內(nèi)是實(shí)際的端口連接//括號(hào)外相當(dāng)于C語(yǔ)言的形式參數(shù),括號(hào)內(nèi)相當(dāng)于實(shí)際參數(shù)endmodule
上面所述的情況是,測(cè)試平臺(tái)頂層模塊的測(cè)試變量直接連接了所設(shè)計(jì)的功能模塊。測(cè)試平臺(tái)還可以是另一種形式,即測(cè)試平臺(tái)并不直接連接所設(shè)計(jì)的功能模塊,而是在這個(gè)測(cè)試平臺(tái)之下,將激勵(lì)模塊和功能模塊以相同的抽象級(jí)別,通過(guò)線網(wǎng)相互連接。這兩種形式的測(cè)試平臺(tái)都可以完成對(duì)功能模塊的測(cè)試。大型的電路系統(tǒng),正是由各個(gè)層次不同模塊之間的連接、調(diào)用,來(lái)實(shí)現(xiàn)復(fù)雜的功能的。
verilog實(shí)現(xiàn)定時(shí)器函數(shù)
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
評(píng)論
查看更多