VHDL implementing 2 seven segments at one - vhdl

Here is my assignment for class. Our task will be to design a VHDL component that provides basic stop watch functionality. Your design should start at zero and be able to count up to 20 on the right-most 7-segment displays (the other two displays should be blank except as noted below). Pressing the center button causes the count to start and stop. The down button resets the counter to 00. If the count reaches 20, the 16 leds on the board will create a complex victory pattern.
How would I display two numbers on different numbers on two different 7segs at the same time.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;
entity lab_3 is
Port (
-------------led output-------------------------------------
led: out std_logic_vector(15 downto 0);
-------------button inputs----------------------------------
btnc: in std_logic;
btnd: in std_logic;
-----------7 seg outpus--------------------------------------------
seg: out std_logic_vector(6 downto 0); --MSB=a: LSB=g
-------------7 seg enables----------------------------------------
an: out std_logic_vector(3 downto 0)
);
end lab_3;
architecture Behavioral of lab_3 is
------decimal seven segment display--------------------------CONSTANTS
constant ZERO_7SEG: std_logic_vector(6 downto 0) := "1000000";
constant ONE_7SEG: std_logic_vector(6 downto 0) := "1111001";
constant TWO_7SEG: std_logic_vector(6 downto 0) := "0100100";
constant THREE_7SEG: std_logic_vector(6 downto 0) := "0110000";
constant FOUR_7SEG: std_logic_vector(6 downto 0) := "0011001";
constant FIVE_7SEG: std_logic_vector(6 downto 0) := "0010010";
constant SIX_7SEG: std_logic_vector(6 downto 0) := "0000010";
constant SEVEN_7SEG: std_logic_vector(6 downto 0) := "1111000";
constant EIGHT_7SEG: std_logic_vector(6 downto 0) := "0000000";
constant NINE_7SEG: std_logic_vector(6 downto 0) := "0010000";
constant TEN_7SEG: std_logic_vector(6 downto 0) := "1000000";
constant ELEVEN_7SEG: std_logic_vector(6 downto 0) := "1111001";
constant TWELVE_7SEG: std_logic_vector(6 downto 0) := "0100100";
constant THIRTEEN_7SEG: std_logic_vector(6 downto 0) := "0110000";
constant FOURTEEN_7SEG: std_logic_vector(6 downto 0) := "0110001";
constant FIFTEEN_7SEG: std_logic_vector(6 downto 0) := "0010010";
constant SIXTEEN_7SEG: std_logic_vector(6 downto 0) := "0000010";
constant SEVENTEEN_7SEG: std_logic_vector(6 downto 0) := "1111000";
constant EIGHTEEN_7SEG: std_logic_vector(6 downto 0) := "0000000";
constant NINETEEN_7SEG: std_logic_vector(6 downto 0) := "0010000";
constant TWENTY_7SEG: std_logic_vector(6 downto 0) := "1111001";
-------------------led dance-------------------------------------- ` constant step_one: std_logic_vector(15 downto 0):="0000000000000001";`
constant step_two: std_logic_vector(15 downto 0):="0000000000000010";
constant step_three: std_logic_vector(15 downto 0):="0000000000000100";
constant step_four: std_logic_vector(15 downto 0):="0000000000001000";
constant step_five: std_logic_vector(15 downto 0):="0000000000010000";
constant step_six: std_logic_vector(15 downto 0) :="0000000000100000";
constant step_seven: std_logic_vector(15 downto 0) :="0000000001000000";
constant step_eight: std_logic_vector(15 downto 0) :="0000000010000000";
constant step_nine: std_logic_vector(15 downto 0) :="0000000100000000";
constant step_ten: std_logic_vector(15 downto 0) :="0000001000000000";
constant step_eleven: std_logic_vector(15 downto 0):="0000010000000000";
constant step_twelve: std_logic_vector(15 downto 0):="0000100000000000";
constant step_thirteen: std_logic_vector(15 downto 0):="0001000000000000";
constant step_fourteen: std_logic_vector(15 downto 0) :="0010000000000000";
constant step_fifteen: std_logic_vector(15 downto 0) :="0100000000000000";
constant step_sixteen: std_logic_vector(15 downto 0):="1000000000000000";
---------------------active constants-----------------------------------
constant active: std_logic :='1';
constant inactive: std_logic :='0';
constant ACTIVE_RESET: std_logic := '0';
constant TERMINAL_VALUE: integer := 50000000;
-------------------internal connections-------------------------SIGNALS
signal Clock: std_logic;
signal Count: unsigned(7 downto 0);
signal DividedClock: std_logic;
signal Digit0: std_logic_vector(6 downto 0);
signal Digit1: std_logic_vector(6 downto 0);
signal DigitSelect: std_logic;
signal led_dance: std_logic_vector( 15 downto 0);
-----------------clock divider----------------------------
begin
process(Clock)
variable counter: integer range 0 to TERMINAL_VALUE;
begin
if (btnD=ACTIVE_RESET) then
counter := 0;
elsif (rising_edge(Clock)) then
counter := counter + 1;
if (counter = TERMINAL_VALUE) then
counter := 0;
DividedClock <= not DividedClock;
end if;
end if;
end process;
--------------------------counter-----------------------------
process(Clock)
begin
if (btnD=active) then
count <= "00000000";
elsif (rising_edge(Clock)) then
count <= count + 1;
end if;
end process;
-------------------BCD to 7seg--------------------------------
with count select
Digit0 <= ZERO_7SEG when "0000000",
ONE_7SEG when "0000001",
TWO_7SEG when "0000010",
THREE_7SEG when "0000011",
FOUR_7SEG when "0000100",
FIVE_7SEG when "0000101",
SIX_7SEG when "0000110",
SEVEN_7SEG when "0000111",
EIGHT_7SEG when "0001000",
NINE_7SEG when "0001001",
TEN_7SEG when "0001010",
ELEVEN_7SEG when "0001011",
TWELVE_7SEG when "0001100",
THIRTEEN_7SEG when "0001101",
FOURTEEN_7SEG when "0001110",
FIFTEEN_7SEG when "0001111",
SIXTEEN_7SEG when "0010000",
SEVENTEEN_7SEG when "0010001",
EIGHTEEN_7SEG when "0010010",
NINETEEN_7SEG when "0010011",
TWENTY_7SEG when others;
with count select
Digit1 <= ZERO_7SEG when "0000000",
ZERO_7SEG when "0000001",
ZERO_7SEG when "0000010",
ZERO_7SEG when "0000011",
ZERO_7SEG when "0000100",
ZERO_7SEG when "0000101",
ZERO_7SEG when "0000110",
ZERO_7SEG when "0000111",
ZERO_7SEG when "0001000",
ZERO_7SEG when "0001001",
TWO_7SEG when "0010100",
ONE_7SEG when others;
end Behavioral;

I suppose you need to connect either the Digit0 or Digit1 signal to the seg output port.
From my experience with such displays I assume that all four digits will show the pattern encoded by seg. In order to display different patterns for each digit, the idea is to quickly turn the individual digits on and off using the an output, so that only one of them is on at any given moment, while switching seg between Digit0 and Digit1 at the same time.
If the switching is done quick enough, it will not be apparent to the eye.

There are several design examples including SSDs at vhdl.us.

Related

VHDL - Want to create a simple divider

I'm using Vivado 2018.2
I want to make a simple divider, say the input is 153 and the constant is 53. So with 153/53, I want to see 2 and the remainder 47.
The code I have so far errors out (sequential).
entity divider_main is
port(
dividend: in std_logic_vector(7 downto 0);
remainder: out std_logic_vector(5 downto 0);
quotient: out std_logic_vector(2 downto 0)
);
end divider_main;
architecture Behavioral of divider_main is
signal dividend_signal: signed(7 downto 0);
signal remainder_signal: std_logic_vector(5 downto 0);
signal fifty_three: signed(7 downto 0);
signal count: unsigned(2 downto 0);
begin
dividend_signal <= signed(dividend);
fifty_three <= "00011101";
count <= "000";
process(dividend, dividend_signal) is
begin
if dividend_signal < fifty_three then
remainder(5 downto 0) <= std_logic_vector(dividend_signal(5 downto 0));
quotient <= std_logic_vector(count);
dividend_signal <= "00000000";
count(2 downto 0) <= "000";
else
count <= count + 1;
dividend_signal <= dividend_signal - fifty_three;
quotient(2 downto 0) <= "000";
remainder <= "000000";
end if;
end process;
end Behavioral;
I'm new to vhdl so let me know what I am doing wrong!

Slicing a STD_LOGIC_VECTOR and putting back together?

I have sliced a 16 bit STD_LOGIC_VECTOR into 3 parts. I want to leave the first 8 MSBs untouched and break the 8 LSBs into 2 nibbles to do some processing on them.
I can do all this and the processing is all fine but when I try to put them all together into a 16 bit STD_LOGIC_VECTOR output it just stays UUUU. is there a special way that putting it back together should go?
signal fullout : std_logic_vector(15 downto 0);
signal Sbox1 : integer;
signal Sbox2 : integer;
signal tophalf : std_logic_vector(7 downto 0);
signal secondnibble, firstnibble : std_logic_vector(3 downto 0); --break the LSH into 2 nibbles
begin
tophalf(7 downto 0) <= LUTin(15 downto 8);
secondnibble(3 downto 0) <= LUTin(7 downto 4);
-- Sbox1 <= to_integer(unsigned(secondnibble));
firstnibble(3 downto 0) <= LUTin(3 downto 0);
-- Sbox2 <= to_integer(unsigned(firstnibble));
p1: process(LUTin)
begin
fullout(15 downto 8) <= tophalf(7 downto 0);
fullout(7 downto 4) <= secondnibble(3 downto 0);
fullout(3 downto 0) <= firstnibble(3 downto 0);
Always initialize outputs. In your case, its not clear that what is output, so here is my guess:
architecture xyz of zyx is
signal fullout : std_logic_vector(15 downto 0) := (others =>'0');
signal tophalf : std_logic_vector(7 downto 0):= (others =>'0');
signal secondnibble, firstnibble : std_logic_vector(3 downto 0):= (others =>'0');
.....
begin
....
end xyz;

Implementing a 10 bit shift register with led outputs

I am trying to implement the the following shift register
entity MyShiftRegister is
port(
clock: in std_logic;
DataIn: in std_logic_vector (9 downto 0);
Left: in std_logic; --synchronous left rotate
Right: in std_logic; --synchronous right rotate
Load: in std_logic; --synchronous parallel load
Clear: in std_logic; -- synchronous clear
DataOut: out std_logic_vector (9 downto 0);
This is what I have so far
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity question2 is
Port (
led: buffer std_logic_vector (9 downto 0);
clk: in std_logic;
btnu: in std_logic;
btnL: in std_logic;
btnR: in std_logic ;
btnD: in std_logic;
btnC: in std_logic
);
end question2;
architecture Behavioral of question2 is
constant active: std_logic :='1';
constant inactive: std_logic :='0';
constant step_zero: std_logic_vector(9 downto 0) :="0000000000";
constant step_one: std_logic_vector(9 downto 0) :="0000000001";
constant step_two: std_logic_vector(9 downto 0) :="0000000010";
constant step_three: std_logic_vector(9 downto 0) :="0000000100";
constant step_four: std_logic_vector(9 downto 0) :="0000001000";
constant step_five: std_logic_vector(9 downto 0) :="0000010000";
constant step_six: std_logic_vector(9 downto 0) :="0000100000";
constant step_seven: std_logic_vector(9 downto 0) :="0001000000";
constant step_eight: std_logic_vector(9 downto 0) :="0010000000";
constant step_nine: std_logic_vector(9 downto 0) :="0100000000";
constant step_ten: std_logic_vector(9 downto 0) :="0100000000";
signal DataIn: std_logic_vector (9 downto 0):= "1111111111";
signal Load: std_logic := btnD;
signal Reset: std_logic;
signal Left: std_logic:= btnL;
signal Right: std_logic:= btnR;
signal DataOut: std_logic_vector := led (9 downto 0);
signal Clear: std_logic:= btnU;
signal speed_enable: std_logic;
begin
SpeedControl: process (clk)
variable counter: integer range 0 to 10000000;
begin
speed_enable<=not active;
if Reset = Active then
counter:= 0;
elsif (rising_edge (clk)) then
counter := counter + 1;
if (counter=10000000) then
speed_enable<= Active;
counter:=0;
end if;
end if;
end process;
shiftregister: process(clk, clear)
begin
if rising_edge (clk) then
if clear= active then
DataOut <= (others => '0');
elsif load = active then
DataOut <= DataIn ;
elsif Left = active then
DataOut <= DataOut(8 downto 0) & "1" ;
if DataOut = "1000000000" then
clear <= active;
elsif Right = active then
DataOut <= DataOut (9 downto 1) & "1" ;
if DataOut = "0000000001" then
clear <= active;
end if;
end if;
end if;
end if;
end process;
with DataOut select
led <= step_one when "0000",
step_two when "0001",
step_three when "0010",
step_four when "0011",
step_five when "0100",
step_six when "0101",
step_seven when "0110",
step_eight when "0111",
step_nine when "1000",
step_ten when "1001",
step_zero when others;
end Behavioral;
How exactly do I rotate bits left and right and tie that to my led outputs. I was thinking of using a counter and just incrementing and decrementing to shift bits left or right but I'm not sure if that would still be considered a shift register.
thanks
To start:
constant step_nine: std_logic_vector(9 downto 0) :="0100000000";
constant step_ten: std_logic_vector(9 downto 0) :="0100000000";
is incorrect. It should be
constant step_nine: std_logic_vector(9 downto 0) :="0100000000";
constant step_ten: std_logic_vector(9 downto 0) :="1000000000";
But this approach is very error prone anyhow. Lets simplify it:
process(sel)
variable selected_led : natural;
begin
led <= (others => '0');
selected_led := to_integer(unsigned(sel));
if selected_led < led'length then
led(selected_led) <= '1';
end if;
end process;
If the led(selected_led) <= '1'; won't synthesize, you probably have to change it to
for i in 0 to led'length-1 loop
if (i = selected_led) then
led(i) <= '1';
end if;
end loop;
As for using the buffer port. Don't. preferably only use in or out. If you want to read an out port, compile with VHDL-2008, or use a temporary signal in between.
Then note that right and left are keywords in VHDL. you shouldn't use them
What you want is very simple and basic VHDL. Example (using VHDL-2008):
process(clock)
begin
if rising'edge(clock) then
if clear = '1' then
data_out <= (others => '0');
elsif load = '1' then
data_out <= data_in;
elsif right_rotate = '1' then
data_out <= data_out(0) & data_out(data_out'length-1 downto 1);
elsif left_rotate = '1' then
data_out <= data_out(data_out'length-2 downto 0) &
data_out(data_out'length-1);
end if;
end if;
end process;

= can not have such operands in this context

Here's the full error: ERROR:HDLParsers:808 - "C:/Users/vROG/Desktop/.../CacheController.vhd" Line 72. = can not have such operands in this context.
I'd understand how to fix this if I was used '+' or '*', but equal sign?
As you can tell, the code isn't nearly being close to completely, but I can't understand why my second nested if isn't working. I've tried turning dirtyBIT to type int, but it still gives me the same error, which leads me to believe that I made a trivial error somewhere.
FIXED (Using user1155120's advice) However how do I resolve the issue with offset and tag?
architecture Behavioral of CacheController is
signal tagFROMCPU : STD_LOGIC_VECTOR(7 downto 0) := CPU_addr(15 downto 8);
signal indexFROMCPU: STD_LOGIC_VECTOR(2 downto 0) := CPU_addr(7 downto 5);
signal offsetFROMCPU: STD_LOGIC_VECTOR(4 downto 0) := CPU_addr(4 downto 0);
TYPE STATETYPE IS (state_0, state_1, state_2, state_3);
SIGNAL present_state : STATETYPE;
--Variables
signal dirtyBIT: std_logic_vector (7 downto 0);
signal validBIT: std_logic_vector (7 downto 0);
TYPE tag is array (7 downto 0) of STD_LOGIC_VECTOR(7 downto 0);
TYPE offset is array (7 downto 0) of STD_LOGIC_VECTOR(4 downto 0);
signal myTag: tag;
signal myOFFSET : offset;
begin
--STATE MACHINE
process(clk)
begin
if (present_state = state_0) then --Start State : Checks for HIT or MISS, PERFORMS HIT OPERATION or MOVES TO STATE_1
if ((myTag(to_integer(unsigned(indexFROMCPU)) = tagFROMCPU)) then
--HIT
else
present_state <= state_1;
end if;
elsIF (present_state = state_1) then --CHECKS DIRTY BIT. IF 0, LOADS DATA, MOVES TO STATE_0 ELSE move to state_2
if (dirtyBit(to_integer(unsigned(indexFROMCPU))) = '0') then
present_state <= state_0;
else
present_state <= state_2;
end if;
elsIF(present_state = state_2) then -- DIRTY BIT IS 1, SAVES DATA, goes back to STATE_1
present_state <= state_1;
end if;
end process;
end Behavioral;
OLD CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity CacheController is
Port (
clk : in STD_LOGIC;
CPU_addr : in STD_LOGIC_VECTOR (15 downto 0);
CPU_WR_RD : in STD_LOGIC;
CPU_CS : in STD_LOGIC;
CPU_RDY : out STD_LOGIC;
SDRAM_Addr : out STD_LOGIC_VECTOR (15 downto 0);
SDRAM_WR_RD : out STD_LOGIC;
SDRAM_MSTRB : out STD_LOGIC;
MUX1,MUX2 : out STD_LOGIC;
SRAM_Addr : out STD_LOGIC_VECTOR (7 downto 0);
SRAM_WEN : out STD_LOGIC
);
end CacheController;
architecture Behavioral of CacheController is
signal tagFROMCPU : STD_LOGIC_VECTOR(7 downto 0) := CPU_addr(15 downto 8);
signal indexFROMCPU: STD_LOGIC_VECTOR(2 downto 0) := CPU_addr(7 downto 5);
signal offsetFROMCPU: STD_LOGIC_VECTOR(4 downto 0) := CPU_addr(4 downto 0);
TYPE STATETYPE IS (state_0, state_1, state_2, state_3);
SIGNAL present_state : STATETYPE;
--Variables to emulate SRAM
TYPE dirtyBIT is array (7 downto 0) of std_logic;
TYPE validBIT is array (7 downto 0) of std_logic;
TYPE tag is array (7 downto 0,7 downto 0) of std_logic;
TYPE offset is array (7 downto 0,4 downto 0) of std_logic;
begin
--STATE MACHINE
process(clk)
begin
if (present_state = state_0) then --Start State : Checks for HIT or MISS, PERFORMS HIT OPERATION or MOVES TO STATE_1
elsIF (present_state = state_1) then --CHECKS DIRTY BIT. IF 0, LOADS DATA, MOVES TO STATE_0 ELSE move to state_2
if (dirtyBit(to_integer(unsigned(indexFROMCPU))) = '0') then
present_state <= state_0;
else
present_state <= state_2;
end if;
elsIF(present_state = state_2) then -- DIRTY BIT IS 1, SAVES DATA, goes back to STATE_1
present_state <= state_1;
end if;
end process;
end Behavioral;
Operator overload resolution (for the "=" operator) requires a function be declared with a matching signature (types of the left and right inputs and the return type).
if (dirtyBit(to_integer(unsigned(indexFROMCPU))) = '0') then
Change the declaration for dirtyBit:
--Variables to emulate SRAM
-- TYPE dirtyBIT is array (7 downto 0) of std_logic;
signal dirtyBIT: std_logic_vector (7 downto 0);
And your code analyzes. I'd suggest the other type declaration (validBIT, tag and offset) should be similarly treated.
It looks like there should be an array type where offset is used. The type name might be changed to preserve offset as a signal name.

VHDL code to find square root of number?

Is there is any in built function or any library that can be included in the design to find square root of a number?
Restoring square root algorithm is easy to implement on fpga, wikipedia has an example.
FPGA vendors should have cores available, it hides inside the general purpose CORDIC core on Xilinx. They also have square root cores for floating points, if that's what you need.
For non-synthesizable (simulation/test-bench only) operation, square root for real can be done with:
y := math_real.sqrt(x)
For synthesizable operation, see answer from Jonathan Drolet.
This one worked for me.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_unsigned.ALL;
entity squart is port(
clock : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(3 downto 0)); end squart;
architecture behaviour of squart is
signal part_done : std_logic := '0';
signal part_count : integer := 3;
signal result : std_logic_vector(4 downto 0) := "00000";
signal partialq : std_logic_vector(5 downto 0) := "000000";
begin
part_done_1: process(clock, data_in, part_done)
begin
if(clock'event and clock='1')then
if(part_done='0')then
if(part_count>=0)then
partialq(1 downto 0) <= data_in((part_count*2)+ 1 downto part_count*2);
part_done <= '1'; else
data_out <= result(3 downto 0);
end if;
part_count <= part_count - 1;
elsif(part_done='1')then
if((result(3 downto 0) & "01") <= partialq)then
result <= result(3 downto 0) & '1';
partialq(5 downto 2) <= partialq(3 downto 0) - (result(1 downto 0)&"01");
else
result <= result(3 downto 0) & '0';
partialq(5 downto 2) <= partialq(3 downto 0);
end if;
part_done <= '0';
end if;
end if;
end process;
end behaviour;
Check this one:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SQRT is
Generic ( b : natural range 4 to 32 := 16 );
Port ( value : in STD_LOGIC_VECTOR (15 downto 0);
result : out STD_LOGIC_VECTOR (7 downto 0));
end SQRT;
architecture Behave of SQRT is
begin
process (value)
variable vop : unsigned(b-1 downto 0);
variable vres : unsigned(b-1 downto 0);
variable vone : unsigned(b-1 downto 0);
begin
vone := to_unsigned(2**(b-2),b);
vop := unsigned(value);
vres := (others=>'0');
while (vone /= 0) loop
if (vop >= vres+vone) then
vop := vop - (vres+vone);
vres := vres/2 + vone;
else
vres := vres/2;
end if;
vone := vone/4;
end loop;
result <= std_logic_vector(vres(result'range));
end process;
end;

Resources