Bài 10: Thanh ghi dịch là gì? (Shift Register)

THANH GHI DỊCH =>Tạo delay, chuyển đổi dữ liệu nối tiếp và dữ liệu song song trong FPGA

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.

Simple Delay Shift Đăng ký

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;
// 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
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;
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

Chapichuse

Đam mê công nghệ

You may also like...

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *