Thứ Ba, 1 tháng 8, 2017

[Verilog] RTL code mô tả các loại bộ đếm - counter

Bài viết này mô tả mạch nguyên lý và RTL code của các loại bộ đếm thông dụng như bộ đếm binary, bộ đếm Gray, bộ đếm Ring, Johnson và modulo-N.
1. Bộ đếm binary
Bộ đếm binary có các đặc điểm sau đây: 
  • Bộ đếm lên/xuống tuần tự
  • Có reset đồng bộ mức thấp
  • Có tín hiệu nạp giá trị cho bộ đếm
  • Số lượng bit của bộ đếm là N
  • Có tín hiệu báo bộ đếm đang hoạt động đếm lên hoặc đếm xuống
Loại bộ đếm này rất thông dụng trong các thiết kế số để chia tần số, đếm số xung, giám sát động rộng tín hiệu, tạo địa chỉ truy cập bộ nhớ, ... Tất nhiên, tùy vào ứng dụng thực tế bộ đếm sẽ có những tùy biến khác nhau.
Hình 1. Mạch nguyên lý bộ đếm binary
RTL code cho bộ đếm binary:
module bin_counter (clk, rst_n, load, count_up, count_down, init_value, binary_count, count_on);
parameter N = 4;
////Interface
input clk;
input rst_n;
input load;
input count_up;
input count_down;
input [N-1:0] init_value;
output reg [N-1:0] binary_count;
output wire count_on;
always @ (posedge clk) begin
  if (~rst_n) binary_count[N-1:0] <= 0;
  else if (load) binary_count[N-1:0] <= init_value[N-1:0];
  else begin
    case ({count_up, count_down})
      2'b10: binary_count[N-1:0] <= binary_count[N-1:0] + 1'b1;
      2'b01: binary_count[N-1:0] <= binary_count[N-1:0] - 1'b1;
    endcase
  end
end
assign count_on = (count_down | count_up) & ~load;
endmodule
2. Bộ đếm theo mã Gray
Mã Gray có đặc điểm là 2 giá trị liên tiếp nhau chi khác nhau một bit. Mã Gray có thể được chuyển đổi từ mã binary thông qua quy tắc sau: 
  • Bit MSB của mã Gray bằng bit MSB của mã binary
  • Bit thứ n trong mã Gray bằng bit thứ n XOR với bit thứ n+1 trong mã binary
Hình 2. Mạch nguyên lý chuyển đổi từ mã binary sang mã Gray N bit
Hình 3. Ví dụ về bảng chuyển đổi giữa mã binary và gray 4 bit
Để thực hiện được một bộ đếm mã Gray, chúng ta chỉ cần thêm mạch chuyển đổi từ mã binary sang mã Gray như hình 2 vào ngõ ra bộ đếm binary. RTL code của bộ đếm mã Gray N bit như sau:
module gray_counter (clk, rst_n, load, count_up, count_down, init_value, gray_count, count_on);
parameter N = 4;
////Interface//
input clk;
input rst_n;
input load;
input count_up;
input count_down;
input [N-1:0] init_value;
output reg [N-1:0] gray_count;
output wire count_on;
reg [N-1:0] binary_count;
always @ (posedge clk) begin
if (~rst_n) binary_count[N-1:0] <= 0;
else if (load) binary_count[N-1:0] <= init_value[N-1:0];
else begin
 case ({count_up, count_down})
 2'b10: binary_count[N-1:0] <= binary_count[N-1:0] + 1'b1;
 2'b01: binary_count[N-1:0] <= binary_count[N-1:0] - 1'b1;
 endcase
end
end
assign count_on = (count_down | count_up) & ~load;
//Binary to Gray
integer i;
always @ (*) begin
 gray_count[N-1] = binary_count[N-1];
 for (i = 0; i < N-1; i = i + 1) gray_count[i] = binary_count[i] ^ binary_count[i+1];
end 
endmodule
3. Bộ đếm vòng - Ring counter
Bộ đếm vòng hoạt động như một thanh ghi dịch. Nó sẽ dịch một giá trị đã nạp trước trong một vòng khép kín theo xung clock.
Hình 4. Bộ đếm vòng
Hình 4 là bộ đếm vòng đơn giản có một tín hiệu load để nạp giá trị ban đầu. Nếu load = 0, bộ đếm sẽ hoạt động liên tục theo xung clock.
Hình 5. Ví dụ về bộ đếm vòng 4 bit với giá trị khởi động được nạp là 0001
RTL có của bộ đếm vòng N bit như sau:
module ring_counter (clk, rst_n, load, init_value, ring_count);
parameter N = 4;
////Interface
input clk;
input rst_n;
input load;
input [N-1:0] init_value;
output reg [N-1:0] ring_count;
always @ (posedge clk) begin
if (~rst_n) ring_count[N-1:0] <= 0;
else if (load) ring_count[N-1:0] <= init_value[N-1:0];
else ring_count[N-1:0] <= {ring_count[N-2:0], ring_count[N-1]};
end
endmodule
4. Bộ đếm Johnson
Bộ đếm Johnson là một loại bộ đếm theo kiểu dịch như bộ đếm vòng trên đây. Điểm khác biệt là bộ đếm Johnson là ngõ vào của LSB (bit 0) sẽ lấy bù của ngõ ra bit MSB (bit N-1).
Hình 6. Ví dụ về bộ đếm Johnson 4 bit
Hình 7. Mạch nguyên lý bộ đếm Johnson N bit
RTL code của bộ đếm Johnson N bit:
module johnson_counter (clk, rst_n, js_count);
parameter N = 4;
////Interface
input clk;
input rst_n;
output reg [N-1:0] js_count;
wire js_msb_inv;
assign js_msb_inv = ~js_count[N-1];
always @ (posedge clk) begin
if (~rst_n) js_count[N-1:0] <= 0;
else js_count[N-1:0] <= {js_count[N-2:0], js_msb_inv};
end
endmodule
5. Bộ đếm Modulo-N
Modulo-N, viết tắt là MOD-N, là bộ đếm có N trạng thái tuần tự. Giả sử các trạng thái đó tuần tự từ 0 đến N-1 thì sau N-1, trạng thái bộ đếm sẽ quay về 0. Ví dụ, bộ đếm MOD-3 sẽ có chuỗi trạng thái như sau: 0->1->2->(quay lại về 0). Bộ đếm có số bit là n thì có thể tạo thành bộ đếm modulo tối đa là MOD-2^n. Ví dụ, bộ đếm 2 bit thì tối đa là MOD-4, 3 bit thì tối đa là MOD-8. Như vậy, để tạo bộ đếm MOD-5, MOD-6 hoặc MOD-7 thì cần 3 bit.
Bộ đếm lên MOD-N với số bit tùy chọn có các đặc điểm sau đây: 
  • MODN là số trạng thái bộ đếm, tương ứng với số N trong ký hiệu MOD-N 
  • BITN là số bit của bộ đếm 
  • en là tín hiệu cho phép bộ đếm hoạt động 
  • rst_n là reset đồng bộ tích cực mức thấp
Hình 8. Mạch nguyên lý bộ đếm lên MOD-N
RTL code của bộ đếm MOD-N:
module mod_counter (clk, rst_n, en, mod_count);
parameter BITN = 3;
parameter MODN = 5;
////Interface//
input clk;
input rst_n;
input en;
output reg [BITN-1:0] mod_count;
always @ (posedge clk) begin
if (~rst_n) mod_count[BITN-1:0] <= 0;
else if (en) mod_count[BITN-1:0] <= (mod_count[BITN-1:0] + 1'b1)%MODN;
end
endmodule

Lịch sử cập nhật:
1) 2019.11.10 - Chỉnh link hình 

5 bình luận:

  1. Có bài thiết kế mạch đếm vòng 8 bit có reset, có pause k ạ?

    Trả lờiXóa
    Trả lời
    1. Nó có thể đơn giản như sau:

      always @ (posedge Clk, negedge RstN)
      if (!RstN) Counter[7:0] <= 8'd0;
      else if (Pause)
      Counter[7:0] <= Counter[7:0];
      else
      Counter[7:0] <= Counter[7:0] + 1;
      end

      RstN là tín hiệu reset mức thấp, nếu RstN==0 thì Counter bị reset về 0.
      Pause là tín hiệu tạm dừng đếm, tích cực mức cao. Nếu Pause==1, thì bộ đến giữ nguyên giá trị hiện tại.
      Nếu RstN==1 (ko reset) và Pause==0 (ko tạm dừng) thì Counter đếm lên đều 1 đơn vị theo cạnh lên clock Clk.

      Nếu có yêu cầu khác thì em tự điều chỉnh theo gợi ý này.

      Xóa
  2. Anh có thể chỉ rõ va fgiair thích chương trih của bộ đếm mã vong có pause được không ạ

    Trả lờiXóa
  3. có bài thiết kế mạch đếm vòng đơn khoong ạ

    Trả lờiXóa
    Trả lời
    1. Em có thể mô tả chi tiết hơn "mạch đếm vòng đơn" mà em đang đề cập. Nó sẽ đếm như thế nào? anh sẽ gợi ý cách thực hiện

      Xóa