Reputation: 10870
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;
Upvotes: 0
Views: 579
Reputation: 1646
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.
Upvotes: 2