Led matrix row bits don't shift - vhdl

I am new to VHDL and I am trying to do a simple application with a led matrix (8x8). My goal is to turn on the leds of the matrix so I can see a smiley face. For some reason none of the leds turn on.
In order to see what's wrong I tried to turn on all leds on each line at a time by commenting the case statement and giving cols<="00000000" before the statement, the result is that the only line that turns on is the first, it keeps turning on and off each second.
I made the frequency divider for 1 second just to see if the code works correctly.
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;
entity main is
Port ( clk : in STD_LOGIC;
rows : out STD_LOGIC_VECTOR (7 downto 0);
cols : out STD_LOGIC_VECTOR (7 downto 0));
end main;
architecture Behavioral of main is
signal count: std_logic_vector(7 downto 0):= "00000001";
signal clk1Hz: std_logic_vector(26 downto 0);
begin
process(clk)
begin
if rising_edge(clk) then
if clk1Hz = X"5F5E0FF" then
clk1Hz <= "000" & X"000000";
else
clk1Hz <= clk1Hz + 1;
end if;
if clk1Hz(26) = '1' then
if count = "10000000" then
count <= "00000001";
else
count(7 downto 1) <= count(6 downto 0);
count(0) <= '0';
end if;
rows <= count;
case count is
when "00000001" => cols <= "11111111";
when "00000010" => cols <= "11011011";
when "00000100" => cols <= "11011011";
when "00001000" => cols <= "11111111";
when "00010000" => cols <= "00111100";
when "00100000" => cols <= "10000001";
when "01000000" => cols <= "11000011";
when "10000000" => cols <= "11111111";
when others => cols <= "11111111";
end case;
end if;
end if;
end process;
end Behavioral;

Do you realize that if clk1Hz(26) = '1' then stays true from X"4000000" to X"5F5E0FF"?
You most likely want to change count only on the exact X"4000000" value, no? And not continuously for 1/3rd of the time...

I can tell you didn't simulate this. The clk1Hz signal wasn't initialized and wasn't reset. It won't spin in sim without this, since it initializes to X. However, on hardware it will work just fine.
So, when your clk counter hits x400_0000, bit (26) is set and your row/col shifters start going like mad for 1/3 of a second. Then when the clk counter resets, all activity stops.
Is this really what you want? I can see from simulating this that rows and cols are both shifting correctly, albeit for only a third of a second.
During the pause, rows stops at 0x80, and cols at 0xFF.

Related

VHDL uart which send 16 chars string

I have to do UART with vhdl on the Xilinx which will send 16 chars string. I wrote such code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(3 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(9 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
-- freq of clock
begin
process(CLK, RESET)
begin
if rising_edge(CLK) then
if(A = '1' and K < 10416) then
K <= K + 1;
CLK_Txd <= K(13);
elsif(B = '1' and K < 5208) then
K <= K + 1;
CLK_Txd <= K(12);
elsif(C = '1' and K < 20832) then
K <= K + 1;
CLK_Txd <= K(14);
else
K <= (others => '0');
end if;
end if;
end process;
--counter
process(CLK_Txd, RESET, ENABLE)
begin
if(RESET = '1' and ENABLE = '0') then
Q <= "0000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
--comparator
ENABLE <= '1' when (Q > 4) else '0';
--transcoder
process(Q, CLK_Txd)
begin
if (rising_edge(CLK_Txd)) then
case Q is
when "0001" => DATA <= x"40";
when "0010" => DATA <= x"41";
when "0011" => DATA <= x"42";
when "0100" => DATA <= x"43";
when "0101" => DATA <= x"44";
when "0110" => DATA <= x"45";
when "0111" => DATA <= x"46";
when "1000" => DATA <= x"47";
when "1001" => DATA <= x"48";
when "1010" => DATA <= x"49";
when "1011" => DATA <= x"50";
when "1100" => DATA <= x"51";
when "1101" => DATA <= x"52";
when "1110" => DATA <= x"53";
when "1111" => DATA <= x"54";
when others => DATA <= x"55";
end case;
end if;
end process;
--uart
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '0') then
QTxD <= DATA & "01";
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(9 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
It's send data completely not connected with that what i have in transcoder and realy dont know why. Do you have any ideas what is wrong with my code, or do you have any diffrent examples of it how to send your own 16 chars with uart? I suppose that something is wrong with my counter or comparator.
--EDIT
Thans for your effort, i can't try your code at the Xilinx right now couse I am workin on it at my university. I see that you made a lot of changes in my code. Of course first i try to do it like you show and i hope this will be acceptable, but I propably have to do it with transcoder according to this picture.
From last time i made such changes i my code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.ALL;
entity uartByJackob is
Port ( CLK, A, B, C : in STD_LOGIC;
RESET : in STD_LOGIC;
TxD, TxDOSC : out STD_LOGIC);
end uartByJackob;
architecture Behavioral of uartByJackob is
signal K: std_logic_vector(14 downto 0);
signal Q: std_logic_vector(7 downto 0);
signal CLK_Txd: std_logic;
signal ENABLE: std_logic;
signal QTxD: std_logic_vector(7 downto 0);
signal DATA : STD_LOGIC_VECTOR(7 downto 0);
signal QPrim: std_logic_vector(3 downto 0);
begin
process(CLK, RESET)
begin
CLK_Txd <= CLK;
end process;
process(CLK_Txd, RESET, ENABLE)
begin
if(ENABLE = '0') then
Q <= "00000000";
elsif (rising_edge(CLK_Txd)) then
Q <= Q + 1;
end if;
end process;
ENABLE <= '1' when (Q <= 255) else '0';
process(Q(7 downto 4))
begin
case Q(7 downto 4) is
when "0000" => DATA <= x"40";
when "0001" => DATA <= x"41";
when "0010" => DATA <= x"42";
when "0011" => DATA <= x"43";
when "0100" => DATA <= x"44";
when "0101" => DATA <= x"45";
when "0110" => DATA <= x"46";
when "0111" => DATA <= x"47";
when "1000" => DATA <= x"48";
when "1001" => DATA <= x"49";
when "1010" => DATA <= x"50";
when "1011" => DATA <= x"51";
when "1100" => DATA <= x"52";
when "1101" => DATA <= x"53";
when "1110" => DATA <= x"54";
when "1111" => DATA <= x"55";
when others => DATA <= x"56";
end case;
end process;
process(CLK_Txd, ENABLE, DATA)
begin
if(ENABLE = '1') then
QTxD <= DATA;
elsif rising_edge(CLK_Txd) then
QTxD <= '1'&QTxD(7 downto 1);
end if;
end process;
TxD <= QTxD(0);
TxDOSC <= QTxD(0);
end Behavioral;
According to that i send MSB to transcoder and LSB to comparator but my program all the time still send x"40" to DATA and it is propably connected with this counter which you were talking about.
There is my simulation efect. I becoming upset with that couse i don't have enough skills in vhdl to do it by my self. I hope that you will help me to do rebuild my project. On simulation it looks good i dont know how it looks on Xilinx.
Can you show me a piece of code? - Stefan
The entire purpose to providing the link to Adrian Adamcyzk's code (Altera FPGA hardware (has an issue) vs ModelSim simulation (ok) - self implemented UART) was to provide an example with a bit (baud) counter and flip flop used to control sending the message once.
Here's Jackob's modified:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity uartbyjackob is
port (
clk, a, b, c: in std_logic;
reset: in std_logic;
txd, txdosc: out std_logic
);
end entity uartbyjackob;
architecture foo of uartbyjackob is
-- signal k: unsigned(14 downto 0); -- FOR simulation
-- note if k were used in simulation it would require initialization
signal q: unsigned (3 downto 0); -- WAS std_logic_vector
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(9 downto 0);
-- signal data: std_logic_vector(7 downto 0);
-- added:
signal bdcnt: unsigned (3 downto 0);
signal ldqtxd: std_logic;
signal davl: std_logic;
type data_lut is array (0 to 15) of std_logic_vector (7 downto 0);
constant data: data_lut := (
x"40", x"41", x"42", x"43", x"44", x"45", x"46", x"47",
x"48", x"49", x"50", X"51", x"52", X"53", x"54", x"55"
);
signal datalut: std_logic_vector (7 downto 0); -- FOR SIMULATION visibility
begin
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk) then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
clk_txd <= clk; -- SHORTENS SIMULATION
DAVL_FF: -- DATA_AVAILABLE to send
process (clk_txd, reset)
begin
if reset = '1' then
davl <= '0';
elsif rising_edge (clk_txd) then
if q = 15 and bdcnt = 9 then -- a JK FF equivalent
davl <= '0';
elsif q = 0 then
davl <= '1'; -- one clock holderover from reset
-- else
-- davl <= davl;
end if;
end if;
end process;
-- process(clk_txd, reset, enable)
-- begin
-- if reset = '1' and enable = '0' then
-- q <= "0000";
-- elsif rising_edge(clk_txd) then
-- q <= q + 1;
-- end if;
-- end process;
QCNT:
process (clk_txd, reset)
begin
if reset = '1' then
q <= (others => '0');
elsif rising_edge (clk_txd) then
if enable = '1' then
q <= q + 1;
end if;
end if;
end process;
BAUD_COUNTER:
process (clk_txd, reset)
begin
if reset = '1' then
bdcnt <= (others => '0');
elsif rising_edge (clk_txd) then
if davl = '0' or bdcnt = 9 then
bdcnt <= (others => '0');
else
bdcnt <= bdcnt + 1;
end if;
end if;
end process;
-- comparator
-- enable <= '1' when (q > 4) else '0';
enable <= '1' when bdcnt = 9 and davl = '1' and q /= 15 else
'0';
-- q latches at 15;
ldqtxd <= '1' when bdcnt = 9 and davl = '1' else
'0';
datalut <= data(to_integer(q)); -- FOR SIMULATION VISIBILITIY
--transcoder
-- process(q, clk_txd)
-- begin
-- if rising_edge(clk_txd) then
-- case q is
-- when "0001" => data <= x"40";
-- when "0010" => data <= x"41";
-- when "0011" => data <= x"42";
-- when "0100" => data <= x"43";
-- when "0101" => data <= x"44";
-- when "0110" => data <= x"45";
-- when "0111" => data <= x"46";
-- when "1000" => data <= x"47";
-- when "1001" => data <= x"48";
-- when "1010" => data <= x"49";
-- when "1011" => data <= x"50";
-- when "1100" => data <= x"51";
-- when "1101" => data <= x"52";
-- when "1110" => data <= x"53";
-- when "1111" => data <= x"54";
-- when others => data <= x"55";
-- end case;
-- end if;
-- end process;
-- uart
-- process (clk_txd, enable, data)
-- begin
-- if enable = '0' then
-- qtxd <= data & "01";
-- elsif rising_edge(clk_txd) then
-- qtxd <= '1' & qtxd(9 downto 1);
-- end if;
-- end process;
TX_SHIFT_REG:
process (clk_txd, reset) -- shift regiseter Tx UART
begin
if reset = '1' then
qtxd <= (others => '1'); -- output mark by default
elsif rising_edge (clk_txd) then
if ldqtxd = '1' then
qtxd <= '1' & data(to_integer(q)) & '0';
-- STOP & Data(q) 7 downto 0 & START , a MUX and expansion
else
qtxd <= '1' & qtxd(9 downto 1); -- shift out;
end if;
end if;
end process;
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture foo;
library ieee;
use ieee.std_logic_1164.all;
entity uartbyjackob_tb is
end entity;
architecture foo of uartbyjackob_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal txd: std_logic;
begin
DUT:
entity work.uartbyjackob
port map (
clk => clk, -- clk_txd driven by clk
a => 'X',
b => 'X',
c => 'X', -- a, b, c aren't used
reset => reset,
txd => txd,
txdosc => open
);
CLOCK:
process
begin
wait for 52.35 us;
clk <= not clk;
if now > 20000 us then
wait;
end if;
end process;
STIMULUS:
process
begin
wait for 104.7 us;
reset <= '1';
wait for 104.7 us;
reset <= '0';
wait;
end process;
end architecture;
The model has been modified for faster simulation, ignoring the baud rate clock generator.
There's an added flip flop (davl) for enabling the UART to run. There's an added baud (bit) counter bdcnt.
I changed the order of the start, stop and data values loaded into QTxD so the start bit came out first, followed by 8 data bits and the stop bit.
You can read off TxD from left to right start bit, data(q)(0) ... data(q(7), stop bit. The enable or ldqtxd will occur at the same time as a stop bit.
There's only one observable draw back to this implementation, if you reset while a value in the shift register hasn't finished loading you'll cause a framing error for the receiver. Don't reset it for 10 baud times after davl goes false.
The simulation is shown with a 9600 baud clk_txd, the characters go out back to back.
It has fewer flip flops than the original (disregarding k). There is no data register separate from QTxD ( - 8 FFs) plus bdcnt (+ 4) plus davl (+ 1). There are two comparisons (optimized to two) bdcnt = 9, q =, /= 9. Those could be expressed separately so it doesn't require optimization during synthesis.
I changed the look up table style, a matter of personal preference also the excuse for changing counters to type unsigned and using only package numeric_std for arithmetic.
The little testbench likewise doesn't expect the k counter to generate the baud clock.
Running the testbench gives:
Where there's an added signal datalut to show the value being shifted out after ldqtxd.
After your change making the q counter (7 downto 0)
We still see from your waveform that it doesn't work.
This is due to the enable and the shift register.
If you use a single counter with the upper four bits indexing the output character your character is transmitted in 10 out of the 16 clk_txd times indexed by the lower four bits of the counter. The remaining clock times TxD should be '1' (idle line marks in RS-232 parlance).
The order for data to be transmitted will be a space (the start bit), data(0) through data(7) and a mark (the stop bit). (Shown left to right on TxD).
For simulation the k counter is not used. I included it commented out below.
I made several changes for proper simulation. These include synchronously loading the shift register containing QTxD, synchronously clearing the rightmost bit of QTxD to provide a full width and moving enable to occur once every sixteen clocks (clk_txd). The enable is preceded by a new clear for the start bit and both been offset to prevent it from occurring during reset which has the effect of causing a framing error on the first character for any receiver.
Simulation is done with the same testbench I provide above.
The changes to your new code are shown by comments:
architecture behavioral of uartbyjackob is
-- signal k: std_logic_vector(14 downto 0);
signal q: unsigned (7 downto 0); -- std_logic_vector(7 downto 0);
signal clk_txd: std_logic;
signal enable: std_logic;
signal qtxd: std_logic_vector(7 downto 0);
-- using an 8 bit shift register requires a method of outputting a
-- synchronous start bit (the width is important for receive framing)
-- and synchronous stop bit
signal data: std_logic_vector(7 downto 0);
signal qprim: std_logic_vector(3 downto 0);
signal clear: std_logic; -- synchronous clear for start bit
begin
-- let's keep this here for when you put it the FPGA
-- -- freq of clock -- NOTE k never in known binary state for simulation
-- process (clk, reset)
-- begin
-- if rising_edge(clk then
-- if a = '1' and k < 10416 then
-- k <= k + 1;
-- clk_txd <= k(13);
-- elsif b = '1' and k < 5208 then
-- k <= k + 1;
-- clk_txd <= k(12);
-- elsif c = '1' and k < 20832 then
-- k <= k + 1;
-- clk_txd <= k(14);
-- else
-- k <= (others => '0');
-- end if;
-- end if;
-- end process;
process (clk) -- , reset)
begin
clk_txd <= clk; -- if simply a concurrent assignment statement this
end process; -- would look similar to the elaborated equivalent
-- process. The difference, no sensitivity list and
-- an explict wait on clk statement at the end.
-- This process wants to be removed and replaced by
-- the above commented out process for synthesis
process (clk_txd, reset) -- , reset, enable) -- enable a reset?
begin
-- if enable = '0' then
if reset = '1' then -- puts q counter in known state for simulation
q <= "00000000";
elsif rising_edge(clk_txd) then
if q /= 255 then -- stop after sending once
q <= q + 1;
end if;
end if;
end process;
-- enable <= '1' when q <= 255 else '0'; -- this appears incorrect
enable <= '1' when q(3 downto 0) = "0010" else
'0';
clear <= '1' when q(3 downto 0) = "0001" else
'0';
-- USING ONE COUNTER requires some clocks output MARKS
-- (idle bits) each 16 clocks. It requires the load (enable)
-- occur once every 16 clocks.
-- q(3 downto 0) is selected for enable to prevent outputting spaces
-- TxD during reset (q is reset to all '0's). This would cause a receive
-- framing error.
process (q(7 downto 4))
begin
case q(7 downto 4) is
when "0000" => data <= x"40";
when "0001" => data <= x"41";
when "0010" => data <= x"42";
when "0011" => data <= x"43";
when "0100" => data <= x"44";
when "0101" => data <= x"45";
when "0110" => data <= x"46";
when "0111" => data <= x"47";
when "1000" => data <= x"48";
when "1001" => data <= x"49";
when "1010" => data <= x"50";
when "1011" => data <= x"51";
when "1100" => data <= x"52";
when "1101" => data <= x"53";
when "1110" => data <= x"54";
when "1111" => data <= x"55";
when others => data <= x"56";
end case;
end process;
process (clk_txd) -- , enable, data) -- synchronous enable and clear
begin
-- if enable = '1' then -- this appears incorrect
-- qtxd <= data;
if reset = '1' then
qtxd <= (others => '1'); -- outputs mark after reset
elsif rising_edge(clk_txd) then
if clear = '1' then -- synchronous clear for start bit
qtxd(0) <= '0';
elsif enable = '1' then -- synchronous load
qtxd <= data;
else
qtxd <= '1' & qtxd(7 downto 1); -- shift right
end if;
end if;
end process;
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
txd <= qtxd(0);
txdosc <= qtxd(0);
end architecture behavioral;
The comment table:
-- the synchronous load prevents the first start bit from being stretched
-- q(3 downto 0) the following in hex notation
-- q(3 downto 0) = 2 is the start bit
-- = 3 is data(0)
-- ...
-- = A is data(7)
-- = B is the stop bit
-- = C - 1 are mark (idle) bits (q(3 downto 0) rolls over)
-- = 1 enable occurs loading qtxd
--
-- The offset is caused by synchronous load (1 clk_txd) and the load point
-- (q(3 downto 0) = 1 in enable term).
--
-- The load point wants to occur in the first 6 counts of q(3 downto 0) to
-- insure a trailing mark when q is stopped.
--
-- q(3 downto 0) = 1 is selected for enable to prevent spurious spaces
-- during reset from causing a receive framing error.
tells you where to find bits of the data(q(7 downto 0)) selected character. In the following waveform q is shown as hex to match:
You'll find with the fixes the first character transmitted is 0x40, the second 0x41,...

VHDL 8-bit multiplier, 3-bit input and 4-bit input, how to compensate for number of bits in output?

I have been working on a vhdl program that accepts 2 inputs, a 3-bit input and a 4-bit input. The 3-bit input represents "2 to the power of n", ie an input of 010(which is 2) would equal 2^2=4. An input of 110(which is 6) would yield 2^6 which is 64. This is to be multiplied by a 4-bit input from 0000 to 1111, and the answer stored as 8-bits. However, when I try to solve for this in VHDL, I keep getting the error "Expression error at midterm_q_one.vhd(34): expression has 12 elements, but must have 8 elements". I am new to VHDL, and searching online has yielded little result. I want a way for my output, in this case hex, to store the product of my 2 inputs as an 8 bit value but don't know how. Any help would be greatly appreciated and below is my code. Thanks!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity midterm_q_one is
port(en: in std_logic;
reset: in std_logic;
three_bit: in std_logic_vector(2 downto 0);
four_bit: in std_logic_vector(3 downto 0);
hex: out std_logic_vector(7 downto 0)
);
end midterm_q_one;
architecture arch of midterm_q_one is
signal temp : std_logic_vector(7 downto 0);
begin
process(en, reset, three_bit, four_bit)
begin
if(reset = '1') then
temp <= "00000000";--reset to decimal 0
elsif(en = '1') then
case three_bit is
when "000" => temp <= "00000001";--1
when "001" => temp <= "00000010";--2
when "010" => temp <= "00000100";--4
when "011" => temp <= "00001000";--8
when "100" => temp <= "00010000";--16
when "101" => temp <= "00100000";--32
when "110" => temp <= "01000000";--64
when "111" => temp <= "10000000";--128
end case;
end if;
hex <= temp * four_bit;
end process;
end arch;
Multiplication of the 8-bit temp with the 8-bit four_bit gives a 12-bit result, which is assigned to the 8-bit hex, thus the error message "expression has 12 elements, but must have 8 elements".
Suggestion: Get ridge of the non-standard (Synopsys) STD_LOGIC_ARITH and STD_LOGIC_UNSIGNED, and start using the standard numeric_std package.
With the numeric_std you can resize the result using:
library ieee;
use ieee.numeric_std.all;
...
hex <= std_logic_vector(resize(unsigned(temp) * unsigned(four_bit), hex'length));
I could see two ways to get rid of the error.
The simplest is:
architecture simple of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
begin
if reset = '1' then
hex <= (others => '0');
elsif en = '1' then
hex <= SHL("0000" & four_bit, three_bit);
end if;
end process;
end architecture;
This still requires some knowledge of what 8 bit's you want, or whether you want the value to clamp to x"FF" or whether you want the 8 bit best product:
architecture best_product of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
variable intermed: std_logic_vector (11 downto 0);
begin
if reset = '1' then
intermed := (others => '0');
elsif en = '1' then
intermed := SHL("0000" & four_bit, three_bit);
end if;
hex <= intermed(11 downto 4);
end process;
end architecture;
Clamping:
architecture saturate_clamp of midterm_q_one is
begin
process (en, reset, four_bit, three_bit)
variable intermed: std_logic_vector (11 downto 0);
begin
if reset = '1' then
intermed := (others => '0');
elsif en = '1' then
intermed := SHL("0000" & four_bit, three_bit);
end if;
if intermed(11) = '1' or intermed(10) = '1' or
intermed(9) = '1' or intermed(8) = '1' then
hex <= x"FF";
else
hex <= intermed(7 downto 0);
end if;
end process;
end architecture;
What are the 8 bits supposed to represent mathematically?

Trying to make a 4-bit multiplier in VHDL with 3x4 keypad input and 2x16 LCD to be implemented on a Spartan 3E board

everyone. I'm trying to make a 4-bit multiplier in VHDL. It is to be implemented on a Spartan 3E board using the built-in 2x16 LCD and a 3x4 keypad through a C922 IC.
Using it goes like this: user inputs a number through the keypad, presses a button for confirmation, enters a second number, presses the confirmation button again, and the product shows up on the LCD.
So far, the codes for the keypad+c922 and the LCD are okay. The code for the multiplier is almost okay. The problem is that the confirmation button only works when another number (which is not ultimately used) is pressed.
Here is my code. Following at are screenshots of the Xilinx simulation
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity multi_4bit is
Port ( CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
Input : in STD_LOGIC_VECTOR (3 downto 0);
DAVBL : in STD_LOGIC;
Confirm : in STD_LOGIC;
Output : out STD_LOGIC_VECTOR (7 downto 0));
end multi_4bit;
architecture Behavioral of multi_4bit is
type state is (R,S0,S1,S2,S3,S4);
signal pstate, nstate: state;
signal A_sig, B_sig: STD_LOGIC_VECTOR(3 downto 0);
begin
state_transition: process(CLK,RESET)
begin
if RESET = '1' then
pstate <= R;
elsif rising_edge(CLK) then
pstate <= nstate;
end if;
end process;
nstate_output: process(pstate,DAVBL,Input)
variable temp_var: STD_LOGIC_VECTOR(3 downto 0);
variable tempMult_var,tempProd_var: STD_LOGIC_VECTOR(7 downto 0);
begin
case pstate is
when R =>
nstate <= S0;
tempMult_var := (others => '0');
tempProd_var := (others => '0');
A_sig <= (others => '0');
B_sig <= (others => '0');
Output <= (others => '0');
when S0 =>
nstate <= S0;
if (DAVBL = '1') then
A_sig <= Input;
nstate <= S1;
end if;
when S1 =>
nstate <= S1;
if (Confirm = '1') then
nstate <= S2;
end if;
when S2 =>
nstate <= S2;
if (DAVBL = '1') then
B_sig <= Input;
nstate <= S3;
end if;
when S3 =>
nstate <= S3;
if (Confirm = '1') then
nstate <= S4;
end if;
when S4 =>
nstate <= S0;
for x in 0 to 3 loop
temp_var := (A_sig AND (B_sig(x)&B_sig(x)&B_sig(x)&B_sig(x) ) );
tempMult_var := "0000" & temp_var;
if (x=0) then tempMult_var := tempMult_var;
elsif (x=1) then tempMult_var := tempMult_var(6 downto 0)&"0";
elsif (x=2) then tempMult_var := tempMult_var(5 downto 0)&"00";
elsif (x=3) then tempMult_var := tempMult_var(4 downto 0)&"000";
end if;
tempProd_var := tempProd_var + tempMult_var;
end loop;
Output <= tempProd_var;
tempProd_var := (others => '0');
end case;
end process;
end Behavioral;
The simulation when no number is pressed with the confirmation button:
The simulation when a number is pressed with the confirmation button:
I've been going through my code for an hour now but still can't see what's wrong.
Thanks in advance to anyone who can help.
As mentioned by fru1tbat, Brian, and David, you have a problem with the sensitivity list in the combinatorial portion of your state machine. Specifically, you are missing the Confirm input. Since the Confirm input is not in the sensitivity list, the state machine will not "wake up" to evaluate new outputs/state transitions when confirm changes state. You need to wait for another condition (a different button press) in order to evaluate properly and update the output.
There are multiple ways that this can be resolved.
You can make sure you have a complete sensitivity list for your state machine logic
With VHDL-2008, you can use process(all) to automatically list all necessary inputs in the sensitivity list (your compiler support may vary).
You can choose to use a "single process state machine" style, which avoids this issue. However, different styles of state machines have their strengths and pitfalls that need to be considered.

Trying to show one cycle of 8 bit LFSR with VHDL

I'm trying to do a VHDL code with the objective to make a 8 bit LFSR and show all the random states, and after one cycle (when the last state be the same seed value) it stop. But I'm have a problems, keep saying: "loop must terminate within 10,000 iterations". I'm using Quartus II-Altera.
Code:
entity lfsr_8bit is
--generic ( n : integer := 2**8 );
port (
clk : in bit;
rst : in bit;
lfsr : out bit_vector(7 downto 0)
);
end lfsr_8bit;
architecture behaviour of lfsr_8bit is
--signal i : integer := 0;
--signal seed : bit_vector(7 downto 0) := "10000000";
signal rand : bit_vector(7 downto 0);
begin
ciclo : process (clk,rst)
begin
loop
if (rst='0') then
rand <= "10000000";
elsif (clk'event and clk='1') then
rand(0) <= rand(6) xor rand(7);
rand(7 downto 1) <= rand(6 downto 0);
end if;
-- wait until rand = "10000000" for 100 ns;
exit when rand = "10000000";
-- case rand is
-- when "10000000" => EXIT;
-- when others => NULL;
-- end case;
-- i <= i +1;
end loop;
lfsr <= rand(7 downto 0);
end process ciclo;
end behaviour;
Thank you for all help.
Get rid of that loop, that loop does not work the way you think it does! Stop thinking like a software designer and think like a hardware designer. Loops in hardware are used to replicate logic. So that loop of yours is literally trying to generate 10,000 LFSRs!
I don't believe that you need to be using that loop there at all. If you remove it your LFSR should work as intended. You may need to add a control signal to enable/disable the LFSR, but definitely do not use a loop.
Here's some example code demonstrating this. Change the default value of rand to something else or the LFSR will never run! It will immediately set the lfsr_done signal.
ciclo : process (clk,rst)
begin
if (rst='0') then
rand <= "10000000"; -- SET THIS TO SOMETHING DIFFERENT
lfsr_done <= '0';
elsif (clk'event and clk='1') then
if rand = "10000000" then
lfsr_done <= '1';
end if;
if lfsr_done = '0' then
rand(0) <= rand(6) xor rand(7);
rand(7 downto 1) <= rand(6 downto 0);
end if;
end if;

Trouble running decimal numbers on 7 segment

I am a beginner so please excuse my code logic. I am trying to diplay 20 values on a 7 segment through a counter. When the value is greater than 9 the second segment is selected. When I run this code my first segment flickers very fast and the second one goes off. I know I have done some mistake with the case where i have assigned values to the segment. What am i missing here? My prescaled value is 48Hz. any ideas?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity counter is
Port ( clk : in STD_LOGIC;
segment : out STD_LOGIC_VECTOR (6 downto 0);
anode: out std_logic_vector (3 downto 0) );
end counter;
architecture Behavioral of counter is
constant prescaler: STD_LOGIC_VECTOR(16 downto 0) := "00000000000110000";
signal prescaler_counter: STD_LOGIC_VECTOR(16 downto 0) := (others => '0');
signal counter: std_logic_vector (19 downto 0):= (others => '0');
signal r_anode: std_logic_vector (3 downto 0):= (others => '0');
begin
process (clk) begin
if (clk'event and clk = '1') then
prescaler_counter <= std_logic_vector (unsigned(prescaler_counter) + 1);
if(prescaler_counter = prescaler) then
counter <= std_logic_vector (unsigned(counter)+1);
end if;
end if;
end process;
anode <= r_anode;
process (counter) begin
if (counter > "00000000000000001001") then
r_anode <= "1110";
else
r_anode <= "1101";
end if;
case counter is
when "00000000000000000000" => segment <= "0000001"; --0
when "00000000000000000001" => segment <= "1001111"; --1
when "00000000000000000010" => segment <= "0010010"; --2
when "00000000000000000011" => segment <= "0000110"; --3
when "00000000000000000100" => segment <= "1001100"; --4
when "00000000000000000101" => segment <= "0100100"; --5
when "00000000000000000110" => segment <= "0100000"; --6
when "00000000000000000111" => segment <= "0001111"; --7
when "00000000000000001000" => segment <= "0000000"; --8
when "00000000000000001001" => segment <= "0000100"; --9
when others => segment <= "1111111";
end case;
end process;
end Behavioral;
48Hz still seems pretty fast to cycle through 10 values for a digit, but if that's what you want... (if you slowed it down, the problem might become more obvious, by the way)
The problem is a combination of your count process, how you're setting r_anode, and your case statement to determine the value of segment, possibly among other things.
Your count process goes from 1 to, well, a lot, and you only want to go to 20, as I understand it. You may want to consider adding a wraparound condition. That depends on how you do the following, though.
r_anode is "1110" for 10 clocks and then "1101" for the rest of the 2^20 cycles. I don't think this is what you want. By the way, with numeric_std, you can just write unsigned(counter) > 9 - I'm not sure what you have written should even compile (you were using std_logic_unsigned before, I gather?).
This is the main problem. You seem to want the values for both of your digits to depend on this one counter, but you are comparing the entire 20-bit counter value, so segments are only active for 10 clocks out of 2^20, and only on for the first digit, since you're explicitly checking only values 0 through 9. What you need is some sort of a modulus operation (or separate counters for each digit, or something).
You may also need to think about how you are driving the two displays, but that depends on how you fix the other issues.
I was in the middle of getting this ready to display when fru1bat answered. It may provide illumination:
Note I used a 10 ns clock for sake of expediency.
The first digit goes through it's counts (seen on segment) then switches to the other digit, who's segments show the others choice):
process (counter)
begin
if (counter > "00000000000000001001") then
r_anode <= "1110";
else
r_anode <= "1101";
end if;
case counter is
when "00000000000000000000" => segment <= "0000001"; --0
when "00000000000000000001" => segment <= "1001111"; --1
when "00000000000000000010" => segment <= "0010010"; --2
when "00000000000000000011" => segment <= "0000110"; --3
when "00000000000000000100" => segment <= "1001100"; --4
when "00000000000000000101" => segment <= "0100100"; --5
when "00000000000000000110" => segment <= "0100000"; --6
when "00000000000000000111" => segment <= "0001111"; --7
when "00000000000000001000" => segment <= "0000000"; --8
when "00000000000000001001" => segment <= "0000100"; --9
when others => segment <= "1111111";
end case;
end process;
From that we can imagine you'll see every segment in the 'fast' digit flicker, followed by a long interval waiting for counter to roll over, then flicker again.
Both the prescaler counter and counter seem too long.
You want to switch through enabled anodes, meaning the switch should be between one digit and the other. That should be a bit faster than 48 Hz more than likely. (LCD or LED?).
You want the counter that drives segment to be much slower. Start out with 48 Hz to switch anode values between the two display digits using counter's LSB. Use bits from toward the other end of counter to drive the seven segement conversion. You want the digits to change slow enough to see. Also note that because counter isn't a BCD counter (now there's an idea), there will be blank displayed times for any four bits when those are greater than 9 as an aggregate.
You could always drive 0,1,2,3,4,5,6,7,8,9,A,b,C,d,E,F (by modifying your case statement). This will allow you to pick a prescaler value that gives you minimum flicker.
I don't recommend simply simulating your design, I did it to make the same points fru1bat covered. I wanted the picture. I stopped it about 1/10th of the way through (was going to run for 2 seconds, got 186 MB of clock transitions as it is).
I posted this code and I figured out my errors thanks to #fru1bat and #David. Yes I was using a 20 bit counter which was really dumb of me so i used a 5 bit counter and slowed my clock with this delay code.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity delay is
Port ( clk : in STD_LOGIC;
a : in STD_LOGIC_VECTOR (31 downto 0);
flag : out STD_LOGIC);
end delay;
architecture Behavioral of delay is
signal count :integer:=0;
begin
process(clk) begin
if(clk'event and clk='1') then
count <= count +1; --increment counter.
end if;
--see whether counter value is reached,if yes set the flag.
if(count = to_integer (unsigned(a))) then
count <= 0;
flag <='1';
else
flag <='0';
end if;
end process;
end Behavioral
And then I used this code in my 7 segment code, which for now turns on only one segment, it starts form 0 and goes till 9, after reaching 9 the counter resets. Now my question is how should I display two digits? Should I use the double dabble algorithm here? Or what? My basic issue of flickering is gone now I need to turn on the second segment to display two digits using this same code. How should i modify my code? Any ideas? Here is my final one digit code!
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity counter is
Port ( clk : in STD_LOGIC;
segment : out STD_LOGIC_VECTOR (6 downto 0);
anode: out std_logic_vector (3 downto 0) );
end counter;
architecture Behavioral of counter is
component delay
Port ( clk : in STD_LOGIC;
a : in STD_LOGIC_VECTOR (31 downto 0);
flag : out STD_LOGIC);
end component;
signal flag : std_logic :='0';
signal delay_needed : std_logic_vector(31 downto 0);
constant countvalue: STD_LOGIC_VECTOR (4 downto 0) := "01001";
signal counter: std_logic_vector (4 downto 0):= (others => '0');
signal r_anode: std_logic_vector (3 downto 0):= (others => '0');
begin
delay_needed <= "00000001011111010111100001000000"; --25000000 in binary
inst_delay : delay port map(clk,delay_needed,flag);
process (flag) begin
if (flag'event and flag = '1') then
counter <= std_logic_vector (unsigned(counter)+1);
if (counter = countvalue) then
counter <= (others => '0');
end if;
end if;
end process;
anode <= r_anode;
r_anode <= "1110";
process (counter, r_anode) begin
case r_anode is
when "1110" => case counter is
when "00000" => segment <= "0000001"; --0
when "00001" => segment <= "1001111"; --1
when "00010" => segment <= "0010010"; --2
when "00011" => segment <= "0000110"; --3
when "00100" => segment <= "1001100"; --4
when "00101" => segment <= "0100100"; --5
when "00110" => segment <= "0100000"; --6
when "00111" => segment <= "0001111"; --7
when "01000" => segment <= "0000000"; --8
when "01001" => segment <= "0000100"; --9
when others => segment <= "1111111";
end case;
when others => segment <= "1111111";
end case;
end process;
end Behavioral;

Resources