I have to develop a SDRAM controller for a class project in VHDL. But this is my first time working with VHDL, that has a very important learning curve.
I have downloaded a SDRAM controller from github (https://github.com/christianmiyoshi/SDRAM_Controller_VHDL/blob/master/sdram_controller.vhd) and I am trying to complete it.
I am trying to write a data in an address and later read it, but I cant read a single data. I dont know if my problem is in the writing or in the reading process.
Can anybody help me, please?
Thank you all!
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity ram_controller is
port(
clk : in std_logic;
reset: in std_logic;
refresh: in std_logic;
read_write_enable: in std_logic;
write_n: in std_logic;
address: in std_logic_vector(21 downto 0);
data_in: in std_logic_vector(15 downto 0);
dqmu: in std_logic;
dqml: in std_logic;
ready: out std_logic;
done: out std_logic;
data_out: out std_logic_vector(15 downto 0);
single_burst: in std_logic; --0 single y 1 burst
SDRAM_CKE: out std_logic;
SDRAM_CS_N: out std_logic;
SDRAM_RAS_N: out std_logic;
SDRAM_CAS_N: out std_logic;
SDRAM_WE_N: out std_logic;
SDRAM_BA: out std_logic_vector(1 downto 0);
SDRAM_SA: out std_logic_vector(11 downto 0);
SDRAM_DQ: inout std_logic_vector(15 downto 0);
SDRAM_DQM: out std_logic_vector(1 downto 0)
);
end entity;
architecture behavior of ram_controller is
type state_type is (init_ckeLow, init_stableClock, init_wait, init_nopCommand, init_prechargeAll, init_refresh_1, init_mode, init_refresh_2, idle, refresh_state, activate_row, activate_rcd, read_write, ras1, ras2, precharge);
signal state: state_type := init_ckeLow;
signal ticks: std_logic_vector(7 downto 0) := (others => '0');
signal ticks_ref: integer := 0;
signal ticks_ref_refresh: integer := 0;
constant burstMode: std_logic := '0';
constant casLatency: std_logic_vector(2 downto 0) := "010";
constant burstType: std_logic := '0';
constant burstLength: std_logic_vector(2 downto 0) := "000";
--signal highz_output: std_logic:= '0';
constant MODE_REG: std_logic_vector(11 downto 0) := "00" & burstMode & "00" & casLatency & burstType & burstLength;
constant MODE_REG_BURST: std_logic_vector(11 downto 0) := "000000100111";
signal command: std_logic_vector(3 downto 0);
signal row: std_logic_vector(11 downto 0);
signal column: std_logic_vector(7 downto 0);
signal bank: std_logic_vector(1 downto 0);
signal sd_busdir_x: std_logic:='0';
-- Command truth table
-- CS_N, RAS_N, CAS_N, WE_N
constant CMD_ACTIVATE: std_logic_vector(3 downto 0) := "0011";
constant CMD_PRECHARGE: std_logic_vector(3 downto 0) := "0010";
constant CMD_WRITE: std_logic_vector(3 downto 0) := "0100";
constant CMD_READ: std_logic_vector(3 downto 0) := "0101";
constant CMD_MODE: std_logic_vector(3 downto 0) := "0000";
constant CMD_NOP: std_logic_vector(3 downto 0) := "0111";
constant CMD_REFRESH: std_logic_vector(3 downto 0) := "0001";
signal address_buffer: std_logic_vector(21 downto 0) := (others => '0');
signal data_in_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal dqu_buffer: std_logic := '0';
signal dql_buffer: std_logic := '0';
signal ready_buffer: std_logic := '0';
signal done_buffer: std_logic := '0';
signal data_out_buffer: std_logic_vector(15 downto 0) := (others => '0');
signal CKE: std_logic;
signal CS_N: std_logic;
signal RAS_N: std_logic;
signal CAS_N: std_logic;
signal WE_N: std_logic;
signal BA: std_logic_vector(1 downto 0);
signal SA: std_logic_vector(11 downto 0);
signal DQ: std_logic_vector(15 downto 0);
signal DQM: std_logic_vector(1 downto 0);
signal contador : std_logic_vector(15 downto 0) := x"0000";
signal modo: std_logic := '0';
begin
(CS_N, RAS_N, CAS_N, WE_N) <= command;
SDRAM_CKE <= CKE;
SDRAM_CS_N <= CS_N;
SDRAM_RAS_N <= RAS_N;
SDRAM_CAS_N <= CAS_N;
SDRAM_WE_N <= WE_N;
SDRAM_BA <= BA;
SDRAM_SA <= SA;
--SDRAM_DQ <= DQ;
SDRAM_DQM <= DQM;
--SA <= address_buffer;
SDRAM_DQ <= data_in_buffer when sd_busdir_x = '1' else (others => 'Z');
DQM <= dqu_buffer & dql_buffer;
ready <= ready_buffer;
done <= done_buffer;
data_out <= data_out_buffer;
bank <= address(21 downto 20);
row <= address(19 downto 8);
column <= address(7 downto 0);
process(clk, reset)
begin
if reset = '0' then
state <= init_ckeLow;
ticks_ref <= 0;
elsif rising_edge(clk) then
if ticks_ref /= 0 then
ticks_ref <= ticks_ref - 1;
else
-- Micron datasheet instructions
-- Frequency = 100 Mhz => period of 10ns
-- 1: Apply Vdd and Vddq simultaneously
case state is
when init_ckeLow =>
-- 2: Assert and hold CKE ant LVTTL logic low
ticks_ref <= 10;
CKE <= '0';
state <= init_stableClock;
when init_stableClock =>
-- 3: Provide stable clock
ticks_ref <= 10;
state <= init_wait;
when init_wait=>
-- 4: Wait at least 100us
-- 5: bring cke high at some point of the period
-- with command inhibit or nop
--ticks_ref <= 10000;
ticks_ref <= 2; -- debugadd
state <= init_nopCommand;
when init_nopCommand =>
--ticks_ref <= 10000;
ticks_ref <= 2; -- debug
CKE <= '1';
command <= CMD_NOP;
state <= init_prechargeAll;
when init_prechargeAll =>
-- 6: perform precharge all
-- 7: wait at leas t_RP
command <= CMD_PRECHARGE;
BA <= "00";
SA(10) <= '1'; -- all banks
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_1;
when init_refresh_1 =>
-- auto refresj period: < 64 ns
if ticks_ref_refresh = 0 then
state <= init_mode;
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when init_mode =>
command <= CMD_MODE;
if single_burst = '0' then
SA <= MODE_REG;
modo <= '0';
else
SA <= MODE_REG_BURST;
modo <= '1';
end if;
BA <= "00";
ticks_ref <= 2;
ticks_ref_refresh <= 8;
state <= init_refresh_2;
when init_refresh_2 =>
if ticks_ref_refresh = 0 then
state <= idle;
--done_buffer <= '1';
else
ticks_ref_refresh <= ticks_ref_refresh - 1;
command <= CMD_REFRESH;
ticks_ref <= 7;
end if;
when idle =>
done_buffer <= '0';
contador <= (others => '0');
if read_write_enable = '1' then
-- tras: active to precharge: 45 ns min, 120000ns max
state <= activate_row;
command <= CMD_ACTIVATE;
SA <= row;
BA <= bank;
--done_buffer <= '0';
elsif refresh = '1' then
state <= refresh_state;
command <= CMD_REFRESH;
ticks_ref <= 7;
--done_buffer <= '0';
end if;
when refresh_state =>
state <= idle;
--done_buffer <= '1';
when activate_row =>
--trcd 20 ns
command <= CMD_NOP;
state <= activate_rcd;
data_in_buffer <= data_in;
ticks_ref <= 1;
when activate_rcd =>
-- trcs = 20ns min
state <=read_write;
SA <= "0000" & column;
if write_n = '0' then
command <= CMD_WRITE;
dqu_buffer <= dqmu;
dql_buffer <= dqml;
sd_busdir_x <= '1';
else
command <= CMD_READ;
end if;
when read_write =>
--command <= CMD_NOP;
state <= ras1;
--if modo='0' then
--sd_busdir_x <= '0';
--end if;
when ras1 =>
state <= ras2;
command <= CMD_NOP;
when ras2 =>
-- trp = 20ns min
if modo='1' and contador <= x"00FF" then
data_in_buffer <= data_in;
state <= ras2;
contador <= contador +1;
else
contador <= (others => '0');
state <= precharge;
sd_busdir_x <= '0';
command <= CMD_PRECHARGE;
SA(10) <= '1';
data_out_buffer <= SDRAM_DQ;
ticks_ref <= 2;
end if;
when precharge =>
state <= idle;
done_buffer <= '1';
ticks_ref <= 1;
end case;
end if;
end if;
end process;
end architecture;
[enter image description here][1]
[1]: https://i.stack.imgur.com/CaqqL.png
Related
I have to implement a mini-router in VHDL. The design requirements for this are:
I've written the implementation, and a testbench. However, looking at the simulation waveform, some of my initial signals are undefined and I'm not sure why.
This is the source code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end entity;
architecture arch of mini_router is
signal aux : std_logic_vector(9 downto 0);
signal aux1 : std_logic_vector(1 downto 0);
signal aux2 : std_logic_vector(1 downto 0);
signal aux_valid : std_logic;
signal aux_grant1 : std_logic;
signal aux_grant2 : std_logic;
begin
mini_router: process(clk)
variable r : std_logic:= '1';
begin
-- conta le volte in cui c'è stato data conflict
if rising_edge(clk) then -- chiuso
if reset = '0' then
aux <= (others => '0');
aux_valid <= '0';
aux_grant1 <= '0';
aux_grant2 <= '0';
elsif reset = '1' then
if (req1 xor req2) = '1' then --chiuso -- un solo req è alto
if req1 ='1' then --chiuso
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
else
aux <= data2;
aux_grant1 <= '0';
aux_grant2 <= '1';
aux_valid <= '1';
end if;
----entrambi i req sono alti
elsif (req1 and req2) = '1' then -- chiuso
if ((unsigned(aux1)) > (unsigned(aux2))) then
aux <= data1;
aux_grant1 <= '1';
aux_grant2 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) < (unsigned(aux2))) then
aux <= data2;
aux_grant2 <= '1';
aux_grant1 <= '0';
aux_valid <= '1';
elsif ((unsigned(aux1)) = (unsigned(aux2))) then -- stesso livello di priorità -- alternativa:(aux1 xnor aux2)="11"
if r = '1' then
aux <= data1;
aux_grant1<= '1';
aux_grant2 <= '0';
aux_valid <= '1';
r := not (r);
else
aux <= data2;
aux_grant2 <= '1';
aux_grant1<= '0';
aux_valid <= '1';
r := not (r);
end if;
end if;
elsif (req1 nor req2) = '1' then
aux_valid <= '0';
aux <= (others => '0');
aux_grant1 <= '0';
aux_grant2 <= '0';
end if;
end if; -- if del reset
end if; -- if del clock
end process;
data_out <= aux(9 downto 2);
aux1 <= data1 (1 downto 0);
aux2 <= data2 (1 downto 0);
valid <= aux_valid;
grant1 <= aux_grant1;
grant2 <= aux_grant2;
end architecture;
This is the testbench:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity mini_router_tb is
end mini_router_tb;
architecture arc of mini_router_tb is
constant T_CLK : time := 10 ns; --- frequenza di clock: 125 MHz
signal clk_tb : std_logic := '1';
signal reset_tb : std_logic := '0'; -- reset attivo basso sincrono
signal data1_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req1_tb : std_logic:= '0';
signal grant1_tb : std_logic;
signal data2_tb : std_logic_vector(9 downto 0) := (others => '0');
signal req2_tb : std_logic:= '0';
signal grant2_tb : std_logic;
signal data_out_tb : std_logic_vector(7 downto 0);
signal valid_tb : std_logic;
signal end_sim : std_logic := '1'; -- signal to use to stop the simulation when there is nothing else to test
component mini_router is
port (
clk : in std_logic;
reset : in std_logic; -- synchronous negative reset
data1 : in std_logic_vector(9 downto 0);
req1 : in std_logic;
grant1 : out std_logic;
data2 : in std_logic_vector(9 downto 0);
req2 : in std_logic;
grant2 : out std_logic;
data_out : out std_logic_vector(7 downto 0);
valid : out std_logic
);
end component;
begin
clk_tb <= (not(clk_tb)and(end_sim)) after T_CLK/2;
DUT : mini_router
port map (
clk => clk_tb,
reset => reset_tb,
data1 => data1_tb,
req1 => req1_tb,
grant1 => grant1_tb,
data2 => data2_tb,
req2 => req2_tb,
grant2 => grant2_tb,
data_out => data_out_tb,
valid => valid_tb
);
-- process used to make the testbench signals change synchronously with the rising edge of the clock
stimuli_process: process(clk_tb,reset_tb)
variable t : integer := 0; -- variabile che conta i cicli di clock
begin
if (rising_edge(clk_tb)) then
case (t) is
when 1 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=0 per il reset
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 2 => reset_tb <= '1';
data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4; data_out=1
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13;
req1_tb <= '1' ; req2_tb<= '0';
when 3 => data1_tb <= (9 downto 3 => '0') & "100"; -- data1= 4;
data2_tb <= (9 downto 4 => '0') & "1101";-- data2= 13; data_out=3
req1_tb <= '0' ; req2_tb<= '1';
when 4 => data1_tb <= (9 downto 5 => '0') & "11100"; --data1=28
data2_tb <= (9 downto 4 => '0') & "1101"; -- data2= 13; data_out=3 priorità maggiore
req1_tb <= '1' ; req2_tb<= '1';
when 5 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1 priorità maggiore
data2_tb <= (9 downto 5 => '0') & "11101"; -- data2= 29;
req1_tb <= '1' ; req2_tb<= '1';
when 6 => data1_tb <= (9 downto 5 => '0') & "00111"; --data1=7; data_out=1
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31;
req1_tb <= '1' ; req2_tb<= '1';
when 7 => data1_tb <= (9 downto 5 => '0') & "00111"; --data_out=0;
data2_tb <= (9 downto 5 => '0') & "11111";
req1_tb <= '0' ; req2_tb<= '0';
when 8 => data1_tb <= (9 downto 5 => '0') & "10111"; --data1=7; data_out non assunto=5
data2_tb <= (9 downto 5 => '0') & "11111"; -- data2= 31; data_out=7
req1_tb <= '1' ; req2_tb<= '1';
when 9 => end_sim <= '0'; -- stops the simulation when t = 10
when others => null; -- non accade nulla negli altri casi
end case;
t := t + 1;
end if;
end process;
end architecture;
Your reset logic is synchronous, because the outmost condition is rising_edge(clk). Therefore the internal signals are undefined until the first raising edge of the clock.
Change to an asynchronous reset like this (excerpt):
if reset = '0' then
-- reset statements
elsif rising_edge(clk) then
-- work statements
end if;
Please be aware that even with an asynchronous reset the signals will be undefined until reset is activated or the clock raises. This reflects the actual behavior of a real device.
The reason your signals are initially set to U or X is because the values of all signals, variables, etc. are initialized to the left hand side of the type definition.
From the IEEE 1076 code (see here):
-------------------------------------------------------------------
-- logic state system (unresolved)
-------------------------------------------------------------------
type STD_ULOGIC is ( 'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-' -- Don't care
);
--------------------------------
And std_logic is just a resolved version of std_ulogic. So any signal of type std_logic will have its default value be U, unless set otherwise.
Consider the following code:
signal A : std_logic;
signal B : std_logic := '1';
Signal A would be U until set otherwise. Signal B will be 0 until set otherwise.
This is why you are seeing U in your simulation. (As for X you see in your waveform window, many simulators that collapse vectors into a single value in the waveform view treat collections with U as X. Expand that vector and I suspect you will see several U's.)
I'm trying to follow an example on my VHDL book. Its name is FPGA Prototyping by VHDL Examples, Pong Chu. It has a Divider Circuit example in Chapter 6, Listing 5. I understood the general idea of a division operation. To verify the module I wrote a testbench and I saw that it doesn't work properly. If anyone could explain to me where the problem is, I would be very appreciated.
Here are the codes of module and testbench.
Module:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Divider is
generic(W: integer := 8;
CBIT: integer := 4 );
Port ( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (W-1 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (W-1 downto 0));
end Divider;
architecture Behavioral of Divider is
type state_type is (idle, op, last, done);
signal state_reg, state_next: state_type;
signal rh_reg, rh_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal rl_reg, rl_next: STD_LOGIC_VECTOR(W-1 downto 0) := (others => '0');
signal rh_temp: UNSIGNED(W-1 downto 0) := (others => '0');
signal d_reg, d_next: UNSIGNED(W-1 downto 0) := (others => '0');
signal n_reg, n_next: UNSIGNED(CBIT-1 downto 0) := (others => '0');
signal q_bit: STD_LOGIC;
begin
-- FSMD State and Data Registers
process(clk, reset)
begin
if reset = '1' then
state_reg <= idle;
rh_reg <= (others => '0');
rl_reg <= (others => '0');
d_reg <= (others => '0');
n_reg <= (others => '0');
elsif rising_edge(clk) then
state_reg <= state_next;
rh_reg <= rh_next;
rl_reg <= rl_next;
d_reg <= d_next;
n_reg <= n_next;
end if;
end process;
-- FSMD Next-State Logic and Data Path Logic
process(state_reg, n_reg, rh_reg, rl_reg, d_reg, start, dvsr, dvnd, q_bit, rh_temp, n_next)
begin
ready <= '0';
done_tick <= '0';
state_next <= state_reg;
rh_next <= rh_reg;
rl_next <= rl_reg;
d_next <= d_reg;
n_next <= n_reg;
case state_reg is
when idle =>
ready <= '1';
if start = '1' then
rh_next <= (others => '0');
rl_next <= dvnd; -- Dividend
d_next <= UNSIGNED(dvsr); -- Divisor
n_next <= TO_UNSIGNED(W+1, CBIT); -- Index
state_next <= op;
end if;
when op =>
--Shift rh and rl left
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp(W-2 downto 0) & rl_reg(W-1);
--Decrease index
n_next <= n_reg - 1;
if(n_next = 1) then
state_next <= last;
end if;
when last =>
rl_next <= rl_reg(W-2 downto 0) & q_bit;
rh_next <= rh_temp;
state_next <= done;
when done =>
state_next <= idle;
done_tick <= '1';
end case;
end process;
-- Compare and Subtract
process(rh_reg, d_reg)
begin
if rh_reg <= d_reg then
rh_temp <= rh_Reg - d_reg;
q_bit <= '1';
else
rh_temp <= rh_reg;
q_bit <= '0';
end if;
end process;
-- Output
quo <= rl_reg;
rmd <= STD_LOGIC_VECTOR(rh_reg);
end Behavioral;
Testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_Divider is
-- Port ( );
end tb_Divider;
architecture Behavioral of tb_Divider is
signal clk, reset, start, ready, done: STD_LOGIC;
signal dvsr, dvnd: STD_LOGIC_VECTOR(7 downto 0);
signal quo, rmd: STD_LOGIC_VECTOR(7 downto 0);
component Divider is
port( clk, reset : in STD_LOGIC;
start : in STD_LOGIC;
dvsr, dvnd : in STD_LOGIC_VECTOR (7 downto 0);
ready, done_tick : out STD_LOGIC;
quo, rmd : out STD_LOGIC_VECTOR (7 downto 0));
end component Divider;
begin
UUT: Divider port map( clk => clk, reset => reset, start => start, dvsr => dvsr, dvnd => dvnd,
ready => ready, done_tick => done, quo => quo, rmd => rmd);
process
begin
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end process;
process
begin
start <= '0';
dvnd <= x"00";
dvsr <= x"00";
wait for 100 ns;
start <= '1';
dvnd <= x"C8";
dvsr <= x"0A";
wait for 10 us;
end process;
end Behavioral;
Result of Testbench:
I'm newbie in FPGAs and VHDL. This time, I m trying to send Data from FPGA to TTL. I' m using GPIO pins for TX and GND and Data can be changed with switch on FPGA. My issue is whenever i press the button on FPGA, I always see FF on terminal. I couldn't find where the problem is.
Here is TX code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector(7 downto 0);
Out_Tx : out std_logic
);
end entity;
Architecture Behavioral of UART_Tx is
constant Baudrate : integer := 9600;
constant CLK_Hiz : integer := 50000000;
constant CLK_Bit : integer := (CLK_Hiz / Baudrate) + 1;
signal tx_Data_ind : integer range 0 to 7;
signal counter_baud : integer range 0 to (CLK_Bit - 1) := 0;
signal shift_button : std_logic_vector (3 downto 0) := (others => '0');
signal button_out : std_ulogic := '1';
signal baud_pulse : std_ulogic := '0';
signal tx_enable : std_ulogic := '0';
signal tx_Data : std_logic_vector (7 downto 0) := (others => '0');
signal tx_cikis : std_ulogic;
signal tx_tamam : std_ulogic := '0';
signal counter_sil : std_ulogic := '0';
begin
process(CLK, Reset)
begin
if (Reset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif (rising_edge(CLK)) then
if (counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if (counter_sil = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, Reset)
begin
if (Reset = '0') then
tx_Data <= (others => '0');
tx_data_ind <= 0;
tx_enable <= '0';
elsif (rising_edge(CLK)) then
tx_cikis <= '1';
out_tx <= tx_cikis;
shift_button(3) <= button;
shift_button(2 downto 0) <= shift_button(3 downto 1);
if shift_button(3 downto 0) = "001" then
button_out <= '0';
end if;
if (button_out = '0') then
counter_sil <= '1';
tx_cikis <= '0';
if (tx_cikis = '0') then
tx_enable <= '1';
end if;
if (tx_enable = '1') then
counter_sil <= '0';
tx_Data <= Data;
if (baud_pulse = '1') then
tx_cikis <= tx_Data(tx_Data_ind);
if (tx_data_ind < 7) then
tx_Data_ind <= tx_Data_ind + 1;
else
tx_tamam <= '1';
end if;
if (tx_tamam = '1') then
tx_Data <= (others => '0');
tx_Data_ind <= 0;
tx_enable <= '0';
button_out <= '1';
tx_cikis <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
end Architecture;
Here is Testbench code:
library ieee;
use ieee.std_logic_1164.all;
entity tb_UART_Tx is
end tb_UART_Tx;
architecture tb of tb_UART_Tx is
component UART_Tx
port (CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector (7 downto 0);
Out_Tx : out std_logic);
end component;
signal CLK : std_logic:='0';
signal Reset : std_logic:='1';
signal Button : std_logic:='1';
signal Data : std_logic_vector (7 downto 0);
signal Out_Tx : std_logic;
constant TbPeriod : time := 20 ns;
signal TbSimEnded : std_logic := '0';
begin
dut : UART_Tx
port map (CLK => CLK,
Reset => Reset,
Button => Button,
Data => Data,
Out_Tx => Out_Tx);
clk_process: process
begin
CLK <= '0';
wait for TbPeriod/2;
CLK <= '1';
wait for TbPeriod/2;
end process;
stimuli : process
begin
Reset <= '0';
wait for 20 ns;
Button <= '1';
Data <= "00110000";
wait for 30 ns;
Button <= '0';
wait for 50 ns;
Button <= '1';
wait for 1000 ns;
-- Button <= '0';
-- wait for 30 ns;
-- Button <= '1';
TbSimEnded <= '1';
wait;
end process;
end tb;
configuration cfg_tb_UART_Tx of tb_UART_Tx is
for tb
end for;
end cfg_tb_UART_Tx;
Added Testbench results
EDIT: HERE is the working code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK: in std_logic;
nReset: in std_logic;
nButton: in std_logic;
Data: in std_logic_vector (7 downto 0);
Data_Tx: out std_logic
);
end UART_Tx;
architecture Behavioral of UART_Tx is
constant Baudrate: integer:= 9600;
constant CLK_Hiz: integer:= 50000000;
constant CLK_Bit: integer:= (CLK_Hiz / Baudrate) + 1;
signal tx_counter: integer range 1 to 9:= 1;
signal counter_baud: integer range 0 to (CLK_Bit - 1):= 0;
signal shift_nButton:std_logic_vector (3 downto 0):= (others => '1');
signal tx_reg: std_logic_vector (7 downto 0):= (others => '0');
signal nButton_out: std_ulogic:= '1';
signal baud_pulse: std_ulogic;
signal tx_out: std_ulogic:= '1';
signal counter_del: std_ulogic;
signal start_bit: std_ulogic:='0';
signal data_bit: std_ulogic:='0';
signal stop_bit: std_ulogic:='0';
begin
process(CLK,nReset)
begin
if(nReset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif(rising_edge(CLK)) then
if(counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if(counter_del = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, nReset)
begin
Data_Tx <= tx_out;
if(nReset = '0') then
tx_reg <= (others => '0');
tx_counter <= 1;
elsif(rising_edge(CLK)) then
shift_nButton(3) <= nButton;
shift_nButton(2 downto 0) <= shift_nButton(3 downto 1);
if shift_nButton(2 downto 0) = "001" then
nButton_out <= '0';
counter_del <= '1';
start_bit <= '1';
end if;
if(nButton_out = '1') then
tx_out <= '1';
elsif(nButton_out = '0') then
counter_del <= '0';
if(start_bit = '1') then
tx_out <= '0';
tx_reg <= Data;
if(baud_pulse = '1') then
start_bit <= '0';
data_bit <= '1';
end if;
end if;
if(data_bit = '1')then
if(tx_counter > 0 and tx_counter < 10) then
tx_out <= tx_reg((tx_counter)-1);
if(baud_pulse = '1') then
tx_counter <= tx_counter + 1;
if(tx_counter = 9)then
data_bit <= '0';
stop_bit <= '1';
end if;
end if;
end if;
end if;
if(stop_bit = '1') then
tx_out <= '1';
tx_counter <= 1;
if(baud_pulse = '1') then
stop_bit <= '0';
nButton_out <= '1';
tx_reg <= (others => '0');
end if;
end if;
end if;
end if;
end process;
end Behavioral;
I have a mega-assignment and the last part(for extra marks) is to display the output of a designed ALU using two 7-seg displays. These should display the result of the operations performed in the ALU. I am performing logical and arithmetic operations and I can only use the lower display for logical operations. For the arithmetic operations I need to use BCD code to display the answers. My ALU is working fine, I am finding it hard to do the decoder part. I don't even know if I am on the right track. Help!
CODE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
entity codeALU is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
Cin : in STD_LOGIC;
S0 : in STD_LOGIC;
S1 : in STD_LOGIC;
M : in STD_LOGIC;
Cout : out STD_LOGIC;
Z : out STD_LOGIC;
F : out STD_LOGIC_VECTOR (3 downto 0);
bcd1 : out STD_LOGIC_VECTOR (6 downto 0);
bcd2 : out STD_LOGIC_VECTOR (6 downto 0));
end codeALU;
architecture Behavioral of codeALU is
begin
process(A, B, M, Cin, S1, S0)
variable temp : STD_LOGIC_VECTOR (4 downto 0);
variable Fx : STD_LOGIC_VECTOR (3 downto 0);
variable Cx, Zx : STD_LOGIC;
variable Sel : STD_LOGIC_VECTOR (2 downto 0);
begin
Sel := S1 & S0 & Cin;
Cx := '0';
Zx := '0';
if M = '0' then
Z <= '0';
case Sel(2 downto 1) is
when "00" =>
Fx := A AND B;
Zx := '0';
when "01" =>
Fx := A XOR B;
when "10" =>
Fx := A OR B;
when "11" =>
Fx := A XNOR B;
when others =>
null;
end case;
case Fx is
when "0000"=> bcd1 <="0000001"; -- '0'
when "0001"=> bcd1 <="1001111"; -- '1'
when "0010"=> bcd1 <="0010010"; -- '2'
when "0011"=> bcd1 <="0000110"; -- '3'
when "0100"=> bcd1 <="1001100"; -- '4'
when "0101"=> bcd1 <="0100100"; -- '5'
when "0110"=> bcd1 <="0100000"; -- '6'
when "0111"=> bcd1 <="0001111"; -- '7'
when "1000"=> bcd1 <="0000000"; -- '8'
when "1001"=> bcd1 <="0000100"; -- '9'
when others=> bcd1 <="1111111";
end case;
else
case Sel is
when "000" =>
temp := (B(3)&B(3 downto 1) + ('0'&A));
Fx := temp(3 downto 0);
Cx := temp(4);
when "001" =>
temp := (A(3)&A(3 downto 1) + ('0'&B));
Fx := temp(3 downto 0);
Cx := temp(4);
when "010" =>
temp := ('0'&A) + ('0'&B);
Fx := temp(3 downto 0);
Cx := temp(4);
when "011" =>
temp := ('0'&A) + ('0'&B) + ('0'&Cin);
Fx := temp(3 downto 0);
Cx := temp(4);
when "100" =>
temp := ('0'&A) + (not B);
Fx := temp(3 downto 0);
Cx := temp(4);
when "101" =>
temp := (not B) + ('0'&A) + 1;
Fx := temp(3 downto 0);
Cx := temp(4);
when "110" =>
temp := ('0'&A) + ('0'&B(3 downto 1));
Fx := temp(3 downto 0);
Cx := temp(4);
when "111" =>
temp := ('0'&B) + ('0'&A(3 downto 1));
Fx := temp(3 downto 0);
Cx := temp(4);
when others =>
null;
end case;
case Fx is
when "0000"=> bcd2 <="0000001"; -- '0'
when "0001"=> bcd2 <="1001111"; -- '1'
when "0010"=> bcd2 <="0010010"; -- '2'
when "0011"=> bcd2 <="0000110"; -- '3'
when "0100"=> bcd2 <="1001100"; -- '4'
when "0101"=> bcd2 <="0100100"; -- '5'
when "0110"=> bcd2 <="0100000"; -- '6'
when "0111"=> bcd2 <="0001111"; -- '7'
when "1000"=> bcd2 <="0000000"; -- '8'
when "1001"=> bcd2 <="0000100"; -- '9'
when others=> bcd2 <="1111111";
end case;
for i in 0 to 3 loop
Zx := Zx or Fx(i);
end loop;
Z <= not Zx;
end if;
F <= Fx;
Cout <= Cx;
end process;
end Behavioral;
Test Bench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.std_logic_arith.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY test4ALU IS
END test4ALU;
ARCHITECTURE behavior OF test4ALU IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT codeALU
PORT(
A : IN std_logic_vector(3 downto 0);
B : IN std_logic_vector(3 downto 0);
Cin : IN std_logic;
S0 : IN std_logic;
S1 : IN std_logic;
M : IN std_logic;
Cout : OUT std_logic;
Z : OUT std_logic;
F : OUT std_logic_vector(3 downto 0);
bcd1 : OUT std_logic_vector(6 downto 0);
bcd2 : OUT std_logic_vector(6 downto 0)
);
END COMPONENT;
--Inputs
signal A : std_logic_vector(3 downto 0) := (others => '0');
signal B : std_logic_vector(3 downto 0) := (others => '0');
signal Cin : std_logic := '0';
signal S0 : std_logic := '0';
signal S1 : std_logic := '0';
signal M : std_logic := '0';
--Outputs
signal Cout : std_logic;
signal Z : std_logic;
signal F : std_logic_vector(3 downto 0) := (others => '0');
signal bcd1 : std_logic_vector(6 downto 0);
signal bcd2 : std_logic_vector(6 downto 0);
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: codeALU PORT MAP (
A => A,
B => B,
Cin => Cin,
S0 => S0,
S1 => S1,
M => M,
Cout => Cout,
Z => Z,
F => F,
bcd1 => bcd1,
bcd2 => bcd2
);
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
A <= "1001";
B <= "1111";
M <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
wait for 50 ns;
M <= '1';
S1 <= '0';
S0 <= '0';
Cin <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '0';
Cin <= '1';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
Cin <= '0';
wait for 50 ns;
S1 <= '0';
S0 <= '1';
Cin <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
Cin <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '0';
Cin <= '1';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
Cin <= '0';
wait for 50 ns;
S1 <= '1';
S0 <= '1';
Cin <= '1';
wait;
end process;
process
begin
for i in 0 to 9 loop
F <= conv_std_logic_vector(i,4);
wait for 50 ns;
end loop;
end process;
END;
You've issue in your test bench:
Within codeALU entity is F defined as out signal. Within you test bench signal F is used to map F out from component codeALU. In the name less process below in test bench the signal F gets value: F <= conv_std_logic_vector(i,4);
It's unusable behavior. You see it in modelsim as red X's (not defined).
I want to make a FSM model of FIR, for that I need to write FIR calculation code line in FSM implementation.
Here is the actual and correct code for FIR
entity fir_4tap is
port( Clk : in std_logic; --clock signal
Clk_fast : in std_logic;
-- Xin : in signed(7 downto 0); --input signal
bit_in : in std_logic;
bit_out : out std_logic;
Yout : out signed(15 downto 0) --filter output
);
end fir_4tap;
architecture Behavioral of fir_4tap is
signal add_out3 : signed(15 downto 0) := (others => '0');
signal index : unsigned(2 downto 0) := (others =>'0');
signal counter : unsigned(3 downto 0) := (others => '0');
signal p : unsigned(1 downto 0) := (others => '0');
signal k : unsigned(1 downto 0) := (others => '0');
signal j : unsigned(1 downto 0) := (others => '0');
type array_signed is array(8 downto 0) of signed(7 downto 0);
signal z : array_signed := (others => "00000000");
type array_signed1 is array(3 downto 0) of signed(7 downto 0);
signal H : array_signed1 := (others => "00000000");
signal Xin : array_signed1 := (others => "00000000");
begin
z(0) <= to_signed(-3,8);
z(1) <= to_signed(1,8);
z(2) <= to_signed(0,8);
z(3) <= to_signed(-2,8);
z(4) <= to_signed(-1,8);
z(5) <= to_signed(4,8);
z(6) <= to_signed(-5,8);
z(7) <= to_signed(6,8);
z(8) <= to_signed(0,8);
H(0) <= to_signed(-2,8);
H(1) <= to_signed(-1,8);
H(2) <= to_signed(3,8);
H(3) <= to_signed(4,8);
process (clk)
begin
if (rising_edge(Clk)) then
index <= index +1;
if (index = "111") then
Xin(to_integer(p)) <= z(to_integer(counter)); k <= p;
p <= p + 1;
***-- This part of the code has problem, I want to write the line which is summing --up for add_out3 in a for loop.***
add_out3 <= (others => '0');
add_out3 <= Xin(to_integer(k))*H(to_integer(j)) + Xin(to_integer(k-1))*H(to_integer(j+1)) + Xin(to_integer(k-2))*H(to_integer(j+2)) + Xin(to_integer(k-3))*H(to_integer(j+3));
Yout <= add_out3;
end if;
end if;
end process;
end Behavioral;
Now Below is the FSM implementation try by me but not getting the same out sample as input can somebody tell me what could be the problem in the code?
----------------FSM implementation of the FIR filter ----------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity test is
port( Clk : in std_logic; --clock signal
Clk_fast : in std_logic;
bit_in : in std_logic;
bit_out : out std_logic;
Yout : out signed(15 downto 0) --filter output
);
end test;
architecture Behavioral of test is
signal data_buffer : signed(7 downto 0) := (others => '0');
signal index : unsigned(2 downto 0) := (others =>'0');
signal counter : unsigned(3 downto 0) := (others => '0');
type array_signed is array(8 downto 0) of signed(7 downto 0);
signal z : array_signed := (others => "00000000");
type array_signed1 is array(3 downto 0) of signed(7 downto 0);
signal H : array_signed1 := (others => "00000000");
signal input : signed(7 downto 0) := (others => '0');
type MULT_TYPE is array(3 downto 0) of signed(15 downto 0);
signal MULT_array : MULT_TYPE := (others => "0000000000000000");
type ADD_TYPE is array(3 downto 0) of signed(15 downto 0);
signal ADD_array : ADD_TYPE := (others => "0000000000000000");
constant ZERO : signed(15 downto 0) := (others => '0');
type state_type is (s0,s1,s2,s3); --type of state machine.
signal current_s : state_type := s0; --current and next state declaration.
signal next_s : state_type := s0;
signal reset : std_logic := '0';
signal go : std_logic := '0';
signal change_state : std_logic := '0' ;
signal counter_FSM_monitor : unsigned( 6 downto 0) := "0000000";
begin
z(0) <= to_signed(-3,8);
z(1) <= to_signed(1,8);
z(2) <= to_signed(0,8);
z(3) <= to_signed(-2,8);
z(4) <= to_signed(-1,8);
z(5) <= to_signed(4,8);
z(6) <= to_signed(-5,8);
z(7) <= to_signed(6,8);
z(8) <= to_signed(0,8);
H(0) <= to_signed(-2,8);
H(1) <= to_signed(-1,8);
H(2) <= to_signed(3,8);
H(3) <= to_signed(4,8);
process (Clk) is
begin
if falling_edge(Clk) then
data_buffer(to_integer(index)) <= bit_in;
index <= index +1;
if (index = "111") then
input <= z(to_integer(counter));
counter <= counter + 1;
if(counter = "1000") then
counter <= "0000";
end if;
end if;
end if;
end process;
process (clk_fast)
begin
if (falling_edge(clk_fast)) then
counter_FSM_monitor <= counter_FSM_monitor + 1;
if( to_integer(counter_FSM_monitor) = 76) then
counter_FSM_monitor <= "0000000";
end if;
case change_state is
when '1' =>
current_s <= next_s; --state change.
when '0' => --current_s <= s0;
when others =>
end case;
end if;
end process;
Process(current_s,input)
begin
if ( to_integer(counter_FSM_monitor) < 64 ) then
-- waiting for the Input
elsif (to_integer(counter_FSM_monitor) >= 64 and to_integer(counter_FSM_monitor) < 76) then
---------------------------------------------- FSM ----------------------------------------
case current_s is
when s0 =>
mult_array(0) <= input*H(3);
ADD_array(0) <= ZERO + mult_array(0);
next_s <= s1;
change_state <= '1';
when s1 =>
mult_array(1) <= input*H(2);
ADD_array(1) <= mult_array(1) + ADD_array(0);
next_s <= s2;
change_state <= '1';
when s2 =>
mult_array(2) <= input*H(1);
ADD_array(2) <= mult_array(2) + ADD_array(1);
next_s <= s3;
change_state <= '1';
when s3 =>
mult_array(3) <= input*H(0);
ADD_array(3) <= mult_array(3) + ADD_array(2);
Yout <= ADD_array(3);
next_s <= s0;
change_state <= '1';
when others =>
next_s <= s0;-- never comes here
change_state <= '1';
end case;
---------------------------------------------- FSM ----------------------------------------
end if;
end process;
end Behavioral;
How ever I am not able to receive the same output which I received by the first code.
FSM code gives the correct output for the first out but from the second out sample it gives wrong result.Can somebody tell me what I am doing wrong ?
This answer is for the initial version of the question but Now question has been changed.
Made add_out3 a variable instead of a signal.
for i in 0 to 3 loop
add_out3 := add_out3 + Xin(k-i)*H(i);
end loop;
Did the above changes in the for loop It works fine.
So the code in my question is a correct code for FIR also, works smoothly.
Learnt that one needs to be very careful while using signal or variables. All the signals get a new value at the same time i.e at the end of clock period, while in variables values gets updated as assigned within a process. Tried to run the simulation step by step and figured out the problem.