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ụ:
- Trì hoãn dữ liệu theo một số chu kỳ đồng hồ (tạo delay);
- Chuyển đổi dữ liệu nối tiếp thành dữ liệu song song;
- 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.
-- 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
Bình luận gần đây