2017年11月14日 星期二

暫停與啟動按鍵分開

always@(posedge clk_L ) 
begin

if (reset)
begin
count <= 0;
pause_flag <= 0;
end
else if (pause_flag)
begin
if (!start_pre && start)
begin
count <= count+1;
pause_flag <= 0;
end
end
else if (!pause_pre && pause)
begin
count <= count;
pause_flag <= 1;
end
else
count <= count+1;

pause_pre <= pause;
start_pre <= start;
end

2017年11月8日 星期三

流水燈


//=======================================================
//  This code is generated by Terasic System Builder
//=======================================================

module button_game2(

//////////// CLOCK //////////
CLOCK_50,
CLOCK2_50,
CLOCK3_50,

//////////// LED //////////
LEDG,
LEDR,

//////////// KEY //////////
KEY,

//////////// SW //////////
SW,

//////////// SEG7 //////////
HEX0,
HEX1,
HEX2,
HEX3,
HEX4,
HEX5,
HEX6,
HEX7
);

//=======================================================
//  PARAMETER declarations
//=======================================================


//=======================================================
//  PORT declarations
//=======================================================

//////////// CLOCK //////////
input           CLOCK_50;
input           CLOCK2_50;
input           CLOCK3_50;

//////////// LED //////////
output      [8:0] LEDG;
output     [17:0] LEDR;

//////////// KEY //////////
input      [3:0] KEY;

//////////// SW //////////
input     [17:0] SW;

//////////// SEG7 //////////
output      [6:0] HEX0;
output      [6:0] HEX1;
output      [6:0] HEX2;
output      [6:0] HEX3;
output      [6:0] HEX4;
output      [6:0] HEX5;
output      [6:0] HEX6;
output      [6:0] HEX7;


//=======================================================
//  REG/WIRE declarations
//=======================================================

wire [7:0] score;
wire [7:0] death;
wire [3:0] count_1kHz, count_100Hz, count_10Hz, count_1Hz;
wire clock_1Hz, clock_10Hz, clock_100Hz, clock_1kHz, clock_10kHz;

wire b10, b06, b03, b01;

//=======================================================
//  Structural coding
//=======================================================


clock_all ck( .clk(CLOCK_50), .clock_10kHz(clock_10kHz), .clock_1kHz(clock_1kHz), .clock_100Hz(clock_100Hz), .clock_10Hz(clock_10Hz), .clock_1Hz(clock_1Hz));



// divider_10 div( .clk(~KEY[1]), .reset(~KEY[0]), .clk_div10(LEDR[0]), .count_10(count_1Hz) );
SEG7_LUT_8 seg( .oSEG0(HEX0),.oSEG1(HEX1),.oSEG2(HEX2),.oSEG3(HEX3),
.oSEG4(HEX4),.oSEG5(HEX5),.oSEG6(HEX6),.oSEG7(HEX7),
.iDIG( score) );

//PWM p0( .clk(clock_10kHz),   .duty(100), .pwm(b10));
//PWM p1( .clk(clock_10kHz),   .duty( 75), .pwm(b06));
//PWM p2( .clk(clock_10kHz),   .duty( 50), .pwm(b03));
//PWM p3( .clk(clock_10kHz),   .duty( 25), .pwm(b01));



// assign LEDR[17:0] = { b03, b01, 1'b0,b01, b03, b06, b10, b06, b03, b01, 1'b0, b01, b03, b06, b10, b06, b03, b01};

 LEDR_wave L0( .clk_L(clock_10Hz), .clk_H(clock_10kHz), .LEDR( LEDR), .count(score));


//assign LEDR[17] = clock_1Hz;
//assign LEDR[16] = clock_10Hz;

//shrew us( .clk(clock_1Hz), .reset(~SW[0]), .key(KEY), .show_shrew({LEDG[6], LEDG[4], LEDG[2], LEDG[0]}), .score(score), .death(LEDR) );

endmodule

module LEDR_wave(clk_L, clk_H, LEDR, count);

input clk_L, clk_H;
output  reg [17:0] LEDR;

output reg [2:0] count;

wire b10, b06, b03, b01;


PWM p0( .clk(clk_H),   .duty(100), .pwm(b10));
PWM p1( .clk(clk_H),   .duty( 50), .pwm(b06));
PWM p2( .clk(clk_H),   .duty( 20), .pwm(b03));
PWM p3( .clk(clk_H),   .duty( 05), .pwm(b01));



always@(posedge clk_L ) 
begin
count <= count+1;
end


always @(count)
begin
case(count)

3'h00: LEDR[17:0] = { b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06};
3'h01: LEDR[17:0] = { b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06, b10};
3'h02: LEDR[17:0] = { b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06, b10, b06};
3'h03: LEDR[17:0] = { b01,1'b0,1'b0,1'b0,1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06 ,b10, b06, b03};
3'h04: LEDR[17:0] = {1'b0,1'b0,1'b0,1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06 ,b10, b06, b03, b01};
3'h05: LEDR[17:0] = {1'b0,1'b0,1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06 ,b10, b06, b03, b01,1'b0};
3'h06: LEDR[17:0] = {1'b0,1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06 ,b10, b06, b03, b01,1'b0,1'b0};
3'h07: LEDR[17:0] = {1'b0, b10, b06, b03, b01,1'b0,1'b0,1'b0,1'b0, b10, b06 ,b10, b06, b03, b01,1'b0,1'b0,1'b0};


endcase
end

endmodule

Verilog 時脈產生器

主程式
clock_all.v
以下程式可在Quartus II 利用modelsim後模擬,且可在電路正確執行,但無法在Modelsim裡正確的前模擬,因為沒有初始值時,Modelsim無法進行運算。
  1. // Quartus II Verilog Template
  2. // Binary up/down counter
  3. // Main clock 50MHz.

  4. module clock_all(
  5. input clk,
  6. output  clock_1MHz,
  7. output  clock_100kHz,
  8. output  clock_10kHz,
  9. output  clock_1kHz,
  10. output  clock_100Hz,
  11. output  clock_10Hz,
  12. output  clock_1Hz,
  13. output  clock_01Hz
  14. );

  15. divider_50 clk0( .clk(clk), .clk_div50(clock_1MHz));
  16. divider_10 clk1( .clk(clock_1MHz),  .clk_div10(clock_100kHz));
  17. divider_10 clk2( .clk(clock_100kHz),  .clk_div10(clock_10kHz));
  18. divider_10 clk3( .clk(clock_10kHz),  .clk_div10(clock_1kHz));
  19. divider_10 clk4( .clk(clock_1kHz),  .clk_div10(clock_100Hz));
  20. divider_10 clk5( .clk(clock_100Hz),  .clk_div10(clock_10Hz));
  21. divider_10 clk6( .clk(clock_10Hz),  .clk_div10(clock_1Hz)); 
  22. divider_10 clk7( .clk(clock_1Hz),  .clk_div10(clock_01Hz));
  23.   
  24. endmodule


  25. //=========================================

  26. module divider_10(
  27. input clk, 
  28. output reg clk_div10,
  29. output reg [3:0] count_10
  30. );

  31. always @ (posedge clk)
  32. begin
  33. if (count_10==4)
  34. begin
  35. count_10 <= 0;
  36. clk_div10<=~clk_div10;
  37. end
  38. else
  39. count_10 <= count_10 + 1;
  40. end 
  41. endmodule


  42. //=========================================

  43. module divider_50(
  44. input clk,
  45. output reg clk_div50,
  46. output reg [4:0] count_50
  47. );


  48. always @ (posedge clk)
  49. begin
  50. if (count_50==24)
  51. begin
  52. count_50 <= 0;
  53. clk_div50<=~clk_div50;
  54. end
  55. else
  56. count_50 <= count_50 + 1;
  57. end
  58. endmodule
在Quartus II模擬的test bench 如下:
clock_all_tb.v
  1. `timescale 1ns/1ns

  2. module clock_all_tb;

  3. reg clk;
  4. wire clock_1MHz;
  5. wire clock_100kHz;

  6. clock_all u(
  7. .clk(clk),
  8. .clock_1MHz(clock_1MHz),
  9. .clock_100kHz(clock_100kHz)
  10. );

  11. initial 
  12. begin
  13.   #0 
  14.   clk = 0;
  15. end 

  16. always 
  17. #10 clk = ~clk;

  18. endmodule
當直接使用Modelsim作前模擬時,所有的wire或reg宣告都需要有初始值,需要利用reset使訊號歸零。程式改為
clock_all.v
  1. // Quartus II Verilog Template
  2. // Binary up/down counter
  3. // Main clock 50MHz.

  4. module clock_all(
  5. input clk,
  6. input rst,
  7. output  clock_1MHz,
  8. output  clock_100kHz,
  9. output  clock_10kHz,
  10. output  clock_1kHz,
  11. output  clock_100Hz,
  12. output  clock_10Hz,
  13. output  clock_1Hz,
  14. output  clock_01Hz,
  15. output [4:0] count_50
  16. );

  17. divider_50 clk0( .clk(clk),          .rst(rst), .clk_div50(clock_1MHz), .count_50(count_50));
  18. divider_10 clk1( .clk(clock_1MHz),   .rst(rst), .clk_div10(clock_100kHz));
  19. divider_10 clk2( .clk(clock_100kHz), .rst(rst), .clk_div10(clock_10kHz));
  20. divider_10 clk3( .clk(clock_10kHz),  .rst(rst), .clk_div10(clock_1kHz));
  21. divider_10 clk4( .clk(clock_1kHz),   .rst(rst), .clk_div10(clock_100Hz));
  22. divider_10 clk5( .clk(clock_100Hz),  .rst(rst), .clk_div10(clock_10Hz));
  23. divider_10 clk6( .clk(clock_10Hz),   .rst(rst), .clk_div10(clock_1Hz)); 
  24. divider_10 clk7( .clk(clock_1Hz),    .rst(rst), .clk_div10(clock_01Hz));
  25. endmodule

  26. //=========================================

  27. module divider_10(
  28. input clk,
  29. input rst, 
  30. output reg clk_div10,
  31. output reg [3:0] count_10
  32. );

  33. always @ (posedge clk or negedge rst)
  34. begin
  35. if (!rst)
  36. begin
  37. count_10 <= 0;
  38. clk_div10<= 0;
  39. end
  40. else if (count_10==4)
  41. begin
  42. count_10 <= 0;
  43. clk_div10<=~clk_div10;
  44. end
  45. else
  46. count_10 <= count_10 + 1;
  47. end 
  48. endmodule


  49. //=========================================
  50. module divider_50(
  51. input clk,
  52. input rst,
  53. output reg clk_div50,
  54. output reg [4:0] count_50
  55. );

  56. always @ (posedge clk or negedge rst)
  57. begin
  58. if (!rst)
  59. begin
  60. count_50 <= 0;
  61. clk_div50<= 0;
  62. end
  63. else if (count_50==24)
  64. begin
  65. count_50 <= 0;
  66. clk_div50<=~clk_div50;
  67. end
  68. else
  69. count_50 <= count_50 + 1;
  70. end
  71. endmodule

test bench 的程式檔如下
clock_all_tb.v

  1. `timescale 1ns/1ns

  2. module clock_all_tb;

  3. reg rst;
  4. reg clk;
  5. wire clock_1MHz;
  6. wire clock_100kHz;

  7. clock_all u(
  8. .clk(clk),
  9. .rst(rst),
  10. .clock_1MHz(clock_1MHz),
  11. .clock_100kHz(clock_100kHz)
  12. );

  13. initial 
  14. begin
  15. #0 
  16. clk = 0;
  17. rst = 0;
  18. #30 rst = 1;

  19. end 

  20. always 
  21. #10 clk = ~clk;

  22. endmodule 
用此方法產生時脈,第一步係將50MHz直接除頻至1MHz,原則上係使用除偶數的除頻方法。雖然使用到10MHz時脈的機會不大,但以下設計一個除5的模組,以練習奇數的除頻器。
clock_all.v

  1. // Quartus II Verilog Template
  2. // Binary up/down counter
  3. // Main clock 50MHz.

  4. module clock_all(
  5. input clk,
  6. input rst,
  7. output  clock_10MHz,
  8. output  clock_1MHz, 
  9. output  clock_100kHz,
  10. output  clock_10kHz,
  11. output  clock_1kHz,
  12. output  clock_100Hz,
  13. output  clock_10Hz,
  14. output  clock_1Hz,
  15. output  clock_01Hz,
  16. output [4:0] count_50
  17. );
  18. divider_5  clk0( .clk(clk),          .rst(rst), .clk_div5(clock_10MHz));
  19. divider_10 clk1( .clk(clock_10MHz),  .rst(rst), .clk_div10(clock_1MHz));
  20. divider_10 clk2( .clk(clock_1MHz),   .rst(rst), .clk_div10(clock_100kHz));
  21. divider_10 clk3( .clk(clock_100kHz), .rst(rst), .clk_div10(clock_10kHz));
  22. divider_10 clk4( .clk(clock_10kHz),  .rst(rst), .clk_div10(clock_1kHz));
  23. divider_10 clk5( .clk(clock_1kHz),   .rst(rst), .clk_div10(clock_100Hz));
  24. divider_10 clk6( .clk(clock_100Hz),  .rst(rst), .clk_div10(clock_10Hz));
  25. divider_10 clk7( .clk(clock_10Hz),   .rst(rst), .clk_div10(clock_1Hz)); 
  26. divider_10 clk8( .clk(clock_1Hz),    .rst(rst), .clk_div10(clock_01Hz));
  27. endmodule

  28. //=========================================

  29. module divider_10(
  30. input clk,
  31. input rst, 
  32. output reg clk_div10,
  33. output reg [3:0] count_10
  34. );

  35. always @ (posedge clk or negedge rst)
  36. begin
  37. if (!rst)
  38. begin
  39. count_10 <= 0;
  40. clk_div10<= 0;
  41. end
  42. else if (count_10==4)
  43. begin
  44. count_10 <= 0;
  45. clk_div10<=~clk_div10;
  46. end
  47. else
  48. count_10 <= count_10 + 1;
  49. end 
  50. endmodule

  51. //=========================================

  52. module divider_5(
  53. input clk,
  54. input rst, 
  55. output  clk_div5
  56. );

  57. reg   clk_div5p, clk_div5n;
  58. reg [2:0] count_5p, count_5n;

  59. always @ (posedge clk or negedge rst)
  60. begin
  61. if (!rst)
  62. begin
  63. count_5p <= 0;
  64. end
  65. else if (count_5p==4)
  66. begin
  67. count_5p <= 0;
  68. end
  69. else
  70. begin
  71. count_5p <= count_5p + 1;
  72. end
  73. end 

  74. always @ (posedge clk or negedge rst)
  75. begin
  76. if (!rst)
  77. begin
  78. clk_div5p<= 0;
  79. end
  80. else if (count_5p<=1)
  81. begin
  82. clk_div5p<=1'b1;
  83. end
  84. else
  85. begin
  86. clk_div5p<=1'b0;
  87. end
  88. end 

  89. always @ (posedge clk or negedge rst)
  90. begin
  91. if (!rst)
  92. begin
  93. count_5n <= 0;
  94. end
  95. else if (count_5n==4)
  96. begin
  97. count_5n <= 0;
  98. end
  99. else
  100. begin
  101. count_5n <= count_5n + 1;
  102. end
  103. end 

  104. always @ (negedge clk or negedge rst)
  105. begin
  106. if (!rst)
  107. begin
  108. clk_div5n<= 0;
  109. end
  110. else if (count_5n<=1)
  111. begin
  112. clk_div5n<=1'b1;
  113. end
  114. else
  115. begin
  116. clk_div5n<=1'b0;
  117. end
  118. end 

  119. assign clk_div5 = clk_div5p | clk_div5n;

  120. endmodule 
測試用的test bench
clock_all_tb.v

  1. `timescale 1ns/1ns

  2. module clock_all_tb;

  3. reg rst;
  4. reg clk;
  5. wire clock_10MHz;
  6. wire clock_1MHz;
  7. wire clock_100kHz;

  8. clock_all u(
  9. .clk(clk),
  10. .rst(rst),
  11. .clock_10MHz(clock_10MHz),
  12. .clock_1MHz(clock_1MHz),
  13. .clock_100kHz(clock_100kHz)
  14. );

  15. initial 
  16. begin
  17. #0 
  18. clk = 0;
  19. rst = 0;
  20. #100 rst = 1;

  21. end 

  22. always 
  23. #10 clk = ~clk;

  24. endmodule 
其中,module divider_5係用來將時脈除5,其工作原理係分別使用輸入時脈clk的正、負邊緣觸發。正邊緣觸發clk_div5p在第0及第1兩個完整週期輸出為高準位,負邊緣觸發clk_div5n在第0.5至第2.5兩個週期間輸出為高準位,最後再取or運算,得到2.5週期的高準位。