Thông báo

Collapse
No announcement yet.

[VHDL] Xử lý ảnh

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • [VHDL] Xử lý ảnh

    Tình hình là do mình đang làm luận văn về xử lý ảnh nên chắc sẽ hỏi nhiều ở đây. Hôm nay là vấn đề đầu tiên gặp phải >"<. Mình đang thiết kế khối tách 3 phần R G B ( mỗi phần 8 bits) của từng pixels riêng, data vào đọc từ SRAm 256K x 16 bits nên sẽ có 16 bits, và cũng do 16bits lẻ nên phải đọc 1 lúc 2 điểm ảnh rồi mới tách, chân add_read gửi đến SRAM địa chỉ đọc và lấy data về chân indata. Module mình sẽ có các port như vầy
    Code:
    entity Color_split is port
    
     (	CK: in std_logic;
    	indata: in std_logic_vector ( 15 downto 0);
    	g1: out std_logic_vector (7 downto 0);
    	b1: out std_logic_vector (7 downto 0);
    	r1: out std_logic_vector (7 downto 0);
    	g2: out std_logic_vector (7 downto 0);
    	b2: out std_logic_vector (7 downto 0);
    	r2: out std_logic_vector (7 downto 0);
    	add_read: out std_logic_vector ( 17 downto 0);
    	CEn: out std_logic);
    	
    end Color_split;
    1 hình 180 * 180 * 3 bytes = 97200 bytes, mỗi lần đọc 2 điểm ảnh tương đương 6 bytes, do đó cần đọc 16200 lần, đọc xong sẽ bỏ chân CEn để ngưng đọc. Như vậy indata đủ 6bytes thì sẽ tách.

    Code:
    Library ieee;
    Use ieee.std_logic_1164.all;
    Use ieee.std_logic_arith.all;
    Use ieee.std_logic_unsigned.all;
    USE WORK.MATH.ALL;
    entity Color_split is port
    
     (	CK: in std_logic;
    	indata: in std_logic_vector ( 15 downto 0);
    	g1: out std_logic_vector (7 downto 0);
    	b1: out std_logic_vector (7 downto 0);
    	r1: out std_logic_vector (7 downto 0);
    	g2: out std_logic_vector (7 downto 0);
    	b2: out std_logic_vector (7 downto 0);
    	r2: out std_logic_vector (7 downto 0);
    	add_read: out std_logic_vector ( 17 downto 0);
    	CEn: out std_logic);
    	
    end Color_split;
    
    architecture behav of Color_split is
    
    signal x: integer;
    signal i: integer;    
    signal data1: std_logic_vector  ( 15 downto 0);
    signal data2: std_logic_vector  ( 15 downto 0);
    signal data3: std_logic_vector  ( 15 downto 0);
    
    begin
    	process (CK) 
    	begin
    		if rising_edge (CK) then
    		i <= 0;
    		x<= 3*i;
    		if ( x < 16200) then 
    			CEn <= '0';
    			add_read <=(x + 0);
    			data1 <= indata;
    			add_read <=(x + 1 );
    			data2 <= indata;
    			add_read <=(x + 2 );
    			data3 <= indata;
    			b1 <= data1 ( 15 downto 8);
    			g1 <= data1 ( 7 downto 0);
    			r1 <= data2 ( 15 downto 8);
    			b2 <= data2 ( 7 downto 0);
    			g2 <= data3 ( 15 downto 8);
    			r2 <= data3 ( 7 downto 0);
    			i <= i + 1;
    		else CEn <= '1';	
    		end if;
    		end if;
    
    	end process;
    
    end behav;
    Và... ai thấy code sai ở đâu chỉ dùm mình ^^". Các phép toán + * integer gán vào sstd_logic mình đã viết riêng 1 package, nên các bạn đừng thắc mắc, code không báo lỗi, chỉ có mô phỏng ra sai thôi, có lẽ hiểu sai vấn đề >"< . Theo như code thì address mặc định từ ) và sẽ tăng lên từ từ, nhưng address mình o tăng, các chân R G B cũng không đúng luôn T.T

  • #2
    À, nếu các bạn muốn xem cả phần package mình viết thì cứ nói, mình sẽ post tiếp, trong đó có giải thuật chuyển từ Binary thành integer cũng rất hay, bạn nào thích cứ liên hệ mình ^^". Thx

    Comment


    • #3
      Cậu viết code rất mềm! Chắc là học bên CNTT mới chuyển sang nghiên cứu FPGA?

      Có quá nhiều lỗi dùng signal với thiết kế này ( dù ko sai về cú pháp VHDL ). Cậu cần đọc lại về SIGNAL và VARIABLE. Viết như thế này thì data1=data2=data3 hết. Add cũng ko như cậu mong muốn đc. Chưa kể đến việc cậu ko tính toán tới timing của SRAM nữa.

      Comment


      • #4
        ^^", viết code rất mềm là sao, khen hay chê zậy. Bik là sai chỗ đó rồi, nhưng
        phải sửa sao NEO, cho dù là varỉable thì gán zậy hình như cũng bị lỗi y chang >"<
        Last edited by Milano; 26-03-2009, 23:36.

        Comment


        • #5
          Cái này cậu phải đọc kỹ về process, signal đã. Cái chính ở đây là việc cậu chưa nắm rõ về những thứ này.

          Cậu cứ đọc để phân biệt được VHDL là ngôn ngữ mô tả phần cứng chứ không phải ngôn ngữ lập trình phần mềm cái đã.

          Còn về lỗi của cậu, cụ thể hơn thế này:
          - Về mặt logic khi được synthesize thì signal nó chỉ được cập nhật sau khi chạy hết toàn bộ process. Vì thế nó chỉ nhận lệnh gán cuối cùng,
          vd: addr=x+2 nếu x<16200 còn ko thì ko đổi giá trị.

          - Hơn nữa, cả cái process của cậu chỉ thực hiện trong 1 chu kỳ clock mà thôi. Đấy là sự khác biệt giữa VHDL và C hay Java. Thế nên indata của cậu thực ra chỉ mang 1 giá trị.

          - Về SRAM timing, cái này còn phụ thuộc và cái SRAM interface của cậu để trễ bao nhiêu ( tương ứng với tần số hoạt động bao nhiêu vì thường SRAM ngoài là asynchronous ). Nhưng dù trễ bao nhiêu thì khi cậu để CE_n='0' và cập nhật addr mới thì chu kỳ sau cậu mới chốt được dữ liệu đúng.

          PS: tóm lại cậu cứ bình tĩnh, đọc kỹ để hiểu về VHDL và FPGA đã.
          Last edited by NEO3F; 27-03-2009, 13:56.

          Comment


          • #6
            Code:
            if rising_edge (CK) then
            		i <= 0;
            nếu làm vậy thì khi có xung clk lên thì i lại về 0 => x luôn là 0 khi có xung clk, như vậy thì address của bác ko tăng nồi là đúng rùi.
            Còn về vấn đề signal với variable thì nó khác nhau ở chỗ thời điểm cập nhật, signal chỉ được gán khi ra khỏi process, còn variable thì trong process cũng dc. Ví dụ như sau:
            Code:
            architecture bhv of test is 
            	signal tmp:integer range 0 to 15;
            begin
            	process(clk)
            		--variable tmp:integer range 0 to 15;
            	begin
            		if clk='1' and clk'event then
            			tmp<=1;
            			output<=conv_std_logic_vector(tmp,8);
            			tmp<=2;
            		end if;
            	end process;
            end bhv;
            thì mô phỏng sẽ cho output là 2, còn nếu dùng variable:
            Code:
            architecture bhv of test is 
            	--signal tmp:integer range 0 to 15;
            begin
            	process(clk)
            		variable tmp:integer range 0 to 15;
            	begin
            		if clk='1' and clk'event then
            			tmp:=1;
            			output<=conv_std_logic_vector(tmp,8);
            			tmp:=2;
            		end if;
            	end process;
            end bhv;
            thì cho mô phỏng output là 1.
            Đó là sự khác nhau đó,ngoài ra còn một số vần đề như khi nào thì một biến hay một signal sẽ sinh ra FF, khi nào ko, bác tìm hiểu thêm nha.
            Chuyện nhỏ như con thỏ,bắt thỏ mới là chuyện lớn!!!

            Comment


            • #7
              Code:
              if rising_edge (CK) then
              		i <= 0;
              Chỗ này sáng nay mình mới thấy, đã sửa rồi, đem ra ngoài luôn, nhưng chưa nghĩ ra làm sao gán ra như ý muốn, nên mặc dù addr đã tăng, nhưng tăng 3 lần 2--5--8--B--E...( cùng 1 lỗi sai như data )

              @both: thx 2 bạn nhiều, mình đang coi lại về vấn đề signal và varỉable, 2 bạn có góp ý gì về giải thuật chỗ này cứ send lên đây. Nói thiệt là trong trường giờ toàn verilog, kiếm 1 người biết viết VHDL để hỏi cũng khó

              Comment


              • #8
                À, mình đã test khá nhiều về vaỉable và signal, nói chung là những code nhỏ nhỏ thì hok có gì, nhưng sửa vào code của mình thì có chỗ vẫn hok hiểu, 2 bạn giải thích dùm
                Code:
                architecture behav of Color_split is
                
                 signal temp: std_logic_vector ( 17 downto 0);
                 
                begin
                	process (CK) 
                variable x: integer;
                variable i: integer:=0;   
                variable data1: std_logic_vector  ( 15 downto 0);
                variable data2: std_logic_vector  ( 15 downto 0);
                variable data3: std_logic_vector  ( 15 downto 0);
                
                	begin
                
                		if rising_edge (CK) then
                
                		x:= 3*i;
                		if ( x < 16200) then 
                			CEn <= '0';
                			temp<=(x + 0);
                			temp <= temp +1;
                			data1 := indata;
                			temp <= temp +1;
                			add_read<= temp;
                			data2 := indata;
                			temp <= temp +1;
                			add_read<= temp;
                			data3 := indata;
                			b1 <= data1 ( 15 downto 8);
                			g1 <= data1 ( 7 downto 0);
                			r1 <= data2 ( 15 downto 8);
                			b2 <= data2 ( 7 downto 0);
                			g2 <= data3 ( 15 downto 8);
                			r2 <= data3 ( 7 downto 0);
                			i := i + 1;
                		else CEn <= '1';	
                		end if;
                		end if;
                
                	end process;
                
                end behav;
                Mình đã sửa lại 1 chút như vầy, address tăng đúng rồi, data thì chưa sửa, nhưng theo 2 bạn nói thì signal chỉ cập nhật sau khi hết process, trong code có đoạn
                Code:
                			data1 := indata;
                			temp <= temp +1;
                			add_read<= temp;
                			data2 := indata;
                			temp <= temp +1;
                			add_read<= temp;
                Như vậy có phải add_read chỉ nhận giá trị sau khi temp đã tăng 2 lần không, nếu vậy sao address lại tăng đúng ( bây giờ đúng cũng phải hỏi >"<)

                Comment


                • #9
                  Vấn đề là ko phải cứ có lệnh tăng (temp<=temp+1) là nó tăng.Ở trên em nói còn thiếu.Thật ra thì trình tổng hợp sẽ đọc hết process rùi nó chỉ tổng hợp câu gán cuối cùng của signal thui, tức là câu tăng temp sau cùng í.Vậy thì nó chỉ tăng một lần thui mà.Rắc rối quá nhỉ,tùy trườgn hợp mà code thôi,cái này em cũng chưa rành lắm.
                  Chuyện nhỏ như con thỏ,bắt thỏ mới là chuyện lớn!!!

                  Comment


                  • #10
                    Oh` nhỉ , temp nó cũng là 1 signal mà quên mất >"<. Vậy có nghĩ là Mila viết zầy không có nghĩ là nó đọc data của từng address đúng hok
                    Code:
                    			temp <= temp +1;
                    			add_read<= temp;
                    			data2 := indata;
                    
                    			temp <= temp +1;
                    			add_read<= temp;
                    			data3 := indata;
                    temp lần đầu chưa tăng, có nghĩ là RAM chưa tăng địa chỉ, --> chưa đọc được data mới >"<

                    Comment


                    • #11
                      uh,đúng rùi đó bác,mặc dù em chẳng biết đúng chỗ nào . Em chưa có kit nên học chay thui,chán chết.Nhưng mà em nghĩ nếu làm xử lý ảnh thì fải xài micro blaze zì đó chứ,cứ VHDL chay thì mệt lắm.
                      Chuyện nhỏ như con thỏ,bắt thỏ mới là chuyện lớn!!!

                      Comment


                      • #12
                        Uh, đúng ra là làm Nios. Nhưng mà giờ thầy giao zầy rồi, phải ráng chứ sao giờ, cũng không phải là hấp tấp gì, nhưng mà nghĩ hok ra sợ làm o kịp >"<

                        Comment


                        • #13
                          Nhiệm vụ của cậu là j? Nếu chỉ là tách tín hiệu R,G,B thì cứ từ từ thôi.

                          PS: Cái của cậu nên dùng FSM. Đọc thử xem, cậu sẽ thấy rõ ngay.

                          Comment


                          • #14
                            À, yêu cầu luận văn là xử lý ảnh, đọc hình từ SRAM, lọc màu (vd như mình muốn giữ màu đỏ lại chẳng hạn, thì các màu khác sẽ xử lý xám hay trắng hết), xuất VGA. Bây giờ mình chỉ thử xuất thẳng tấm hình ra VGA thôi mà chưa được, đọc sơ thấy xuất VGA phải có 3 tín hiệu RGB nên mình mới phải tách.

                            Comment


                            • #15
                              Mình cũng không rõ yêu cầu luận văn thực tế của bạn là gì .
                              Nhưng nếu là xuất dữ liệu ra VGA thì trước tiên bạn cần có module tạo ra các tín hiệu đồng bộ VS, HS cũng như các tín hiệu định thời pixel_count, line_count (xác định vị trí điểm ảnh trên màn hình) theo chuẩn VGA. Việc xuất dữ liệu R, G, B sẽ dựa theo các tín hiệu trên.
                              Còn việc đọc SRAM, mình nghĩ có lẽ không khó lắm, bạn chỉ cần thay đổi cách tư duy lập trình từ phần mềm sang phần cứng (đọc kỹ tài liệu một chút là được ). Không rõ là bạn sử dụng RAM ngoài hay tự tạo ra RAM bên trong board FPGA. Nếu không bắt buộc dùng RAM ngoài thì mình nghĩ bạn nên tự tạo ra RAM 24 bits (8 bits R + 8 bits G + 8 bits B) bên trong FPGA để tiện cho việc lưu giữ và truy xuất dữ liệu màu R, G, B.

                              Mình cũng mới làm việc với FPGA nên có nhiều thứ không rõ lắm. Hơn nữa mình hiện cũng chỉ viết code Verilog chứ không dùng VHDL như bạn (mình nghĩ cái này chỉ là sự khác biệt về ngôn ngữ thôi chứ cách tư duy thì không khác mấy, ít nhất là khi thiết kế vẫn còn chưa phức tạp). Có gì không đúng mong bạn thông cảm.

                              Good luck!

                              Comment

                              Về tác giả

                              Collapse

                              Milano Tìm hiểu thêm về Milano

                              Bài viết mới nhất

                              Collapse

                              Đang tải...
                              X