2012-10-05 35 views
10

Tôi đang cố gắng tạo ra một shifter thùng tái sử dụng; nó lấy một mảng đầu vào của các bit và thay đổi chúng một số vị trí nhất định (được xác định bởi một đầu vào khác). Tôi muốn tham số hóa mô-đun để nó hoạt động cho bất kỳ n nào.VHDL: sử dụng độ dài của một số nguyên chung để xác định số lượng các dòng chọn

Số lượng các dòng được chọn được xác định bởi n -> tức là, SHIFT_CNT = log2(NUMBITS-1)+1 trong mã bên dưới. Nó được coi là hình thức xấu trong tổ chức của tôi (và tôi nghĩ tổng thể) có cổng không phải là std_logic_vector hoặc std_logic, vì vậy tôi đã sử dụng một số std_logic_vector cho số dòng được chọn. Tôi cần điều chỉnh độ dài của std_logic_vector dựa trên dữ liệu chung chung. Có cách nào để làm điều này mà không sử dụng một generic chung thứ hai? Tôi đã nhìn thấy this bài đăng, nhưng nó không xử lý với Generics. This bài loại bỏ toàn bộ generics hoặc sử dụng giá trị log như generic, không trực quan cho người dùng trong tương lai (và có thể gây ra vấn đề nếu INPUT không phải là sức mạnh của hai).

Tuyên bố của SHIFT_CNT bên dưới chắc chắn là không chính xác; có cách nào để tự động tạo chiều dài trong khai báo thực thể mà không sử dụng một generic chung thứ hai không?

entity BarrelShifter is 

generic (NUMBITS : integer :=8);             
Port (INPUT  : in std_logic_vector (NUMBITS-1 downto 0);     
      OUTPUT : out std_logic_vector (NUMBITS-1 downto 0);     
      SHIFT_CNT : in std_logic_vector ((NUMBITS-1)'length downto 0)     
     );                
end BarrelShifter; 

Trả lời

7

Bạn có thể tạo một log2 chức năng trong thư viện, như thế này:

function f_log2 (x : positive) return natural is 
     variable i : natural; 
    begin 
     i := 0; 
     while (2**i < x) and i < 31 loop 
     i := i + 1; 
     end loop; 
     return i; 
    end function; 

Nếu thư viện được nhập khẩu sau đó bạn có thể chỉ định các cổng như thế này:

shift_cnt : in std_logic_vector(f_log2(NUMBITS)-1 downto 0) 

Nó là một giải pháp hơi xấu xí, nhưng nó không sử dụng bất kỳ tài nguyên nào (vì hàm này là thuần túy và tất cả các đầu vào đều được biết tại thời gian biên dịch).

Tôi thường làm điều này, nhưng bạn có thể muốn chỉ định giá trị nhật ký làm giá trị chung như bạn đang đề cập.

+0

Đó là một trong những mối quan tâm của tôi - tôi không muốn viết hàm có thể yêu cầu tài nguyên FPGA để tính toán. Tôi vẫn muốn một cái gì đó hoàn toàn khép kín nếu có thể (trái ngược với việc viết một thư viện và sau đó nhớ bao gồm nó bất cứ nơi nào tôi cần) – NickD

+0

Tôi có thể thấy tại sao bạn muốn điều đó (tôi cũng vậy, vì nó là một vấn đề phổ biến!) nhưng tôi khá chắc chắn không có một cách thanh lịch hơn để làm điều đó. Trong công ty của tôi, chúng tôi có một thư viện với các chức năng phổ biến như chức năng này mà chúng tôi nhập vào tất cả các tệp nguồn. – pc3e

13

Bạn có thể sử dụng thư viện toán để tính log2 và ceil của kết quả logarit để khai báo kích thước của SHIFT_CNT.

use IEEE.math_real.all; 

hoặc các chức năng cụ thể

use IEEE.math_real."ceil"; 
use IEEE.math_real."log2"; 

Ví dụ bạn muốn tính clog2 giá trị một

result := integer(ceil(log2(real(a)))); 

Nếu bạn chỉ sử dụng các chức năng để tính toán paramater, mã của bạn là tổng hợp(Tôi đã làm).

Nếu bạn không muốn sử dụng nó trong thực thể, bạn có thể khai báo chúng trong một thư viện hoặc chung chung với các chức năng này.

+0

Cảm ơn Khanh; Tôi đã làm điều này như là một stopgap, và các chức năng ceil và log2 bằng cách nào đó luôn luôn cho tôi một chút thêm. Nó được cắt tỉa đi anyway, nhưng tôi đã hy vọng có một cái gì đó nhỏ gọn hơn mà không yêu cầu thư viện hoặc tài nguyên FPGA bổ sung. – NickD

+0

Nó có nghĩa là bạn muốn tầng log2 cho bit nhỏ hơn. Ví dụ, kết quả của log 2 là 1.34, ceil là 2 và floor là 1. Tôi nghĩ thư viện cần thiết này là tiêu chuẩn (chuẩn IEEE) và không quan tâm đến nó. Phương thức khác là sử dụng tham số 2 để khai báo. Ở tệp trên cùng, bạn có thể sử dụng chức năng này. – Khanh

+0

@ user1723509, sử dụng thư viện theo cách được mô tả trong câu trả lời này hoặc câu trả lời khác [http://stackoverflow.com/a/12751341/897968) không nên sử dụng bất kỳ tài nguyên FPGA bổ sung nào, vì đầu ra của hàm có thể được giải quyết trong thời gian biên dịch/tổng hợp. – FriendFX

3

Hai cách tiếp cận khác:

Bạn có thể làm việc nó ngược lại có generic như shift_bits - sau đó tính toán độ rộng của các vectơ đầu vào và đầu ra từ đó:

generic (shift_bits: integer :=3);             
Port (INPUT  : in std_logic_vector ((2**shift_bits)-1 downto 0);     
      OUTPUT : out std_logic_vector ((2**shift_bits)-1 downto 0);     
      SHIFT_CNT : in std_logic_vector (shift_bits-1 downto 0)     
     ); 

Hoặc xử lý tính là một số:

generic (NUMBITS : integer :=8);             
Port (INPUT  : in std_logic_vector (NUMBITS-1 downto 0);     
      OUTPUT : out std_logic_vector (NUMBITS-1 downto 0);     
      SHIFT_CNT : in integer range 0 to numbits-1     
     ); 

và để các công cụ tìm ra cho bạn.

+0

Tôi nghĩ trong trường hợp BITWIDTH không phải là 2 công suất, khai báo đầu tiên không phù hợp, cách thứ hai tốt hơn. Tôi đã làm một số mô-đun với số nguyên/loại thiên nhiên vào/ra nhưng đồng nghiệp của tôi đã không chấp nhận. Vì vậy, bất kỳ vấn đề với điều này? Là kích thước cố định thu được sau khi tổng hợp? – Khanh

0

Khi tôi đang sử dụng phương pháp được đề cập bởi Khan, tôi gặp lỗi làm tròn. Vì vậy, tôi đã viết các phiên bản của riêng tôi, miễn dịch với các lỗi làm tròn và có thể, về nguyên tắc xử lý hơn 32 bit. Bạn có thể thay thế loại L với bất kỳ Kiểu nào có toán tử trái phép chuyển đổi logic.

Hầu hết thời gian bạn muốn sử dụng log2ceil là số lượng bit cần thiết để lưu trữ số đã cho, trong khi log2floor có thể được mô tả nhiều hơn là bộ bit cao nhất.

Trong hầu hết các trường hợp, các chức năng này là tốt để tổng hợp khi chúng được sử dụng để tạo các hằng số. Vì vậy, không có phần cứng nào được suy ra cho chúng.

function log2ceil (L: POSITIVE) return NATURAL is 
    variable i, bitCount : natural; 
begin 
    i := L-1; 
    bitCount:=0; 
    while (i > 0) loop 
     bitCount := bitCount + 1; 
     i:=srlInteger(i,1); 
    end loop; 
    return bitCount; 
end log2ceil; 

function log2floor (L: POSITIVE) return NATURAL is 
    variable i, bitCount : natural; 
begin 
    i := L; 
    bitCount:=0; 
    while (i > 1) loop 
     bitCount := bitCount + 1; 
     i:=srlInteger(i,1); 
    end loop; 
    return bitCount; 
end log2floor; 

function srlInteger(arg: integer; s:natural) return integer is 
begin 
    return to_integer(SHIFT_RIGHT(to_UNSIGNED(ARG,32), s)); 
end srlInteger; 
0

Bạn có thể thay vì nhập giá trị NUMBITS như 8, đầu vào nó như là 2 (log2 (8)), sau đó gõ lại như dưới đây để có được xung quanh vấn đề này, bạn generic chỉ sẽ không được làm sạch nhưng nó có khả năng mở rộng quy mô.

entity BarrelShifter is 

generic (NUMBITS : integer :=2);             
Port (INPUT  : in std_logic_vector (((2**Nbits)-1) downto 0);     
      OUTPUT : out std_logic_vector (((2**Nbits)-1) downto 0);     
      SHIFT_CNT : in std_logic_vector ((NUMBITS-1) downto 0)     
     );                
end BarrelShifter; 
Các vấn đề liên quan