clock_all.v
以下程式可在Quartus II 利用modelsim後模擬,且可在電路正確執行,但無法在Modelsim裡正確的前模擬,因為沒有初始值時,Modelsim無法進行運算。
- // Quartus II Verilog Template
- // Binary up/down counter
- // Main clock 50MHz.
- module clock_all(
- input clk,
- output clock_1MHz,
- output clock_100kHz,
- output clock_10kHz,
- output clock_1kHz,
- output clock_100Hz,
- output clock_10Hz,
- output clock_1Hz,
- output clock_01Hz
- );
- divider_50 clk0( .clk(clk), .clk_div50(clock_1MHz));
- divider_10 clk1( .clk(clock_1MHz), .clk_div10(clock_100kHz));
- divider_10 clk2( .clk(clock_100kHz), .clk_div10(clock_10kHz));
- divider_10 clk3( .clk(clock_10kHz), .clk_div10(clock_1kHz));
- divider_10 clk4( .clk(clock_1kHz), .clk_div10(clock_100Hz));
- divider_10 clk5( .clk(clock_100Hz), .clk_div10(clock_10Hz));
- divider_10 clk6( .clk(clock_10Hz), .clk_div10(clock_1Hz));
- divider_10 clk7( .clk(clock_1Hz), .clk_div10(clock_01Hz));
- endmodule
- //=========================================
- module divider_10(
- input clk,
- output reg clk_div10,
- output reg [3:0] count_10
- );
- always @ (posedge clk)
- begin
- if (count_10==4)
- begin
- count_10 <= 0;
- clk_div10<=~clk_div10;
- end
- else
- count_10 <= count_10 + 1;
- end
- endmodule
- //=========================================
- module divider_50(
- input clk,
- output reg clk_div50,
- output reg [4:0] count_50
- );
- always @ (posedge clk)
- begin
- if (count_50==24)
- begin
- count_50 <= 0;
- clk_div50<=~clk_div50;
- end
- else
- count_50 <= count_50 + 1;
- end
- endmodule
在Quartus II模擬的test bench 如下:
clock_all_tb.v
- `timescale 1ns/1ns
- module clock_all_tb;
- reg clk;
- wire clock_1MHz;
- wire clock_100kHz;
- clock_all u(
- .clk(clk),
- .clock_1MHz(clock_1MHz),
- .clock_100kHz(clock_100kHz)
- );
- initial
- begin
- #0
- clk = 0;
- end
- always
- #10 clk = ~clk;
- endmodule
當直接使用Modelsim作前模擬時,所有的wire或reg宣告都需要有初始值,需要利用reset使訊號歸零。程式改為
clock_all.v
- // Quartus II Verilog Template
- // Binary up/down counter
- // Main clock 50MHz.
- module clock_all(
- input clk,
- input rst,
- output clock_1MHz,
- output clock_100kHz,
- output clock_10kHz,
- output clock_1kHz,
- output clock_100Hz,
- output clock_10Hz,
- output clock_1Hz,
- output clock_01Hz,
- output [4:0] count_50
- );
- divider_50 clk0( .clk(clk), .rst(rst), .clk_div50(clock_1MHz), .count_50(count_50));
- divider_10 clk1( .clk(clock_1MHz), .rst(rst), .clk_div10(clock_100kHz));
- divider_10 clk2( .clk(clock_100kHz), .rst(rst), .clk_div10(clock_10kHz));
- divider_10 clk3( .clk(clock_10kHz), .rst(rst), .clk_div10(clock_1kHz));
- divider_10 clk4( .clk(clock_1kHz), .rst(rst), .clk_div10(clock_100Hz));
- divider_10 clk5( .clk(clock_100Hz), .rst(rst), .clk_div10(clock_10Hz));
- divider_10 clk6( .clk(clock_10Hz), .rst(rst), .clk_div10(clock_1Hz));
- divider_10 clk7( .clk(clock_1Hz), .rst(rst), .clk_div10(clock_01Hz));
- endmodule
- //=========================================
- module divider_10(
- input clk,
- input rst,
- output reg clk_div10,
- output reg [3:0] count_10
- );
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- count_10 <= 0;
- clk_div10<= 0;
- end
- else if (count_10==4)
- begin
- count_10 <= 0;
- clk_div10<=~clk_div10;
- end
- else
- count_10 <= count_10 + 1;
- end
- endmodule
- //=========================================
- module divider_50(
- input clk,
- input rst,
- output reg clk_div50,
- output reg [4:0] count_50
- );
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- count_50 <= 0;
- clk_div50<= 0;
- end
- else if (count_50==24)
- begin
- count_50 <= 0;
- clk_div50<=~clk_div50;
- end
- else
- count_50 <= count_50 + 1;
- end
- endmodule
test bench 的程式檔如下
clock_all_tb.v
- `timescale 1ns/1ns
- module clock_all_tb;
- reg rst;
- reg clk;
- wire clock_1MHz;
- wire clock_100kHz;
- clock_all u(
- .clk(clk),
- .rst(rst),
- .clock_1MHz(clock_1MHz),
- .clock_100kHz(clock_100kHz)
- );
- initial
- begin
- #0
- clk = 0;
- rst = 0;
- #30 rst = 1;
- end
- always
- #10 clk = ~clk;
- endmodule
clock_all.v
- // Quartus II Verilog Template
- // Binary up/down counter
- // Main clock 50MHz.
- module clock_all(
- input clk,
- input rst,
- output clock_10MHz,
- output clock_1MHz,
- output clock_100kHz,
- output clock_10kHz,
- output clock_1kHz,
- output clock_100Hz,
- output clock_10Hz,
- output clock_1Hz,
- output clock_01Hz,
- output [4:0] count_50
- );
- divider_5 clk0( .clk(clk), .rst(rst), .clk_div5(clock_10MHz));
- divider_10 clk1( .clk(clock_10MHz), .rst(rst), .clk_div10(clock_1MHz));
- divider_10 clk2( .clk(clock_1MHz), .rst(rst), .clk_div10(clock_100kHz));
- divider_10 clk3( .clk(clock_100kHz), .rst(rst), .clk_div10(clock_10kHz));
- divider_10 clk4( .clk(clock_10kHz), .rst(rst), .clk_div10(clock_1kHz));
- divider_10 clk5( .clk(clock_1kHz), .rst(rst), .clk_div10(clock_100Hz));
- divider_10 clk6( .clk(clock_100Hz), .rst(rst), .clk_div10(clock_10Hz));
- divider_10 clk7( .clk(clock_10Hz), .rst(rst), .clk_div10(clock_1Hz));
- divider_10 clk8( .clk(clock_1Hz), .rst(rst), .clk_div10(clock_01Hz));
- endmodule
- //=========================================
- module divider_10(
- input clk,
- input rst,
- output reg clk_div10,
- output reg [3:0] count_10
- );
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- count_10 <= 0;
- clk_div10<= 0;
- end
- else if (count_10==4)
- begin
- count_10 <= 0;
- clk_div10<=~clk_div10;
- end
- else
- count_10 <= count_10 + 1;
- end
- endmodule
- //=========================================
- module divider_5(
- input clk,
- input rst,
- output clk_div5
- );
- reg clk_div5p, clk_div5n;
- reg [2:0] count_5p, count_5n;
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- count_5p <= 0;
- end
- else if (count_5p==4)
- begin
- count_5p <= 0;
- end
- else
- begin
- count_5p <= count_5p + 1;
- end
- end
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- clk_div5p<= 0;
- end
- else if (count_5p<=1)
- begin
- clk_div5p<=1'b1;
- end
- else
- begin
- clk_div5p<=1'b0;
- end
- end
- always @ (posedge clk or negedge rst)
- begin
- if (!rst)
- begin
- count_5n <= 0;
- end
- else if (count_5n==4)
- begin
- count_5n <= 0;
- end
- else
- begin
- count_5n <= count_5n + 1;
- end
- end
- always @ (negedge clk or negedge rst)
- begin
- if (!rst)
- begin
- clk_div5n<= 0;
- end
- else if (count_5n<=1)
- begin
- clk_div5n<=1'b1;
- end
- else
- begin
- clk_div5n<=1'b0;
- end
- end
- assign clk_div5 = clk_div5p | clk_div5n;
- endmodule
測試用的test bench
clock_all_tb.v
- `timescale 1ns/1ns
- module clock_all_tb;
- reg rst;
- reg clk;
- wire clock_10MHz;
- wire clock_1MHz;
- wire clock_100kHz;
- clock_all u(
- .clk(clk),
- .rst(rst),
- .clock_10MHz(clock_10MHz),
- .clock_1MHz(clock_1MHz),
- .clock_100kHz(clock_100kHz)
- );
- initial
- begin
- #0
- clk = 0;
- rst = 0;
- #100 rst = 1;
- end
- always
- #10 clk = ~clk;
- endmodule
其中,module divider_5係用來將時脈除5,其工作原理係分別使用輸入時脈clk的正、負邊緣觸發。正邊緣觸發clk_div5p在第0及第1兩個完整週期輸出為高準位,負邊緣觸發clk_div5n在第0.5至第2.5兩個週期間輸出為高準位,最後再取or運算,得到2.5週期的高準位。
沒有留言:
張貼留言