【问题标题】:VHDL Does my code works on a FPGA?VHDL 我的代码可以在 FPGA 上运行吗?
【发布时间】:2016-05-05 14:05:40
【问题描述】:

我最近几乎完成了我的项目(我需要创建分频器(50MHZ->1HZ(1s))并完成 7 段显示解码器)。我的项目包含一个计时器(倒计时到 00:00 触发警报,如果当前状态为 00:00 则向上计数)。该项目在 Active HDL Simulator 上运行良好,但我不知道它是否适用于 FPGA。我使用行为方法使用 1 个进程编写了代码。我的问题是:如果我完成分频器,我的代码是否可以在 FPGA 上运行?如果没有,我该如何修改代码才能工作?

我的代码:

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;
use IEEE.STD_LOGIC_arith.all;

entity Timer is
    port(start_stop,M,S : in std_logic; --Start/Stop , Minutes,Seconds
    clk : in std_logic; -- clock 1 MHz
    alarm : out std_logic; -- alarm/buzzer
    s1,s2,m1,m2 : inout std_logic_vector(6 downto 0)); --BCD to 7segment display representation for seconds and minutes
end Timer;
--}} End of automatically maintained section

architecture Timer of Timer is
signal sec1,sec2,min1,min2 : std_logic_vector(3 downto 0);
signal T : std_logic := '0';    
signal done : std_logic;  
signal cu : std_logic;
component seg7 is
    port(bcd : in std_logic_vector(3 downto 0);
    output : out std_logic_vector(6 downto 0)
    );
end component;

begin   
P0 : process(clk,start_stop,M,S)
variable temp1,temp2,temp3,temp4 : std_logic_vector(3 downto 0);
variable carry_s,carry_m : std_logic;   
variable alarm_counter : std_logic_vector(3 downto 0) := "1111"; -- buzzer/alarm counter
begin                             
    if(M = '1'and S = '1' and start_stop = '0') 
    then
    temp1 := "0000";
    temp2 := "0000";
    temp3 := "0000";
    temp4 := "0000";
    sec1 <= temp1;
    sec2 <= temp2;  
    min1 <= temp3;
    min2 <= temp4;
    alarm <= '0'; 
    done <= '0';
    T <= '0';--RESET when you press M and S 
    elsif(M = '0' and S = '1' and start_stop = '0')
        then 
        temp1 := temp1 + "0001";
        if(temp1 = "1010")
            then
            temp1 := "0000";
            carry_s := '1';
        else
            carry_s := '0';
        end if;
        if(carry_s = '1')
            then
            temp2 := temp2 + "0001";
            if(temp2 = "0110")
                then
                temp2 := "0000";
                carry_s := '0';
            end if;
        end if;
        sec1 <= temp1;
        sec2 <= temp2;-- Increment seconds when you press M 
    elsif(M = '1' and S = '0' and start_stop = '0')
        then 
        temp3 := temp3 + "0001";
        if(temp3 = "1010")
            then
            temp3 := "0000";
            carry_m := '1';
        else
            carry_m := '0';
        end if;
        if(carry_m = '1')
            then
            temp4 := temp4 + "0001";
            if(temp4 = "1010")
                then
                temp4 := "0000";
                carry_m := '0';
            end if;
        end if;
        min1 <= temp3;
        min2 <= temp4;-- Increment minutes when you press M  
    elsif(S = '0' and M = '0' and start_stop = '1')
        then
        alarm <= '0';
        T <= T xor '1';-- T Flip Flop behaviour 
        if(sec1 /= "0000" or sec2 /= "0000" or min1 /= "0000" or min2 /= "0000")
        then
        cu <= '0';
    else
        cu <= '1';
        end if; -- counting directions
    elsif(T = '1' and RISING_EDGE(clk))
        then  
        if(cu = '0')
            then
            done <= '0';
            temp1 := temp1 - "0001";
            if(temp1 = "1111")
                then
                temp2 := temp2 - "0001";
                temp1 := "1001";
            end if;
            if(temp2 = "1111")
                then
                temp2 := "0101";
                carry_s := '1';
            else
                carry_s := '0';
            end if;
            if(carry_s = '1')
                then
                temp3 := temp3 - "0001";
                if(temp3 = "1111")
                    then
                    temp4 := temp4 - "0001";
                    temp3 := "1001";
                end if;
            end if;
            if(temp1 = "0000" and temp2 = "0000" and temp3 = "0000" and temp4 = "0000")
                then
                done <= '1';
            end if;
            sec1 <= temp1;
            sec2 <= temp2;   
            min1 <= temp3;
            min2 <= temp4;-- counting down
        else
            temp1 := temp1 + "0001";
            if(temp1 = "1010")
                then
                temp1 := "0000";
                temp2 := temp2 + "0001";
            end if;
            if(temp2 = "0110")
                then
                temp2 := "0000";
                carry_s := '1';
            else
                carry_s := '0';
            end if;        
            if(carry_s = '1')
                then
                temp3 := temp3 + "0001";
                if(temp3 = "1010")
                    then
                    temp3 := "0000";
                    temp4 := temp4 + "0001";
                    if(temp4 = "1010")
                        then
                        temp4 := "0000";
                        T <= '0';
                        end if;
                    end if;
                end if;
            sec1 <= temp1;
            sec2 <= temp2;   
            min1 <= temp3;
            min2 <= temp4;-- counting up
        end if; 

     end if;

       if(done = '1')
            then  
            T <= '0'; 
            alarm_counter := alarm_counter - "0001";
            alarm <= '1'; 
            if(alarm_counter = "0000")
                then
                done <= '0';
                alarm <= '0';
                end if;
        else
            alarm_counter := "1111";
            alarm <= '0';
        end if;-- when the alarm starts 

end process P0;

C1 : seg7 port map (sec1,s1);
C2 : seg7 port map (sec2,s2);
C3 : seg7 port map (min1,m1);
C4 : seg7 port map (min2,m2);
-- seven segment display port mapping
end Timer;

编辑:我修复了代码

【问题讨论】:

  • @PlayDough:这个问题与另一个问题的端口映射无关。是的,它们出自同一作者,代码大致相同,但这并不会使它们重复。
  • @BenVoigt 我不同意。另一个确实提到了端口映射,但最终这个问题与它无关,因为a)它从未询问任何关于端口映射的具体内容(只是一个模糊的“[h]如何使用端口映射”)和b)它结束了提出一个关于它是否具有功能性和可合成性的问题。这个问题本质上是同一个问题。

标签: vhdl fpga hardware-programming


【解决方案1】:

不,该设计不可合成。

特别是,您在这里有异步反馈:

if(M = '0' and S = '1')
    then 
    temp1 := temp1 + "0001";

所有计数逻辑都必须有时钟。在模拟器中,进程上的敏感度列表可以防止这种反馈失控,但在实际硬件中,异步循环会发疯。

尝试改用这个结构:

if (M = '1' and S = '1') then
    -- async reset
elsif RISING_EDGE(clk) then
    --all other logic for setting modes, counting, limits goes here
endif

RISING_EDGE 函数与clk = '1' and clk'event 大致相同,只是它对于查看代码的人来说更有意义,并且具有a few more advantages

【讨论】:

  • 如果我解决这个问题可以在 FPGA 上实现吗?
  • 在 FPGA 中构建如此复杂的闹钟是完全可行的,是的。
  • 我不会对此感到满意:if (M = '1' and S = '1') then。从我通过简要阅读代码可以理解的情况来看,MS 是功能输入(“分钟”和“秒”)。功能逻辑不应该控制异步复位;唯一应该驱动异步复位的信号是专用复位信号,其唯一功能是将芯片置于已知状态。使用任何其他信号驱动异步复位都不是同步设计
  • 如果我同时按 M 和 S ,计时器将重置为 00:00 。我是否需要一个信号reset 当 M = 1 和 S = 1 时 reset = '1' 并重置计时器?
  • @CălinCalin:VHDL 分析仪足够智能,可以创建中间信号areset = (M and S),您无需明确执行此操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-11
  • 1970-01-01
  • 2023-01-07
  • 1970-01-01
  • 2016-09-22
  • 2011-03-19
相关资源
最近更新 更多