Nguyên văn bởi nemesis21
Xem bài viết
Thông báo
Collapse
No announcement yet.
Project nhỏ: Bộ lọc số FIR thực hiện bằng FPGA
Collapse
This is a sticky topic.
X
X
-
Tôi nghĩ nếu bạn cá chép đang gặp vấn đề với mạch delay, những giai đoạn tất yếu trước đó đã được hoàn thành? Dù với project nhỏ, chúng ta vẫn nên làm theo trình tự để giảm thiểu vấn đề.
- Requirements / specs cho filter như thế nào? Có vài chỉ số được đưa ra, nhưng hình như thiếu sự liên kết giữa các chỉ số quan trọng. Dù với scalable design, chúng ta vẫn phải đặt ra performance bounds. Rất không nên nhảy vào coding trước khi establishing requirements / specs.
- Design cho filter như thế nào? Dựa vào requirements / specs, bạn đã chọn filter structure nào? Parallel, serial (single multiplier), hoặc semi-parallel? Nếu serial, mạch delay của bạn nên sử dụng RAM (hoặc registers và multiplexer để emulate RAM). Nếu parallel, mạch delay của bạn nên sử dụng registers. Bạn đã chọn structure / mạch delay nào? Bạn đã vẽ block diagram cho design của bạn? Generic design hay là target spefiic? Chẳng hạn như với DSP48 của Virtex-4, parallel design có thể hoàn toàn sử dụng intenal registers và routing của DSP48. Bạn đã diagram / model mạch delay của bạn?
- Giai đoạn viết VHDL nên là giai đoạn dễ dàng nhất.
Khuyến khích làm các project là một việc hay, nhưng tôi nghĩ rằng học về process và các trình tự tất yếu còn quan trọng hơn simulation output đối với những người mới.
Comment
-
Phần filter analysis / design không quá khó. Chỉ với vài dòng lệnh, bạn có thể generate filter coefficients và analyze frequency response như trong screen captures 01/02, so sánh 21/51/101 taps Hamming filters và 101 taps Boxcar filter.
Trong screen captures 03 / 04, zero-padded sine wave được filter qua 21-tap Hamming filter. Zero-padded data được dùng để chúng ta có thể dễ dàng thấy được effect của filter.
Phần FIR filter đơn giản chỉ có 3-4 dòng:
Trong đó, phần delay buffer shifting là:Code:for in range (len(x)) : delay_buf[1:len(filter_coeffs)] = delay_buf[0:len(filter_coeffs)-1] delay_buf[0] = x[i] y[i] = sum(delay_buf * filter_coeffs)
Bạn có thể viết lại theo một form gần giống như HDL implementation hơn:Code:delay_buf[1:len(filter_coeffs)] = delay_buf[0:len(filter_coeffs)-1] delay_buf[0] = x[i]
Khi chuyển phần for loop qua VHDL, bạn có thể dùng generate hoặc loop, chẳng hạn như:Code:for j in range(len(filter_coeffs)-1,0,-1) : delay_buf[j] = delay_buf[j-1] delay_buf[0] = x[i]
Dòng lệnh delay_buf(j) = delay_buf(j-1) chỉ mang tính tượng trưng, delay_buf có thể là array of std_logic_vector hoặc std_logic_vector. Phần delay buffer, chúng ta chỉ cần vài dòng VHDL như bạn thấy. Bạn cũng có thể cần clock-enable nếu data không được transfer in mỗi clock cycle. Chúng ta đốt giai đoạn ở đây, nhưng bạn luôn phải establish requirements / specs / interface trước tiên.Code:DATA_SHIFT : for j in 20 downto 1 generate delay_buf(j) = delay_buf(j-1) when rising_edge(clk); end generate;
Tương tự như vậy, bạn cũng chuyển dần dòng lệnh dưới sang một dạng suitable cho HDL implementation hơn.
Bạn có thể chuyển sang dạng parallel/serial, hoặc semi-parallel tùy theo cấu trúc bạn muốn.Code:y[i] = sum(delay_buf * filter_coeffs)
Ở đây tôi đã dùng floating-point, nhưng đại khái là, bạn nên tạo ra một functional model trước, và sau đó chuyển thể từ từ sang dạng HDL suitable hơn. Như đã từng đề cập, phần viết VHDL nên là phần dễ dàng nhất. Chúc bạn thành công.
Comment
-
Với Matlab bạn sử dụng fir1() thay vì firwin() cho Python. Lưu ý là Nth order filter cho bạn N+1 taps.Nguyên văn bởi tonyvandinh Xem bài viếtNemesis21 có thể giúp dùng Matlab để tạo ra bộ coefficient, số tap, input và output vectors được kô? Thx
Phần analysis đơn giản hơn Python:Code:N = 20; cf = fir1(N, .2, hamming(N+1))
Sine input, nếu bạn không cần zero-fill thì cũng đơn giản:Code:freqz(cf, 1)
Thường tôi không dùng Matlab vì vấn đề license. Python và các numerical libraries có thể không hoàn toàn tiện lợi bằng nhưng là open source.Code:input = sin((1:100)/10))
Comment
-
Sẵn rãnh một chút, tôi sẽ bàn tiếp về FIR filter implementation cho các bạn mới bắt đầu.
Về cấu trúc, khi nào áp dụng serial, parallel, hoặc semi-parallel?
Dựa vào các thông số number of taps N, processing clock rate C, và output sample rate S.
Serial, bạn sử dụng 1 multiplier (M = 1). Bạn cần N clock cycles để calculate 1 output. Nếu processing clock rate = 200 MHz, và number of taps = 20, bạn có thể dùng 1 multiplier để calculate 10 Msps (Megasample per second) trở xuống, N * S <= C * M
Nhưng nếu required output sample rate = 200 Msps, M = 1 không đủ. Trong trường hợp này, bạn cần fully parallel structure, M = N.
Nếu output sample rate = 50 Msps chẳng hạn, chúng ta vẫn có thể dùng M = N. Nhưng thông thường, design goal là phải sử dụng ít resources nhất, cho nên chúng ta sử dụng semi-parallel structure, với M = N / 4.
Nếu output sample rate > 200 Msps, chúng ta vẫn có thể xử lý, nhưng hơi advance cho mạch này.
=======
Sau khi chúng ta đã chọn filter structure hợp lý, cần phải model như thế nào?
Trong khâu này, bạn cần phải có khả năng visualize hardware một chút, và diagraming có lẽ sẽ giúp bạn rất nhiều.Code:y[i] = sum(delay_buf * filter_coeffs)
Break down một chút:
Nếu bạn chọn parallel implementation, bạn cần hình dung / diagram K delay data values và K coefficient values feed vào K multipliers và cho ra K products.Code:temp = 0; for k in range(len(filter_coeffs)) : temp = temp + delay_buf[k] * filter_coeffs[k]; y[i] = temp;
Bạn cộng lại các products như thế nào? Sử dụng adder tree hay là adder chain / cascade?Code:prod = zeros(len(filter_coeffs)); for k in range(len(filter_coeffs)) : prod[k] = delay_buf[k] * filter_coeffs[k];
.......
Comment
-
......
Hãy chọn adder tree nhé? Tổng thể model như thế này:
Code:delay_buf = zeros(len(filter_coeffs)); y = zeros(len(x)); prod = zeros(len(filter_coeffs)) for i in range (len(x)) : delay_buf[1:len(filter_coeffs)] = delay_buf[0:len(filter_coeffs)-1];delay_buf[0] = x[i] for k in range (len(filter_coeffs)) : prod[k] = delay_buf[k] * filter_coeffs[k]; y[i] = adder_tree(prod)
Sau đây hãy bắt đầu so chiếu với VHDL code đơn giản dùng pre-loaded coefficients.
Phần delay buffer declaration như sau:Code:library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.all; entity pfir is generic ( NUM_TAPS : positive range 5 to 200 := 21 ); port ( clk : in STD_LOGIC; data_in : in STD_LOGIC_VECTOR; data_out : out STD_LOGIC_VECTOR ); end pfir;
Phần delay buffer implementation, bạn có thể dùng generate loop như đã đề cập đến, hoặc đơn giản hơn:Code:type data_mem_type is array (natural range <>) of std_logic_vector(data_in'range); signal delay_buf : data_mem_type(NUM_TAPS-1 downto 0) := (others => (others => '0'));
Phần filter coefficients thủ công một chút. Chúng ta assume filter data width tưong tự như input data width.Code:delay_buf <= delay_buf(NUM_TAPS-2 downto 0) & data_in when rising_edge(clk);
Code:constant filter_coeffs : data_mem_type(NUM_TAPS-1 downto 0) := ( std_logic_vector(to_signed(integer(-6.21115459e-19 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-2.12227115e-03 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-6.32535399e-03 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-1.16118104e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-1.23546567e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(4.19252935e-18 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(3.17744976e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(8.14359076e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(1.37493782e-01 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(1.82125490e-01 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(1.99168830e-01 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(1.82125490e-01 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(1.37493782e-01 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(8.14359076e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(3.17744976e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(4.19252935e-18 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-1.23546567e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-1.16118104e-02 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-6.32535399e-03 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-2.12227115e-03 * 2.0**(data_in'length-1)-1.0),data_in'length)), std_logic_vector(to_signed(integer(-6.21115459e-19 * 2.0**(data_in'length-1)-1.0),data_in'length)) );
Phần multiplication cũng không quá khác so với model, cũng dùng for loop.
Code:type prod_mem_type is array (natural range <>) of signed(data_in'length*2-1 downto 0); signal prod : prod_mem_type(NUM_TAPS-1 downto 0) := (others => (others => '0'));
.......Code:MULT_GEN : for i in 0 to NUM_TAPS-1 generate prod(i) <= signed(delay_buf(i)) * signed(filter_coeffs(i)) when rising_edge(clk); end generate MULT_GEN;
Comment
-
.......
Adder tree rất cơ bản, chẳng hạn như chúng ta có 4 inputs a, b, c, d, nhưng adder chỉ có thể cộng lại tối đa mỗi lần 2 inputs, chúng ta trước tiên phải cộng (a+b) và (c+d), và sau đó cộng (a+b)+(c+d). Không khó để các bạn model adder tree, nhưng tôi đưa lên một version ở đây để tham khảo đối chiếu với VHDL implementation.
Code:def adder_tree (data_in) : num_inputs = len(data_in); num_levels = int(ceil(log2(num_inputs))); sum_out = zeros((num_levels, num_inputs)); for l in range(num_levels) : num_adders = int(ceil(num_inputs/(2.0**(l+1)))); num_adder_prev_stage=int(ceil(num_inputs/(2.0**(l)))); if (l == 0) : for m in range (num_adders) : if (m == (num_adders - 1)) and (num_adder_prev_stage % 2 == 1) : sum_out[l][m] = data_in[m*2]; else : sum_out[l][m] = data_in[m*2] + data_in[m*2+1]; else : for m in range (num_adders) : if (m == (num_adders - 1)) and (num_adder_prev_stage % 2 == 1) : sum_out[l][m] = sum_out[l-1][m*2]; else : sum_out[l][m] = sum_out[l-1][m*2] + sum_out[l-1][m*2+1]; return sum_out[num_levels-1][0]
So sánh với phần VHDL dưới đây:
Code:type sum_mem_type is array (natural range <>, natural range <>) of signed(data_in'length*2-1 downto 0); constant num_levels : natural := integer(ceil(log(real(NUM_TAPS)) / log(2.0))); signal sum : sum_mem_type(num_levels-1 downto 0, NUM_TAPS-1 downto 0) := (others => (others => (others => '0')));
Syntax giữa hai language có khác, nhưng về phần giải thuật hoàn toàn tương đồng. Như có thể thấy, nếu bạn model to the right form, bạn có thể nhanh chóng hoán chuyển giải thuật từ language ưa thích của bạn sang (V)HDL. Đừng quá chú tâm vào FPGA và HDL khi bạn implement một thuật toán cho FPGA. Những đoạn code trên hoàn toàn synthesizable.Code:ADDER_LEVELS_GEN : for l in 0 to num_levels-1 generate constant num_adders : natural := integer(ceil(real(NUM_TAPS)/(2.0**(l+1)))); constant num_adder_prev_stage : natural := integer(ceil(real(NUM_TAPS)/(2.0**(l)))); begin LEVEL_0_GEN : if (l = 0) generate ADDERS_GEN : for m in 0 to num_adders-1 generate NO_ADDER_GEN : if ((m = (num_adders-1)) and ((num_adder_prev_stage mod 2) = 1)) generate sum(l,m) <= prod(m*2) when rising_edge(clk); end generate NO_ADDER_GEN; ADDER_GEN : if ((m < (num_adders-1)) or ((num_adder_prev_stage mod 2) = 0)) generate sum(l,m) <= prod(m*2) + prod(m*2+1) when rising_edge(clk); end generate ADDER_GEN; end generate ADDERS_GEN; end generate LEVEL_0_GEN; LEVEL_X_GEN : if (l > 0) generate ADDERS_GEN : for m in 0 to num_adders-1 generate NO_ADDER_GEN : if ((m = (num_adders-1)) and ((num_adder_prev_stage mod 2) = 1)) generate sum(l,m) <= sum(l-1,m*2) when rising_edge(clk); end generate NO_ADDER_GEN; ADDER_GEN : if ((m < (num_adders-1)) or ((num_adder_prev_stage mod 2) = 0)) generate sum(l,m) <= sum(l-1,m*2) + sum(l-1,m*2+1) when rising_edge(clk); end generate ADDER_GEN; end generate ADDERS_GEN; end generate LEVEL_X_GEN; end generate ADDER_LEVELS_GEN; data_out <= std_logic_vector(sum(num_levels-1,0)) when rising_edge(clk);
Comment
-
Sang phần simulation, bạn có thể tiếp tục dùng math_real library.
Đoạn code dưới generate sine wave tương tự như phần Python code:Code:signal data_in : std_logic_vector(15 downto 0) := (others => '0'); signal data_out : std_logic_vector(31 downto 0) := (others => '0'); signal counter : natural := 0;
Phần simulation output trong hình đính kèm. Nói tóm lại là, cho một project, bạn nên dành thời gian cho specs / design / modeling. Với một project nhỏ, nếu bạn model tốt, thì bạn chỉ mất khoảng 5-15 phút để chuyển sang VHDL.Code:data_gen_proc : process(clk) begin if (rising_edge(clk)) then if (counter mod 4 = 0) then data_in <= std_logic_vector(to_signed(integer(sin(real(counter) / 10.0) * 32767.0), data_in'length)); else data_in <= (others => '0'); end if; counter <= counter + 1; end if; end process data_gen_proc;
=======
Adder tree còn rườm rà; systolic form gọn hơn nhiều:
Các bạn tiếp tục thử nhé.Code:delay_buf = zeros(len(filter_coeffs)*2-1); y = zeros(len(x)); prod = zeros(len(filter_coeffs)); sum_out = zeros(len(filter_coeffs)); for i in range (len(x)) : delay_buf[1:len(delay_buf)] = delay_buf[0:len(delay_buf)-1];delay_buf[0] = x[i] for k in range (len(filter_coeffs)) : prod[k] = delay_buf[k*2] * filter_coeffs[k]; for k in range (len(filter_coeffs)-1,-1,-1) : if (k == 0) : sum_out[k] = prod[k]; else : sum_out[k] = prod[k] + sum_out[k-1]; y[i] = sum_out[len(sum_out)-1]Last edited by nemesis21; 08-05-2010, 07:14.
Comment
-
Đây là những câu hỏi thường có trong đầu của người làm thiết kế. Khá phức tạp để chọn lựa cái architecture nào để làm. Khi chọn rồi, làm giữa chừng mà muốn đổi thì sao? Làm sao để trade-off giữa tốc độ và tốn kém? Vì vậy cần phải giữ thiết kế nguồn kô bị lệ thuộc vào thời gian and hardware architecture rồi dùng phương pháp tự động hóa để chuyển biến qua thiết kế hiện thực mà mình muốn. Link dưới đây sẽ cho các bạn có thêm khái niệm về phương pháp này (High Level Synthesis)Nguyên văn bởi nemesis21 Xem bài viết- Design cho filter như thế nào? Dựa vào requirements / specs, bạn đã chọn filter structure nào? Parallel, serial (single multiplier), hoặc semi-parallel? Nếu serial, mạch delay của bạn nên sử dụng RAM (hoặc registers và multiplexer để emulate RAM). Nếu parallel, mạch delay của bạn nên sử dụng registers. Bạn đã chọn structure / mạch delay nào? Bạn đã vẽ block diagram cho design của bạn? Generic design hay là target spefiic? Chẳng hạn như với DSP48 của Virtex-4, parallel design có thể hoàn toàn sử dụng intenal registers và routing của DSP48. Bạn đã diagram / model mạch delay của bạn?
http://en.wikipedia.org/wiki/High-level_synthesis
Comment
-
Với FIR, nếu chúng ta khởi đầu với parallel - adder tree VHDL implementation, conversion sang parallel - simple systolic chỉ mất vài chục giây. Chuyển sang serial, 5-15 phút. Chuyển sang semi-parallel, 10-20 phút. Nếu designed well, semi-parallel FIR có thể trade-off throughput vs size chỉ trong vài giây bằng cách thay đổi generics.Nguyên văn bởi tonyvandinh Xem bài viếtĐây là những câu hỏi thường có trong đầu của người làm thiết kế. Khá phức tạp để chọn lựa cái architecture nào để làm. Khi chọn rồi, làm giữa chừng mà muốn đổi thì sao? Làm sao để trade-off giữa tốc độ và tốn kém? Vì vậy cần phải giữ thiết kế nguồn kô bị lệ thuộc vào thời gian and hardware architecture rồi dùng phương pháp tự động hóa để chuyển biến qua thiết kế hiện thực mà mình muốn. Link dưới đây sẽ cho các bạn có thêm khái niệm về phương pháp này (High Level Synthesis)
http://en.wikipedia.org/wiki/High-level_synthesis
Nếu chúng ta cần gấp một configurable FIR core, chúng ta có thể bỏ ra vài phút với Coregen. FIR filter là một beginner project vừa tầm để introduce basic techniques, nhưng là một unconvincing case cho high level synthesis tools.
Mentor có một demonstration video dùng Catapult C để implement FIR:
http://www.mentor.com/products/esl/m...1-b8518e15cbbe
Phần C code cũng tương tự như bạn đã đưa lên, nhưng phần implementation lại nhắm vào ASIC, nên không thể nói rằng những biến thể đó là parallel vs semi-parallel vs serial architecture trên FPGA.
Nếu có thể thì bạn làm một high level synthesis demonstration cho FPGA. Demo của Mentor không nhắm vào FPGA cho nên chưa được convincing lắm.
System C là một chuyện, more exposure về FPGA cho "software crowd" beginners. Có khá nhiều tool để chuyển từ System C sang HDL. Nhưng "algorithm synthesis tool" có lẽ thuộc vào một phạm trù khác. Về cost và availability, nó nằm ngoài tầm với, ngay cả cho nhiều companies. Tôi cảm thấy nó là một sự phụ thuộc vào tool từ một vài specific vendor hơn là một phương pháp đại trà.
Comment
-
Tiếp theo phần simple systolic FIR hôm trước, nếu bạn thử implement adder chain và synthesize FIR cho Virtex-5 speed grade -2 device, maximum frequency sẽ vào khoảng 250 MHz.
Code:ADDER_GEN : for i in 0 to NUM_TAPS-1 generate ADDER_0_GEN : if i = 0 generate sum(i) <= prod(i) when rising_edge(clk); end generate; ADDER_X_GEN : if i > 0 generate sum(i) <= prod(i) + sum(i-1) when rising_edge(clk); end generate; end generate ADDER_GEN;Làm thế nào để synthesize lên 500-600 MHz?Code:Timing Summary: --------------- Speed Grade: -2 Minimum period: 3.883ns (Maximum Frequency: 257.506MHz) Minimum input arrival time before clock: 0.980ns Maximum output required time after clock: 2.910ns Maximum combinational path delay: No path found
Chúng ta bắt đầu lại với phần hoán chuyển từ adder tree sang adder chain. Đó là một well-documented technique. Hình đính kèm từ Lyrtech illustrate technique đó khá rõ. Chúng ta có thể thấy các systolic "processing elements" illustrated trong phần 3. Simplified systolic (Python) model đã được đưa ra ở trên. Nhưng chúng ta model full systolic array như thế nào?
Đại khái là, processing element có thể được model bằng class:
Sau đó được kết nối lại như một linked-list:Code:class PE () : def __init__(self) : self.leftCell = 0; self.a1 = 0; self.a2 = 0; self.b2 = 0; self.m = 0; self.p = 0; def simClkCycle (self, a1 = 0) : if (self.leftCell == 0) : self.p = self.m + 0; self.m = self.a2 * self.b2; self.a2 = self.a1; self.a1 = a1; else : self.p = self.m + self.leftCell.p; self.m = self.a2 * self.b2; self.a2 = self.a1; self.a1 = self.leftCell.a2;
Và apply stimulus:Code:peList = list(); previousPE = 0; for j in range(len(filter_coeffs)) : pe = PE(); pe.b2 = filter_coeffs[j]; pe.leftCell = previousPE; peList.append(pe); previousPE = pe;
Phần hoán chuyển sang VHDL khá đơn giản:Code:for i in range (len(x)) : for k in range (len(filter_coeffs)-1,0,-1) : peList[k].simClkCycle(); peList[0].simClkCycle(x[i]); y[i] = peList[len(peList)-1].p;
Code:type breg_type is array(natural range <>) of std_logic_vector(data_in'range); signal breg : breg_type(NUM_TAPS-1 downto 0); type preg_type is array(natural range <>) of std_logic_vector(data_in'length*2-1 downto 0); signal preg : preg_type(NUM_TAPS-1 downto 0); constant zero : std_logic_vector(47 downto 0) := (others => '0');
Phần processing element các bạn hãy thử implement. Nếu implement đúng, thì khi synthesize, FIR filter implement sẽ chỉ tốn tài nguyên DSP48, và không tốn thêm bất kỳ resource nào khác.Code:pe_inst : entity work.pe port map ( clk => clk, a => filter_coeffs(0), bcin => data_in, bcout => breg(0), pcin => zero(preg(0)'range), pcout => preg(0) ); PE_X: for i in 1 to NUM_TAPS-1 generate pe_inst : entity work.pe port map ( clk => clk, a => filter_coeffs(i), bcin => breg(i-1), bcout => breg(i), pcin => preg(i-1), pcout => preg(i) ); end generate; data_out <= preg(NUM_TAPS-1);
Và maximum frequency sẽ vào khoảng 590 MHz trên một Virtex-5 speed grade -2 (Virtex-5 có 3 speed grades, -1, -2, và -3).Code:Slice Logic Utilization: Slice Logic Distribution: Number of LUT Flip Flop pairs used: 0 Number with an unused Flip Flop: 0 out of 0 Number with an unused LUT: 0 out of 0 Number of fully used LUT-FF pairs: 0 out of 0 Number of unique control sets: 0 IO Utilization: Number of IOs: 49 Number of bonded IOBs: 49 out of 480 10% Specific Feature Utilization: Number of BUFG/BUFGCTRLs: 1 out of 32 3% Number of DSP48Es: 21 out of 288 7%
Code:Timing Summary: --------------- Speed Grade: -2 Minimum period: 1.692ns (Maximum Frequency: 591.017MHz) Minimum input arrival time before clock: 1.190ns Maximum output required time after clock: 2.910ns Maximum combinational path delay: No path found
Comment
-
Processing element model, nếu bạn nhìn kỹ, là một partial model của DSP48 slice (hình đính kèm). Chúng ta vòng vo một chút để illustrate modeling technique, nhưng DSP48 là primitive mà bạn có thể instantiate directly. Đơn giản là một phần của DSP48 được design especially cho filter implementations.
Đương nhiên chúng ta có thể model với bất kỳ language nào, chẳng hạn như Java, C, hay SystemC. Lợi thế của Python hay Matlab hoặc các tool tương tự là các mathematical libraries. Chúng ta có thể dễ dàng so sánh outputs của model vs output của Python/Matlab functions, chẳng hạn như fft, qr, etc.Code:class PE () : def __init__(self) : self.leftCell = 0; self.a1 = 0; self.a2 = 0; self.b2 = 0; self.m = 0; self.p = 0; def simClkCycle (self, a1 = 0) : if (self.leftCell == 0) : self.p = self.m + 0; self.m = self.a2 * self.b2; self.a2 = self.a1; self.a1 = a1; else : self.p = self.m + self.leftCell.p; self.m = self.a2 * self.b2; self.a2 = self.a1; self.a1 = self.leftCell.a2;
FIR filter có thể là quá đơn giản để model, nhưng các algorithm với multi-dimension systolic array có lẽ sẽ interesting hơn. FIR thì vẫn còn serial và semi-parallel implementation. Chúc thành công.
Comment
-
Em kiếm được cái master thesis của bọn này triển khai FIR filter trên FPGA, show các bác xem thế nào ^^
Link download : http://hungnm.edu.vn/cupid1102/FIR_Filter_FPGA/Cupid1102 = Cupid độc nhất vô nhị
Comment
Bài viết mới nhất
Collapse
-
Trả lời cho Đấu tắt điện cho máy tính bảngbởi bqvietBqv cáo lỗi vì chưa đủ khả năng diễn giải để người đọc hiểu. Người làm kỹ thuật sâu đôi khi như thế đó. Về việc nạp pin không vào dù cell mới, khả năng cái mạch quản lý đó đã hỏng - cũng chính là nguyên nhân đám cell cũ hỏng từ đầu.
-
Channel: Thiết bị điện tử cá nhân
Hôm qua, 17:17 -
-
Trả lời cho Xin hỏi về mạch thu FM/AM trong catsettebởi nguyendinhvanTheo tôi, nó chỉ là cái Tuy- ê - nơ, hoặc là khối Trung Văn Tần, nó một phần trong cái Da đì ô thôi. Vì có thấy một chỗ có ba chân hàn, giiống như chân Cờ rít sờ tăng 455 ki nô hẹc. Còn khối Tuy ê nơ thì không nhìn thây cái Di ốt Va di cáp...
-
Channel: Điện thanh
05-12-2025, 19:59 -
-
Trả lời cho Đấu tắt điện cho máy tính bảngbởi afrendlyCó vẻ ngoài hiểu biết của mình rồi. Cuối cùng mình quyết định tìm mua 2 pin trên Shopee, giá 200K thay vào. Tuy nhận pin được 1%, sạc mãi không vào nhưng cũng mở được máy lên. Vậy cũng tạm. Cảm ơn bạn đã hỗ trợ nhé....
-
Channel: Thiết bị điện tử cá nhân
04-12-2025, 01:27 -
-
Trả lời cho Máy điện châm ?bởi nick22Đúng như bạn nói, máy điện châm hiện nay trên thị trường đã khá đa dạng về mẫu mã, chức năng và giá thành.
-
Channel: Điện tử y sinh
01-12-2025, 13:23 -
-
Trả lời cho Làm thế nào để check IC LM358bởi thetungĐể check IC sống hay chết thì đơn giản : bạn lắp cái mạch ( khuếch đại hoặc dao động ) chạy bằng con IC đó ,nhưng vị trí IC thì lắp cái đế .... thế là cứ cắm rút thì biết . Còn không thì kiếm cái này : https://shopee.vn/Xu-M%C3%A1y-ki%E1%...di-%C4%91%E1%B...
-
Channel: Hướng dẫn tìm thông tin linh kiện
28-11-2025, 14:34 -
-
bởi ngochung90Tình hình là em có mua mạch 3s về để hàn vào khối pin 12v, hàn xong em đo tại các chân từ B-, B1, B2, B+ thì điện áp pin vẫn đủ 12,6v, nhưng tại 2 chân ra P- P+ thì đo chỉ được 6,3v là bị sao các bác, và chân P- P + này đồng thời là chân sạc xả thì mình cắm sạc xả cùng lúc được ko ạ
...-
Channel: Điện tử dành cho người mới bắt đầu
28-11-2025, 10:32 -
-
Trả lời cho Làm thế nào để check IC LM358bởi nguyendinhvanViệc đó tùy thuộc trình độ khoa học kỹ thuật công nghệ ứng dụng hiện tại thôi.
Trong datasheet,họ đưa ra nhiều thông số. Tùy theo khả năng , và những thông số họ cần, họ sẽ kiểm tra casc số đo có khớp với số liệu trong datasheet...-
Channel: Hướng dẫn tìm thông tin linh kiện
27-11-2025, 18:00 -
-
bởi kqbn9091Em có mạch AT89s8253 đang cần sửa số serial no của CHIP mà giờ lâu quá rồi không dùng keil nên không biết phải làm sao, trong khi chỉ còn file hex. Mạch nạp thì progris khi viết không sửa được số serial của IC. Rất cần bác nào còn làm về 89...
-
Channel: Vi điều khiển họ 8051
27-11-2025, 11:13 -
...

Comment