在VHDL中执行顺序语句以进行综合

时间:2013-11-13 17:13:24

标签: vhdl sequential synthesis

所以这就是问题所在。我已经为二进制分频器编写了代码,该分频器应该输出7位7段显示二进制代码以进入8 x 7段显示。 (2个7股分红,除数,商,余数各自和按此顺序)。我的开发板上的这个8 x 7段显示器有一个7位输入(a到g)和一个3位选择。 所以基本的想法是我必须按顺序,连续和足够快地输出被除数,除数,商和余数,这样对于人眼来说输出看起来是恒定的,尽管八个7段中的每一个都是逐个启用的。根据我的输出。 最初,分频器以二进制形式给出所有输出(被除数,除数,商,余数),然后通过函数将其转换为8位bcd,然后bcd数被另一个函数分解为两个4位bcd数(现在我有8个输出变量:2表示被除数,2表示除数等。)这些4位数由另一个函数转换为7段。

以下是完整代码:

library IEEE; 
use IEEE.STD_LOGIC_1164.all; 
use IEEE.STD_LOGIC_UNSIGNED.all;  
use IEEE.STD_LOGIC_ARITH.all; 

entity division is  
    generic(SIZE: INTEGER := 8); 
    port(reset: in STD_LOGIC;                           --reset
        en: in STD_LOGIC;                               --enable
        clk: in STD_LOGIC;                              --clock

        num: in STD_LOGIC_VECTOR((SIZE - 1) downto 0);  --dividend
        den: in STD_LOGIC_VECTOR((SIZE - 1) downto 0);  --divisor

          whatgoes:out STD_LOGIC_VECTOR(6 downto 0)       --output
        ); 
end division; 


architecture behav of division is 
    signal bufreg: STD_LOGIC_VECTOR((2 * SIZE - 1) downto 0); --signal array to hold both accumulator and dividend registers as one i.e bufreg(18 bits)
    signal dbuf: STD_LOGIC_VECTOR((SIZE - 1) downto 0);       --signal array to hold the divisor
    signal count: INTEGER range 0 to SIZE;                    --count to determine when to stop
     signal MYcount: INTEGER range 0 to 100; 
    signal res: STD_LOGIC_VECTOR((SIZE - 1) downto 0);        --result/quotient
    signal rm : STD_LOGIC_VECTOR((SIZE - 1) downto 0);        --remainder

     alias ADreg is bufreg((2 * SIZE - 1) downto SIZE);        --ADreg is is alias for top half of bufreg register(17th to 9th bit) 
    alias DVNDreg is bufreg((SIZE - 1) downto 0);             --DVNDreg is is alias for bottom half of bufreg register(8th to 0th bit)

--Function definitions
function to_bcd ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector; --converts 8 bit binary to 8 bit BCD
function m7seg   (bin : std_logic_vector(3 downto 0) ) return std_logic_vector; --converts 4 bit BCD to 7 bit 7segment
function breakdown1 ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector;  --breaks an 8 bit BCD into a 4 bit BCD with lower bits
function breakdown2 ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector;  ----breaks an 8 bit BCD into a 4 bit BCD with higher bits

--this function assigns the first 4 bits of an 8 bit BCD number to a 4-bit vector
function breakdown1 ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector is
variable bint : std_logic_vector(3 downto 0) :=bin(3 downto 0);
begin
return bint;
end breakdown1;

--this function assigns the last 4 bits of an 8 bit BCD number to a 4-bit vector
function breakdown2 ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector is
variable bint : std_logic_vector(3 downto 0) :=bin(7 downto 4);
begin
return bint;
end breakdown2;

--This function converts 8 bit binary to 8 bit BCD
function to_bcd ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector is
variable i : integer:=0;
variable bcd : std_logic_vector(7 downto 0) :=(others => '0');
variable bint : std_logic_vector(7 downto 0) :=bin;
variable bcd2 : std_logic_vector(7 downto 0) :=(others => '0');


begin
for i in 0 to 7 loop  -- repeating 8 times.
bcd(7 downto 1) := bcd(6 downto 0);  --shifting the bits.
bcd(0) := bint(7);
bint(7 downto 1) := bint(6 downto 0);
bint(0) :='0';


if(i < 7 and bcd(3 downto 0) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(3 downto 0) := bcd(3 downto 0) + "0011";
end if;

if(i < 7 and bcd(7 downto 4) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(7 downto 4) := bcd(7 downto 4) + "0011";
end if;

--if(i < 7 and bcd(11 downto 8) > "0100") then  --add 3 if BCD digit is greater than 4.
--bcd(11 downto 8) := bcd(11 downto 8) + "0011";
--end if;
end loop;
bcd2(7 downto 0):=bcd(7 downto 0);
return bcd2;
end to_bcd;

--This function converts 4 bit bcd to 7 segment
function m7seg (bin : std_logic_vector(3 downto 0))return std_logic_vector is

variable bint : std_logic_vector(3 downto 0):=bin(3 downto 0);
variable out7 : std_logic_vector(6 downto 0);
begin
    case bint is
            when "0000"=> out7:="1111110";
            when "0001"=> out7:="0110000";
            when "0010"=> out7:="1101101";
            when "0011"=> out7:="1111001";
            when "0100"=> out7:="0110011";
            when "0101"=> out7:="1011011";
            when "0110"=> out7:="X011111";
            when "0111"=> out7:="1110000";
            when "1000"=> out7:="1111111";
            when "1001"=> out7:="111X011";
            when others=> out7:="0000000";
    end case;

return out7;
end m7seg;




begin 
--our process begins here  (shift and subtract/ Non restoring division)
    p_001: process(reset, en, clk, bufreg) 
    begin 
        if reset = '1' then 
            res <= (others => '0'); 
            rm <= (others => '0'); 
                dbuf <= (others => '0');
            bufreg <= (others => '0');              
            count <= 0;
            MYcount <= 1;           
        elsif rising_edge(clk) then 
            if en = '1' then 
                case count is 
                when 0 => 
                    ADreg <= (others => '0'); 
                    DVNDreg <= num; 
                    dbuf <= den; 
                    res <= DVNDreg; 
                    rm <= ADreg; 
                    count <= count + 1; 
                when others => 
                    if bufreg((2 * SIZE - 2) downto (SIZE - 1)) >= dbuf then 
                        ADreg <= '0' & (bufreg((2 * SIZE - 3) downto (SIZE - 1)) - dbuf((SIZE - 2) downto 0)); 
                        DVNDreg <= DVNDreg ((SIZE - 2) downto 0) & '1'; 
                    else 
                        bufreg <= bufreg((2 * SIZE - 2) downto 0) & '0'; 
                    end if; 
                    if count /= SIZE then 
                        count <= count + 1; 
                    else 
                        count <= 0; 
                    end if;
                    end case; 
                 end if;

                            res <= DVNDreg; 
                            rm <= ADreg;

                             MYcount<=MYcount+1;
                            whatgoes<=(others => '0');
                        case MYcount is
                         when 2 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(rm)));   --first 7segment(lower bits of remainder)
                         when 3 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(rm)));   --second  7segment (higher bits of remainder)
                         when 4 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(res)));  --third  7segment (lower bits of result/quotient)
                         when 5 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(res)));  --fourth 7segment (higher bits of result/quotient)
                         when 6 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(den)));  --fifth  7segment (lower bits of divisor)
                         when 7 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(den)));  --sixth  7segment (higher bits of divisor)
                         when 8 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(num)));  --seventh  7segment (lower bits of number/dividend)         
                         when 9 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(num)));   --eigth 7segment (higher bits of number/dividend)          
                         when 10 => 
                         MYcount<=1;
                         when others => 
                         NULL;
                    end case;
         end if;
end process;
end behav;   

当我尝试运行模拟时,它会给我各种时髦的东西。我希望输出(whatgoes(6 downto 0))随着时钟的上升沿(clk)而改变。问题在于,由于我是VHDL的初学者,我在合成顺序语句方面遇到了很多问题。 在灵敏度列表中的启用,时钟和复位过程p_001内,我把这个case语句。它在正边缘条件下执行。 代码提取:

case MYcount is
                         when 2 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(rm)));   --first 7segment(lower bits of remainder)
                         when 3 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(rm)));   --second  7segment (higher bits of remainder)
                         when 4 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(res)));  --third  7segment (lower bits of result/quotient)
                         when 5 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(res)));  --fourth 7segment (higher bits of result/quotient)
                         when 6 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(den)));  --fifth  7segment (lower bits of divisor)
                         when 7 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(den)));  --sixth  7segment (higher bits of divisor)
                         when 8 => 
                         whatgoes<=m7seg(breakdown1(to_bcd(num)));  --seventh  7segment (lower bits of number/dividend)         
                         when 9 => 
                         whatgoes<=m7seg(breakdown2(to_bcd(num)));   --eigth 7segment (higher bits of number/dividend)          
                         when 10 => 
                         MYcount<=1;
                         when others => 
                         NULL;
                    end case;

我很确定我的问题就在这里,因为我的其余代码工作正常。 我为上传这么复杂的代码而道歉。我真的被困住了,而且我已经在这里工作了好几个小时。 任何帮助将不胜感激。我知道需要一种特殊的奉献和耐心才能回答这么长,乏味和无聊的问题。 但对于那些可以提供帮助或提供能够解决我的问题的链接的人来说,你们已经为我提供了很棒的服务。

我正在使用ISE 14.3和iSim。

所以,多亏了瑞克,我解决了这个问题。 他帮助我意识到我忘记了驱动3位选择输出。事实证明,使用case语句和计数变量驱动它解决了我顺序执行代码的问题。 我知道代码并没有完全以有条理的方式编写,但我希望随着时间的推移我会变得更好。

process (clk,tmp,rm,res,den,num)
       variable CLR: boolean:=true;
             begin  

                   if (CLR=true) then  

                          tmp <= "000"; 
                           CLR:=false;
                   elsif (clk'event and clk='1') then

                          tmp <= tmp + 1;
                                  if tmp<=8 then
                                  CLR:=true;
                                  end if;

                   end if;    
        case tmp is
                         when "000" => 
                         whatgoes<=m7seg(breakdown1(to_bcd(rm)));   --first 7segment(lower bits of remainder)
                         when "001" => 
                         whatgoes<=m7seg(breakdown2(to_bcd(rm)));   --second  7segment (higher bits of remainder)
                         when "010" => 
                         whatgoes<=m7seg(breakdown1(to_bcd(res)));  --third  7segment (lower bits of result/quotient)
                         when "011" => 
                         whatgoes<=m7seg(breakdown2(to_bcd(res)));  --fourth 7segment (higher bits of result/quotient)
                         when "100" => 
                         whatgoes<=m7seg(breakdown1(to_bcd(den)));  --fifth  7segment (lower bits of divisor)
                         when "101" => 
                         whatgoes<=m7seg(breakdown2(to_bcd(den)));  --sixth  7segment (higher bits of divisor)
                         when "110" => 
                         whatgoes<=m7seg(breakdown1(to_bcd(num)));  --seventh  7segment (lower bits of number/dividend)         
                         when "111" => 
                         whatgoes<=m7seg(breakdown2(to_bcd(num)));   --eigth 7segment (higher bits of number/dividend)          
                         when others => 
                         NULL;
                    end case;
                    sel<=tmp;
             end process;

1 个答案:

答案 0 :(得分:2)

我基本上是在黑暗中射击;也许如果您发布模拟图片,它将帮助我们更好地理解您的问题。无论如何,既然我们在这里,为什么不谈一些随机问题:

  • 如果您将代码拆分为几个块,每个块都有一个目的,那么代码将更容易理解(和使用)。你可以让一个块进行除法,并只输出商和余数。另一个块可以接收8个BCD值,并将它们多路复用,以便它们在您的电路板显示屏上正确显示。如果我们可以一次专注于问题的一部分,那么发现任何错误都会更容易。

  • 你在液晶显示屏上提到了一个3位选择,但我没有在你的代码中看到你开车的地方。也许你应该根据你的信号MYcount输出一些东西?

  • 为了确保您的功能正常工作,您可以将它们放在一个包中并创建一个自我测试的测试平台。至少我就是这样做的。这将使该变量脱离等式。

请发布一些模拟结果,以便我们为您提供帮助。