سؤال

So here's the problem. I've written code for a binary divider that should output 7-bit 7 segment display binary code to go into an 8 x 7segment display. (2 7segments for dividend,divisor,quotient,remainder each and in that order). This 8 x 7segment display on my dev-board has one 7-bit input(a to g) and a 3-bit select. So the basic idea is I have to output the dividend,divisor,quotient and remainder sequentially, continuously and fast enough such that to the human eye the output looks constant despite the fact that the each of the eight 7 segments is being enabled one by one according to what my output is. Originally, the divider gives all the outputs (dividend,divisor,quotient,remainder)in binary which are then converted by a function to 8-bit bcd and that bcd number is then broken down into two 4-bit bcd numbers by another function(Now I have 8 output variables: 2 representing dividend,2 representing divisor etc).These 4-bit numbers are converted by another function to 7 segment.

Here is the full code:

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;   

When I try to run a simulation, it gives me all kinds of funky stuff. I want the output (whatgoes(6 downto 0)) to change with the rising edge of the clock(clk). The problem is that since I'm a beginner at VHDL,Ive been having a lot of problems with synthesizing sequential statements. Inside the process p_001 with enable, clock, and reset in the sensitivity list, i put this case statement. It executes on a positive edge condition. Code extract:

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;

I'm pretty sure my problem lies here since the rest of my code works fine. I apologize for uploading such a convoluted mess of code. I'm genuinely stuck and I've been at this for a good number of hours. Any help would be greatly appreciated. I know it takes a special kind of devotion and patience to answer such a long,boring and nooby problem. But to whoever can help or provide a link to something that has an answer to my kind of problem, you'd have done me a great service.

I'm using ISE 14.3and iSim.

So, thanks to rick, I solved this. He helped me realize that I was forgetting to drive the 3-bit select output. As it turns out, driving it using a case statement and counting variable solved my problem of executing the code sequentially. I know the code is not exactly written in an organized way but i hope with time i'll get better.

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;
هل كانت مفيدة؟

المحلول

I'm basically shooting in the dark here; maybe if you post a simulation picture it will help us understand your problem better. Anyway, since we're at it, why not talk about a few random issues:

  • The code would be easier to understand (and to work with) if you'd split it into a few blocks, each with a single purpose. You could have one block do the division, and output only the quotient and remainder. Another block could take in 8 BCD values, and multiplex them so that they appear correctly on your board's displays. If we can concentrate on one part of the problem at a time, it will be easier to spot anything wrong.

  • You mention a 3-bit select on the LCD, but I don't see in your code where you drive it. Maybe you should output something based on your signal MYcount?

  • To make sure your functions are working ok, you could put them in a package and create a self-cheking testbench. At least that's how I'd do it. This would take that variable out of the equation.

Please post some simulation results so that we can help you out.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top