2012-01-31 42 views
7

Tôi có một vấn đề nhỏ với mã sau VHDL:VHDL lái xe tín hiệu từ các quá trình khác nhau

process (zbroji) 
begin 
    if rising_edge(zbroji) then 
     oduzima <= '0'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 
end process; 

process (oduzmi) 
begin 
    if rising_edge(oduzmi) then 
     oduzima <= '1'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 

end process; 

Vấn đề là tín hiệu ucitanPrvi luôn luôn có giá trị X. Nếu tôi không cố gắng thiết lập giá trị của nó trong hai quá trình , sau đó tôi không có bất kỳ vấn đề ... Vì vậy, tôi biết rằng tôi không phải lái xe một tín hiệu từ nhiều quá trình, nhưng tôi không biết làm thế nào để viết khác ... Có ai có một ý tưởng làm thế nào tôi có thể giải quyết vấn đề này?

Cảm ơn!

EDIT: Cảm ơn tất cả các bạn đã trả lời :) Bây giờ tôi hiểu tại sao tôi không thể lái một tín hiệu từ nhiều quá trình (ít nhất theo cách tôi muốn nó hoạt động).

+0

Đồng hồ odzumi và zbroji hay chỉ là tín hiệu? –

+0

Chúng chỉ là tín hiệu – xx77aBs

Trả lời

5

Nếu bạn muốn tổng hợp thiết kế của bạn cho một FPGA thực hoặc ASIC, bạn sẽ phải suy nghĩ của VHDL về phần cứng thực sự (dây, flip flops, cửa, vv) Ngoài ra, nếu bạn muốn thực hiện một phát triển cạnh thực sự tăng trong phần cứng , bạn sẽ cần một đồng hồ hệ thống mà ổ đĩa flip flop.Với mẫu mã ban đầu của bạn, nó không có vẻ là zbroji hoặc oduzmi là đồng hồ hệ thống, nhưng chỉ std_logic tín hiệu.Tôi đã viết ví dụ mã này giả định chức năng cơ bản từ ví dụ của bạn, hy vọng , bạn có thể lấy mã và nhận xét của tôi và hoàn thành những gì bạn cần.

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity example is 
    port (Reset  : in std_logic; 
     SysClk  : in std_logic; 
     zbroji  : in std_logic; 
     oduzmi  : in std_logic; 
     ulaz_broj : in std_logic; 
     oduzima : out std_logic; 
     ucitanPrvi : out std_logic; 
     broj1  : out std_logic 
     ); 

end example; 

architecture Behavioral of example is 

    -- Delayed version of input signals (1 clock cycle delay) 
    signal zbroji_d : std_logic; 
    signal oduzmi_d : std_logic; 

    signal zbrojiRE : std_logic; 
    signal oduzmiRE : std_logic; 

begin 

    -- Generate 1 clock cycle delayed version of 
    -- signals we want to detect the rising edge 
    -- Assumes active high reset 
    -- Note: You should only use the rising_edge macro 
    -- on an actual global or regional clock signal. FPGA's and 
    -- ASICs place timing constraints on defined clock signals 
    -- that make it possible to use rising_edge, otherwise, we have 
    -- to generate our own rising edge signals by comparing delayed 
    -- versions of a signal with the current signal. 
    -- Also, with any respectable synthesizer/simulator using 
    -- rising_edge is almos exactly the same as (clk'event and clk='1') 
    -- except rising_edge only returns a '1' when the clock makes a 
    -- valid '0' to '1' transition. (see link below) 
    EdgeDetectProc : process (Reset, SysClk) 
    begin 
    if Reset = '1' then 
     zbroji_d <= '0'; 
     oduzmi_d <= '0'; 
    elsif rising_edge(SysClk) then 
     zbroji_d <= zbroji; 
     oduzmi_d <= oduzmi; 
    end if; 
    end process EdgeDetectProc; 

    -- Assert risinge edge signals for one clock cycle 
    zbrojiRE <= '1' when zbroji = '1' and zbroji_d = '0' else '0'; 
    oduzmiRE <= '1' when oduzmi = '1' and oduzmi_d = '0' else '0'; 

    -- Assumes that you want a single cycle pulse on ucitanPrvi on the 
    -- rising edege of zbroji or oduzmi; 
    ucitanPrvi <= zbrojiRE or oduzmiRE; 

    -- Based on your example, I can't tell what you want to do with the 
    -- broj1 signal, but this logic will drive broj1 with ulaz_broj on 
    -- either the zbroji or oduzmi rising edge, otherwise '0'. 
    broj1 <= ulaz_broj when zbrojiRE = '1' else 
      ulaz_broj when oduzmiRE = '1' else 
      '0'; 

    -- Finally, it looks like you want to clear oduzima on the rising 
    -- edge of zbroji and assert oduzima on the rising edge of 
    -- oduzmi 
    LatchProc : process (Reset, SysClk) 
    begin 
    if Reset = '1' then 
     oduzima <= '0'; 
    elsif rising_edge(SysClk) then 
     if zbrojiRE = '1' then 
     oduzima <= '0'; 
     elsif oduzmiRE = '1' then 
     oduzima <= '1'; 
     end if; 
    end if; 
    end process LatchProc; 

end Behavioral; 

Mã trước giả sử bạn có đồng hồ hệ thống. Trong một mô phỏng như ModelSim (miễn phí phiên bản sinh viên), bạn có thể tạo ra một chiếc đồng hồ 100 MHz với mã testbench phi synthesizable như thế này ...

ClockProc : process 
begin 
    SysClk <= '0'; 
    wait for 5 ns; 
    SysClk <= '1'; 
    wait for 5 ns; 
end process ClockProc; 

trong một FPGA/ASIC thực hiện thực tế, có thể bạn sẽ muốn sử dụng một bộ dao động bên ngoài mà bạn chạy vào chip của bạn, đưa tín hiệu vào DCM (Trình quản lý đồng hồ kỹ thuật số), sẽ tạo ra một tín hiệu đồng hồ rất sạch sẽ cho tất cả logic VHDL của bạn, vì vậy bạn có thể có một thiết kế miễn phí.

Và cuối cùng, đây là một lời giải thích rất lớn về sự khác biệt giữa rising_edge và (clk'event và CLK = '1')

http://vhdlguru.blogspot.com/2010/04/difference-between-risingedgeclk-and.html

Hy vọng rằng sẽ giúp.

+0

Wow, cảm ơn ví dụ chi tiết :) – xx77aBs

3

Nếu bạn lái xe một tín hiệu std_logic từ nhiều quá trình (và nhớ rằng việc gán liên tục bên ngoài quá trình cũng tạo ra một quá trình ngụ ý!) Thì tất cả nhưng một trong số chúng phải lái xe Z lên tín hiệu. Để xấp xỉ đầu tiên, hàm phân giải (quyết định giá trị cuối cùng sẽ là gì) sẽ tạo ra X s trừ khi điều này xảy ra.

Tôi không chắc chắn cách tốt nhất để thay đổi mã của bạn - bạn cần quyết định khi nào một quá trình cụ thể cần không lái xe và đưa nó vào Z tại thời điểm đó.


Định nghĩa đầy đủ về cách thức nhiều trình điều khiển được giải quyết được định nghĩa trong gói ieee.std_logic_1164 và bao gồm tất cả các khả năng, chẳng hạn như một 1 và một L lái xe vv IEEE được nổi giận về bản quyền, vì vậy tôi m sẽ không đăng ngay cả một đoạn trích ở đây, nhưng bạn sẽ có thể tìm thấy nó trong thư viện nguồn của trình mô phỏng của bạn.

2

Tín hiệu lái xe từ nhiều quy trình là một ý tưởng tồi trừ khi bạn thực sự biết bạn đang làm gì. Bạn có thể viết lại mã này trong một quá trình như thế này.

process (zbroji, oduzmi) 
begin 
    if rising_edge(zbroji) then 
     oduzima <= '0'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 
    if rising_edge(oduzmi) then 
     oduzima <= '1'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 
end process; 

Lưu ý rằng nếu bạn làm điều này, và bạn sẽ có được một lợi thế cạnh tăng trên cả hai zbroji & oduzmi sau đó oduzima sẽ nhận được giá trị 1 khi nó xảy ra cuối cùng trong quá trình này. Trước khi bạn đã cố gắng đặt nó thành 01 cùng một lúc. Điều đó sẽ mô phỏng thành X và có thể sẽ không tổng hợp. Nếu nó đã tổng hợp bạn sẽ được kết nối điện và mặt đất với nhau trong một thiết kế CMOS.


Phương pháp thay thế là có mỗi quá trình điều khiển phiên bản riêng của tín hiệu và giải quyết chúng bên ngoài với chức năng bạn muốn (hoặc một quy trình khác). Trong trường hợp này tôi đã sử dụng or:

process (zbroji) 
begin 
    if rising_edge(zbroji) then 
     ucitanPrvi_1 <= '1'; 
    end if; 
end process; 

process (oduzmi) 
begin 
    if rising_edge(oduzmi) then 
     ucitanPrvi_2 <= '1'; 
    end if; 

end process; 

ucitanPrvi <= ucitanPrvi_1 or ucitanPrvi_2; 
+0

Trừ khi zbroji và oduzmi là đồng hồ, tôi sẽ không sử dụng câu lệnh rising_edge. Tôi nghĩ phương pháp thay thế là tốt hơn trong hai phương pháp bạn đã đề xuất. –

+0

Câu lệnh tăng cạnh đến từ mã gốc. Tôi sẽ không sử dụng nó. –

1

Trừ zbroji và oduzmi là đồng hồ riêng biệt này là thực hiện đề nghị của tôi

này đăng ký các zbroji và oduzmi và kiểm tra nếu giá trị trong thanh ghi là trái ngược với bản gốc tín hiệu. Điều này chỉ xảy ra khi zbroji/oduzmi đi từ 0 đến 1 và thanh ghi chưa cập nhật thay đổi tín hiệu.

process (clk) 
begin 
    if rising_edge(clk) then 
     if zbroji = '1' and zbroji_old = '0' then 
      oduzima <= '0'; 
      ucitanPrvi <= '1'; 
      broj1 <= ulaz_broj; 
     elif oduzmi = '1' and oduzmi_old = '0' then 
      oduzima <= '1'; 
      ucitanPrvi <= '1'; 
      broj1 <= ulaz_broj; 
     end if; 
     zbroji_old <= zbroji; 
     oduzmi_old <= oduzmi; 
    end if; 
end process; 

Dường như ucitanPrvi và broj1 luôn giống nhau. Hoặc là tín hiệu vô dụng, đây là orignally một lỗi đánh máy hoặc bạn đang tạo "cập nhật" xung trong trường hợp bạn cần báo cáo kết quả

ucitanPrvi <= '0' 
    broj1 <= (others=>'0') -- assumed reset? 

sau if (rising_edge (CLK) tuyên bố

0

Khi bạn thay đổi cùng một giá trị tín hiệu từ nhiều quá trình, trình mô phỏng sẽ tạo nhiều trình điều khiển tín hiệu cho điều này. Đầu ra của chúng về cơ bản sẽ không được giải quyết. Hãy nghĩ về nó như là đầu ra của nhiều cổng kết nối với nhau, bạn mong đợi điều gì?

Để khắc phục điều này, những gì bạn cần thực hiện là chức năng phân giải, điều khiển đầu ra để báo hiệu.

http://www.csee.umbc.edu/portal/help/VHDL/misc.html#resf

Nếu bạn có bất kỳ nghi ngờ nào, hãy cho tôi biết.

Các vấn đề liên quan