使用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實現定時器函數
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
評論
查看更多