Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

Bài viết này giải thích các phương pháp kích hoạt xung cơ bản như kích hoạt xung mức cao, Kích hoạt xung mức thấp, kích hoạt cạnh lên và kích hoạt cạnh xuống.

Kích xung cho Flip Flop

Bài viết này giải thích các phương pháp kích hoạt xung cơ bản như kích hoạt xung mức cao, Kích hoạt xung mức thấp, kích hoạt cạnh lên và kích hoạt cạnh xuống.

Việc kích hoạt xung cho các FF là một việc vô cùng quan trọng, đầu ra của flip flop có thể được thay đổi bằng cách mang lại một thay đổi nhỏ trong tín hiệu đầu vào. Sự thay đổi nhỏ này có thể được thực hiện với sự trợ giúp của xung clock hay được gọi là xung kích hoạt.

Khi một xung được cấp cho ngõ vào ngõ ra sẽ thay đổi , khi đó FF sẽ được kích hoạt. FF được sử dụng nhiều trong thiết kế bộ đếm hoặc thanh ghi lưu trữ dữ liệu dưới dạng số nhiều bit. Nhưng các thanh ghi như vậy cần một nhóm các flip flop được kết nối với nhau như các mạch tuần tự. Và các mạch tuần tự này đòi hỏi các xung kích hoạt.

Số lượng xung kích hoạt được cấp cho đầu vào của mạch xác định số lượng trong một bộ đếm. Một xung đơn làm cho bit di chuyển một vị trí, khi nó được áp dụng vào một thanh ghi lưu trữ dữ liệu nhiều bit.

Trong trường hợp Flip Flop RS, sự thay đổi mức tín hiệu quyết định loại kích hoạt sẽ được cung cấp cho đầu vào. Nhưng mức ban đầu phải được lấy lại trước khi đưa ra xung thứ hai cho mạch.

Nếu một xung đồng hồ được cấp cho đầu vào của flip flop cùng một lúc khi đầu ra của flip flop đang thay đổi, nó có thể gây ra sự mất ổn định cho mạch. Lý do cho sự không ổn định này là thông tin phản hồi được đưa ra từ mạch tổ hợp đầu ra đến các phần tử bộ nhớ. Vấn đề này có thể được giải quyết ở một mức độ nhất định bằng cách làm cho flip flop nhạy hơn với quá trình chuyển đổi xung hơn là thời lượng xung.

Chủ yếu có bốn loại phương pháp kích hoạt xung. Chúng khác nhau theo cách mà các mạch điện tử phản ứng với xung

1.      Kích hoạt xung tích cực mức cao

Khi Flip Flop yêu cầu cần phải lật trạng thái ở trạng thái cao chúng ta sẽ sử dụng phương pháp kích hoạt này.

Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

2.      Kích hoạt xung tích cực mức thấp

Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

Khi Flip Flop yêu cầu cần phải lật trạng thái ở trạng thái thấp chúng ta sẽ sử dụng phương pháp kích hoạt này.

Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

3.      Kích hoạt xung tích cực cạnh lên

Khi FF yêu cầu trạng thái chuyển đổi từ thấp sang cao để lật trạng thái, phương pháp kích hoạt cạnh lên được sử dụng.

Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

4.      Kích hoạt xung tích cực cạnh xuống

Khi FF yêu cầu trạng thái chuyển đổi từ mức cao sang mức thấp để lật trạng thái, phương pháp kích hoạt cạnh xuống được sử dụng.

Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

5.      Chuyển tiếp xung clock

Xung kích hoạt luôn hoạt động từ 0 đến 1 và sau đó là 1 đến 0 của tín hiệu. Do đó, phải mất hai lần chuyển tiếp trong một tín hiệu. Khi nó chuyển từ 0 sang 1 được gọi là chuyển tiếp dương và khi chuyển từ 1 sang 0 gọi là chuyển tiếp âm. Để hiểu thêm hãy xem những hình ảnh dưới đây.

Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

Khi flip-flop được kích hoạt trong quá trình chuyển đổi 0 đến 1 của xung và quá trình chuyển đổi trạng thái bắt đầu ngay khi xung đạt đến mức CAO. Nếu các đầu vào khác thay đổi khi xung vẫn là 1 thì ngõ ra vẫn giữ nguyên cho đến khi gặp xung tiếp theo. 

Thanh ghi dịch là một khối quan trọng phôt biến trong FPGA . Chúng được tạo ra bằng cách xếp tầng các Flip-Flop (Register) thành một chuỗi. Tất cả thanh ghi phải sử dụng cùng một clock và đầu ra của một thanh ghi phải được kết nối với đầu vào của thanh ghi tiếp theo trong chuỗi đó. Thanh ghi dịch chủ yếu được sử dụng để thực hiện một trong ba nhiệm vụ:

  1. Trì hoãn dữ liệu theo một số chu kỳ đồng hồ (tạo delay);
  2. Chuyển đổi dữ liệu nối tiếp thành dữ liệu song song;
  3. Chuyển đổi dữ liệu song song thành dữ liệu nối tiếp.

Tạo delay:

Tạo Delay trong một FPGA là việc sử dụng phổ biến nhất của thanh ghi dịch. Độ trễ thường được sử dụng để căn chỉnh dữ liệu đúng lúc. Hình dưới đây cho thấy kiểu thanh ghi dịch đơn giản này. Số lượng Flip-Flops trong chuỗi trì hoãn quyết định số lượng chu kỳ đồng hồ mà nó sẽ lấy cho dữ liệu trên đầu vào để truyền cho dữ liệu trên đầu ra. Vì vậy, trong hình dưới đây, nó sẽ mất bốn chu kỳ đồng hồ cho một đầu vào trên D trên Flip-Flop đầu tiên được nhìn thấy trên đầu ra Q của Flip-Flop cuối cùng. Đọc về các Processes trong VHDL hoặc Always Blocks trong Verilog để có hướng dẫn về cách tạo một thanh ghi thay đổi trong HDL của bạn.

Thanh ghi dịch sử dụng flip-flop d trong bài thực hành số 3 là thanh ghi dạng

Thanh ghi dịch- Từ D Flip-Flops

-- VHDL Example of Shift Register for Delay: signal r_Shift : std_logic_vector(3 downto 0); process (i_clock) begin if rising_edge(i_clock) then r_Shift(3 downto 1) <= r_Shift(2 downto 0); -- Shift Left r_Shift(0) <= i_Data_To_Delay; -- Bit 3 of r_Shift has been delayed by 4 clock cycles end if; end process;

-- VHDL Example of Shift Register for Delay:

signal r_Shift : std_logic_vector(3 downto 0);

process (i_clock)

begin

  if rising_edge(i_clock) then

    r_Shift(3 downto 1) <= r_Shift(2 downto 0); -- Shift Left

    r_Shift(0)          <= i_Data_To_Delay;

    -- Bit 3 of r_Shift has been delayed by 4 clock cycles

  end if;

end process;


// Verilog Example of Shift Register for Delay: reg [3:0] r_Shift; always @ (posedge i_clock) begin r_Shift[3:1] <= r_Shift[2:0]; // Shift Left r_Shift[0] <= i_Data_To_Delay; // Bit 3 of r_Shift has been delayed by 4 clock cycles end

// Verilog Example of Shift Register for Delay:

reg [3:0] r_Shift;

always @ (posedge i_clock)

  begin

    r_Shift[3:1] <= r_Shift[2:0];  // Shift Left

    r_Shift[0]   <= i_Data_To_Delay;

    // Bit 3 of r_Shift has been delayed by 4 clock cycles

  end


Đoạn mã trên minh họa việc tạo độ trễ bằng cách chuyển i_Data_To_Delay đến bit ít quan trọng nhất của r_Shift. Sau đó r_Shift liên tục dịch chuyển sang trái trên mỗi chu kỳ đồng hồ. Điều này có thể hữu ích ví dụ nếu bạn nhận được một số dữ liệu từ một mô-đun, nhưng không muốn hành động ngay lập tức. Trong đoạn mã trên, bất kỳ bit nào từ r_Shift có thể được sử dụng để kiểm soát chính xác độ trễ được áp dụng, bit 0 có 1 bit trễ, và bit 3 có 4 bit trễ.

Chuyển đổi dữ liệu nối tiếp thành dữ liệu song song

Chuyển đổi từ dữ liệu nối tiếp sang dữ liệu song song là một cách sử dụng phổ biến khác của thanh ghi dịch. Điều này xảy ra khi giao tiếp với các tín hiệu ngoài chip truyền dữ liệu một cách thẳng thắn như bộ thu UART. Khi dữ liệu đến trên UART, nó cần phải được chuyển đổi từ dữ liệu nối tiếp rộng 1-bit thành một byte song song mà FPGA có thể xem xét.

signal r_RX_Data : std_logic := '0'; signal r_Bit_Index : integer range 0 to 7 := 0; -- 8 Bits Total signal r_RX_Byte : std_logic_vector(7 downto 0) := (others => '0'); p_UART_RX : process (i_Clk) begin if rising_edge(i_Clk) then r_Rx_Byte[7] <= r_Rx_Data; -- Data is sent least-significant byte first r_Rx_Byte[6:0] <= r_Rx_Byte[7:1]; -- shift right -- ABOVE DOES SAME THING AS: -- r_RX_Byte(r_Bit_Index) <= r_RX_Data; -- Check if we have sent out all bits if r_Bit_Index < 7 then r_Bit_Index <= r_Bit_Index + 1; r_SM_Main <= s_RX_Data_Bits; else r_Bit_Index <= 0; -- RECEIVE OF A UART BYTE COMPLETE HERE

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

signal r_RX_Data   : std_logic := '0';

signal r_Bit_Index : integer range 0 to 7 := 0;  -- 8 Bits Total

signal r_RX_Byte   : std_logic_vector(7 downto 0) := (others => '0');

p_UART_RX : process (i_Clk)

begin

  if rising_edge(i_Clk) then

    r_Rx_Byte[7]   <= r_Rx_Data;       -- Data is sent least-significant byte first

    r_Rx_Byte[6:0] <= r_Rx_Byte[7:1];  -- shift right

    -- ABOVE DOES SAME THING AS:

    -- r_RX_Byte(r_Bit_Index) <= r_RX_Data;

    -- Check if we have sent out all bits

    if r_Bit_Index < 7 then

      r_Bit_Index <= r_Bit_Index + 1;

      r_SM_Main   <= s_RX_Data_Bits;

    else

      r_Bit_Index <= 0;   -- RECEIVE OF A UART BYTE COMPLETE HERE

reg r_Rx_Data = 1'b1; // Received UART Data reg [2:0] r_Bit_Index = 0; //8 bits total reg [7:0] r_Rx_Byte = 0; always @(posedge i_Clock) begin // SNIPPET: r_Rx_Byte[7] <= r_Rx_Data; // Data is sent least-significant byte first, so shift right r_Rx_Byte[6:0] <= r_Rx_Byte[7:1]; // ABOVE DOES SAME THING AS: // r_Rx_Byte[r_Bit_Index] <= r_Rx_Data; // Check if we have received all bits if (r_Bit_Index < 7) r_Bit_Index <= r_Bit_Index + 1; else r_Bit_Index <= 0; // RECEIVE OF A UART BYTE COMPLETE HERE

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

reg       r_Rx_Data   = 1'b1;  // Received UART Data

reg [2:0] r_Bit_Index = 0; //8 bits total

reg [7:0] r_Rx_Byte   = 0;

always @(posedge i_Clock)

  begin

    // SNIPPET:        

    r_Rx_Byte[7]   <= r_Rx_Data;  // Data is sent least-significant byte first, so shift right

    r_Rx_Byte[6:0] <= r_Rx_Byte[7:1];

    // ABOVE DOES SAME THING AS:

    // r_Rx_Byte[r_Bit_Index] <= r_Rx_Data;

    // Check if we have received all bits

    if (r_Bit_Index < 7)

       r_Bit_Index <= r_Bit_Index + 1;

    else

       r_Bit_Index <= 0;  // RECEIVE OF A UART BYTE COMPLETE HERE

Chuyển đổi dữ liệu song song thành dữ liệu nối tiếp

Điều này ngược lại với phần trên và được sử dụng trong Máy phát UART. Khi bạn muốn truyền một byte qua UART, trước tiên nó phải được tuần tự hóa và được gửi đi trên một dòng UART duy nhất. Một thanh ghi thay đổi có thể được sử dụng cho mục đích này.

signal r_Bit_Index : integer range 0 to 7 := 0; -- 8 Bits Total signal r_TX_Data : std_logic_vector(7 downto 0) := (others => '0'); begin p_UART_TX : process (i_Clk) begin if rising_edge(i_Clk) then -- SNIPPET: o_TX_Serial <= r_TX_Data(0); -- Data is shifted out least-significant bit first. r_TX_Data(6 downto 0) <= r_TX_Data(7 downto 1); -- Shift next bit into place. -- ABOVE DOES SAME THING AS: -- o_TX_Serial <= r_TX_Data(r_Bit_Index); -- Check if we have sent out all bits if r_Bit_Index < 7 then r_Bit_Index <= r_Bit_Index + 1; else r_Bit_Index <= 0; // TRANSMIT OF A UART BYTE COMPLETE HERE end if;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

signal r_Bit_Index : integer range 0 to 7 := 0;  -- 8 Bits Total

  signal r_TX_Data   : std_logic_vector(7 downto 0) := (others => '0');

begin

  p_UART_TX : process (i_Clk)

  begin

    if rising_edge(i_Clk) then

      -- SNIPPET:

      o_TX_Serial <= r_TX_Data(0);  -- Data is shifted out least-significant bit first.

      r_TX_Data(6 downto 0) <= r_TX_Data(7 downto 1);  -- Shift next bit into place.

      -- ABOVE DOES SAME THING AS:

      -- o_TX_Serial <= r_TX_Data(r_Bit_Index);

      -- Check if we have sent out all bits

      if r_Bit_Index < 7 then

        r_Bit_Index <= r_Bit_Index + 1;

      else

        r_Bit_Index <= 0;  // TRANSMIT OF A UART BYTE COMPLETE HERE

      end if;

reg [2:0] r_Bit_Index = 0; reg [7:0] r_Tx_Data = 0; always @(posedge i_Clock) begin // SNIPPET: o_TX_Serial <= r_TX_Data[0]; // Data is shifted out least-significant bit first. r_TX_Data[6:0] <= r_TX_Data[7:1]; // Shift next bit into place. // ABOVE DOES SAME THING AS: // o_Tx_Serial <= r_Tx_Data[r_Bit_Index]; // Check if we have sent out all bits if (r_Bit_Index < 7) begin r_Bit_Index <= r_Bit_Index + 1; end else begin r_Bit_Index <= 0; end end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

reg [2:0] r_Bit_Index = 0;

reg [7:0] r_Tx_Data   = 0;

always @(posedge i_Clock)

  begin      

    // SNIPPET:    

    o_TX_Serial    <= r_TX_Data[0];    // Data is shifted out least-significant bit first.

    r_TX_Data[6:0] <= r_TX_Data[7:1];  // Shift next bit into place.

    // ABOVE DOES SAME THING AS:

    // o_Tx_Serial <= r_Tx_Data[r_Bit_Index];

    // Check if we have sent out all bits

    if (r_Bit_Index < 7)

      begin

        r_Bit_Index <= r_Bit_Index + 1;

      end

    else

      begin

        r_Bit_Index <= 0;

      end

    end

Hy vọng rằng bài viết này đã cho bạn một sự hiểu biết cơ bản về những gì một thanh ghi dịch trong FPGA hoặc ASIC. Để xem cách tạo thanh ghi dịch của riêng bạn trong Verilog hoặc VHDL, hãy xem các liên kết bên dưới.

Tạo một thanh ghi Shift trong Verilog
Shift Left, Shift Right trong VHDL