Well this is a bummer. Here I think I'm being careful, working things
out with
test bench, re-building all the while and checking for growth, only to
be blind sided
when I hook up the pin to the generated signal.
Meantime I've got some more info and questions.
1) >> any idea on how to make it fit?
If it has to be that device, I would need two of them.
that chip we are getting for around $100, I don't even know where to
buy them, and where do I get a Virtex II-PRO chip? digikey says they
are $1000?? Wouldn't I be better off getting the Virtex II-PRO?
Meantime the old chip is
mounted on a custom board layout, I guess my hardware guys are going
to have to re-lay out the board with
two of these chips? that won't work anyway as I added 600 macrocells
to a chip that only had 512 to begin with...
I think I was able to chip that down to under 512 though, but not by
much.
2) what exactly is a macrocell anyway?
3) "Rerun synthesis and check the % utilization "
that's what I've been doing. basically I added the equivalent of soft
uart and the data generator state machine that Jonathan so kindly set
me up with. So I started backing out that code bit by bit to see
where I pop the %s. When I took out the data generator I only freed
up a few macro cells, I tried reducing the fixed buffers, and that
again only freed up some of the small weeds. When I deleted the UART
however, it cleared up the whole mess. But now I don't know if thats
because I've effectively dead ended other parts, ... I'm still
driving the output now, but I can't believe my little uart is that big
a deal. I'm wondering if there is an expense in the separate
modules, and instantiations, or maybe the
'reverse' function. My next step is to start stubbing out sections
and see what causes the growth. It would be nice if in all those
reports that get generated they assigned macrocells/pterms etc back to
the source code that generated them.
Directory of C:\jon\oats
03/20/2009 10:36 AM 19,460 data_gen_40.vhd
03/19/2009 03:48 PM 8,795 OATS_TOP.ucf
03/20/2009 04:56 PM 263,536 OATS_Top.vhd
03/09/2009 11:21 AM 941 mod_m_counter.vhd
03/04/2009 05:23 PM 3,486 fifo.vhd
03/19/2009 03:23 PM 5,635 oats_top_tb.vhd
03/20/2009 01:10 PM 3,851 uart_core40.vhd
03/12/2009 09:22 AM 2,756 uart_rx40.vhd
03/12/2009 12:31 PM 3,734 uart_tx40.vhd
Now clearly source size doesn't make much difference, the OATS_TOP.VHD
program is ridiculously big, but as shown above used reasonable
amounts of resources. I added some clocking and counters to OATS_TOP:
------------------------------
FUNCTION to_slv (c: character) RETURN
STD_LOGIC_VECTOR IS
BEGIN
RETURN std_logic_vector(to_unsigned(character'pos(c), 8));
END;
FUNCTION reverse (a : IN STD_LOGIC_VECTOR) RETURN
STD_LOGIC_VECTOR IS
VARIABLE
result : STD_LOGIC_VECTOR(a'RANGE);
ALIAS aa : STD_LOGIC_VECTOR(a'REVERSE_RANGE) IS a;
BEGIN
FOR i IN aa'RANGE LOOP
result(i) := aa(i);
END LOOP;
RETURN result;
END;
...
clock_4hz: PROCESS ( system_clock_used )
BEGIN
IF ( rising_edge(system_clock_used)) then
IF ( clk_4hz_countdown = 0) THEN
clk_4hz_countdown <= human_clock_count;
clk_4hz <= NOT clk_4hz;
else
clk_4hz_countdown <= clk_4hz_countdown -1;
End if; -- countdown ife
END IF;
END PROCESS clock_4hz;
clock_2mhz: PROCESS ( system_clock_used )
BEGIN
IF ( rising_edge(system_clock_used)) then
IF ( clk_2mhz_countdown = 0) THEN
clk_2mhz_countdown <= clk_2mhz_clock_count; --
base clock choice
clk_2mhz <= NOT clk_2mhz;
else
clk_2mhz_countdown <= clk_2mhz_countdown -1;
End if; -- countdown ife
END IF;
END PROCESS clock_2mhz;
clock_2mhz_ctr: PROCESS ( clk_2mhz )
BEGIN
IF ( rising_edge(clk_2mhz)) then
time_cntr_500ns <= time_cntr_500ns +1;
END IF;
END PROCESS clock_2mhz_ctr;
-- this clock is not uart related
clock_7812hz: PROCESS ( system_clock_used )
BEGIN
IF ( rising_edge(system_clock_used)) then
IF ( clk_7812hz_countdown = 0) THEN
clk_7812hz_countdown <= clk_7812hz_clock_count; --
base clock choice
clk_7812hz <= NOT clk_7812hz;
if (clk_7812hz = '0') Then
clk_7812hz_tick <= '1';
end if;
else
clk_7812hz_tick <= '0';
clk_7812hz_countdown <= clk_7812hz_countdown -1;
if ( (initialize_done = '0' ) AND
(clk_7812hz_countdown = 1276) ) Then
initialize_done <= '1';
initialize_data_gen <= '1';
else
initialize_data_gen <= '0';
end if; -- initialize_done
End if; -- countdown ife
END IF;
END PROCESS clock_7812hz;
clock_7812_ctr: PROCESS ( clk_7812hz )
BEGIN
IF ( rising_edge(clk_7812hz)) then
time_cntr_128us <= time_cntr_128us +1;
uptime_at_128us <= time_cntr_500ns;
a2mhz_parity_plus(7) <=
( (time_cntr_500ns(39) xor time_cntr_500ns(38))
xor
(time_cntr_500ns(37) xor time_cntr_500ns(36))
) xor
( (time_cntr_500ns(35) xor time_cntr_500ns(34))
xor
(time_cntr_500ns(33) xor time_cntr_500ns(32))
);
a2mhz_parity_plus(6) <=
( (time_cntr_500ns(31) xor time_cntr_500ns(30))
xor
(time_cntr_500ns(29) xor time_cntr_500ns(28))
) xor
( (time_cntr_500ns(27) xor time_cntr_500ns(26))
xor
(time_cntr_500ns(25) xor time_cntr_500ns(24))
);
a2mhz_parity_plus(5) <=
( (time_cntr_500ns(23) xor time_cntr_500ns(22))
xor
(time_cntr_500ns(21) xor time_cntr_500ns(20))
) xor
( (time_cntr_500ns(19) xor time_cntr_500ns(18))
xor
(time_cntr_500ns(17) xor time_cntr_500ns(16))
);
a2mhz_parity_plus(4) <=
( (time_cntr_500ns(15) xor time_cntr_500ns(14))
xor
(time_cntr_500ns(13) xor time_cntr_500ns(12))
) xor
( (time_cntr_500ns(11) xor time_cntr_500ns(10))
xor
(time_cntr_500ns(09) xor time_cntr_500ns(08))
);
a2mhz_parity_plus(3) <=
( (time_cntr_500ns(07) xor time_cntr_500ns(06))
xor
(time_cntr_500ns(05) xor time_cntr_500ns(04))
) xor
( (time_cntr_500ns(03) xor time_cntr_500ns(02))
xor
(time_cntr_500ns(01) xor time_cntr_500ns(00))
);
END IF;
END PROCESS clock_7812_ctr;
data_message_handler: PROCESS ( system_clock_used)
BEGIN
IF ( rising_edge(system_clock_used) ) THEN
if ( (w40_wanted = '1' ) and
(clk_7812hz_tick = '1')
) then
w40_data_from_main <=
reverse(
a2mhz_optional_message
& std_logic_vector(uptime_at_128us)
& a2mhz_parity_plus
& a2mhz_optional_message
) ; -- big endian for BAE.
w40_ready <= '1';
else
w40_ready <= '0';
end if; -- w40_wanted ite
else
--w40_ready <= '0';
END IF; --clock edge
END PROCESS data_message_handler;
---------------------
--2mhz communications uart begin
-- instantiate uart
a2mhz_uart_unit: entity work.uart40(str_arch)
generic map (
dbit => a2mhz_data_bit_count,
sb_tick => a2mhz_clock_tick_per_sampling_rate,
dvsr => a2mhz_baud_rate_divisor,
dvsr_bit => 2, -- number of bits necessary to hold
dvsr
FIFO_W => 2 -- 2**(value) is the number of chars
that can be queued.
) -- generic map
port map(
clk => system_clock_used,
reset => initialize_data_gen,
rd_uart => a2mhz_RX_READ_BUFFER_STB,
wr_uart => a2mhz_TX_WRITE_BUFFER_STB,
rx => a2mhz_HUART_RX_LINE,
w_data => a2mhz_TX_1CHAR_BUF,
tx_full => a2mhz_TX_BUFFER_FULL,
rx_empty => open,
rx_not_empty => a2mhz_RX_BUFFER_DATA_PRESENT,
r_data => a2mhz_RX_1CHAR_BUF,
tx => a2mhz_HUART_TX_LINE,
baud_rate_tick => a2mhz_UART_EN_16_x_BAUD
);
a2mhz_DATA_GENERATOR: entity work.data_gen_40
generic map
( PC_bits => 5
, dbit => a2mhz_data_bit_count
, the_program =>
-- Long startup delay
op40_DELAY & 200
& --2 bytes long
op40_LABEL & 04 &
op40_WAIT_FOR_W40 &
op40_GOTOL & 04 & -- spin on
printing W40's from here on in.
op40_HALT
)
port map
( clock => system_clock_used
, reset => initialize_data_gen
, timer => a2mhz_UART_EN_16_x_BAUD
, tx_data => a2mhz_TX_1CHAR_BUF
, tx_valid => a2mhz_tx_valid
, tx_ready => a2mhz_tx_ready
, rx_data => a2mhz_RX_1CHAR_BUF
, lbl_data => a2mhz_lbl_data_from_main
, rx_valid => a2mhz_RX_BUFFER_DATA_PRESENT
, rx_needed => a2mhz_rx_wanted
, reset_out => open --UART_RESET_BUFFER
, lbl_needed => a2mhz_lbl_wanted
, halted => a2mhz_halted
, error_cond => a2mhz_error_cond_main
, w40_data => w40_data_from_main
, w40_ready => w40_ready
, w40_needed => w40_wanted
);
-- JSEB: Conditioning of interface signals between UART and data
generator
a2mhz_tx_ready <= not a2mhz_TX_BUFFER_FULL;
a2mhz_TX_WRITE_BUFFER_STB <= a2mhz_tx_valid and a2mhz_tx_ready; --
Write only when it's safe
a2mhz_RX_READ_BUFFER_STB <= a2mhz_rx_wanted and
a2mhz_RX_BUFFER_DATA_PRESENT;
a2mhz_HUART_TX_CK_LINE <= clk_2mhz;
--2mhz communications uart end
---------------------
now by removing the a2mhz_uart_unit entity, I return to acceptable
levels the old levels. That leads me to believe
I just put all the logic in the unused/don't bother pile and once I
put the uart back in, Is the REVERSE function the problem?
The uart is pretty simple:
----------Uart_core40.vhd-------------
-- Listing 7.4
--
-- jl 090226 First working. WATCH OUT!!! DVSR_BIT!!! for 19200
baud,
-- the DVSR was 325, and guess what? that means that you
need
-- 9 bits instead of 8 for the DVSR_BIT, this still synthed
ok
-- but generated 175 warnings. changing it to 9 bits (or
115,200 baud means
-- the synth gets through with 5 warnings, and works.
-- 090312 copy and redo of uart_core.vhd. this one is to
customize to the to the 40 bit
-- (probably expand to 64) comm port for BAE.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart40 is
generic(
-- Default setting:
-- xxx baud, 8 data bis, 1 stop its, 2^2 FIFO
DBIT : integer:=8; -- # data bits
SB_TICK : integer:=16; -- # ticks for stop bits, 16/24/32
-- for 1/1.5/2 stop bits
DVSR : integer:= 325; -- baud rate divisor
-- DVSR = 50M/(16*baud rate(19200))
== 162.76
-- 100m/(16*19200) ==325.52
-- 100m/(16*115200) ==54.25
DVSR_BIT : integer:=9; -- # bits of DVSR 325 needs 9
bits!!!!!
FIFO_W : integer:=2 -- # addr bits of FIFO
-- # words in FIFO=2^FIFO_W
);
port(
clk,
reset: in std_logic;
rd_uart,
wr_uart: in std_logic;
rx: in std_logic;
w_data: in std_logic_vector((dbit-1) downto 0);
tx_full,
rx_empty: out std_logic;
rx_not_empty: out std_logic;
r_data: out std_logic_vector((dbit-1) downto 0);
tx: out std_logic;
baud_rate_tick: out std_logic
);
end uart40;
architecture str_arch of uart40 is
signal tick: std_logic;
signal rx_done_tick: std_logic;
signal tx_fifo_out: std_logic_vector((dbit-1) downto 0);
signal rx_data_out: std_logic_vector((dbit-1) downto 0);
signal tx_empty, tx_fifo_not_empty: std_logic;
signal tx_done_tick: std_logic;
begin
baud_gen_unit: entity work.mod_m_counter(arch)
generic map(M=>DVSR,
N=>DVSR_BIT)
port map(clk =>clk,
reset =>reset,
q =>open,
max_tick =>tick
);
uart40_rx_unit: entity work.uart40_rx(arch)
generic map(DBIT=>DBIT,
SB_TICK=>SB_TICK)
port map(clk=>clk,
reset=>reset,
rx=>rx,
s_tick=>tick,
rx_done_tick=>rx_done_tick,
dout=>rx_data_out);
fifo_rx_unit: entity work.fifo(arch)
generic map(B=>DBIT, W=>FIFO_W)
port map(clk=>clk,
reset=>reset,
rd=>rd_uart,
wr=>rx_done_tick,
w_data=>rx_data_out,
empty=>rx_empty,
notempty=>rx_not_empty,
full=>open,
r_data=>r_data);
fifo_tx_unit: entity work.fifo(arch)
generic map(B=>DBIT,
W=>FIFO_W)
port map(clk=>clk,
reset=>reset,
rd=>tx_done_tick,
wr=>wr_uart,
w_data=>w_data,
empty=>tx_empty,
notempty=>open,
full=>tx_full,
r_data=>tx_fifo_out);
uart40_tx_unit: entity work.uart40_tx(arch)
generic map(DBIT=>DBIT,
SB_TICK=>SB_TICK)
port map(clk=>clk,
reset=>reset,
tx_start=>tx_fifo_not_empty,
s_tick=>tick,
din=>tx_fifo_out,
tx_done_tick=> tx_done_tick,
tx=>tx);
tx_fifo_not_empty <= not tx_empty;
baud_rate_tick <= tick;
end str_arch;
-----fifo.vhd-----
-- Listing 4.20
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fifo is
generic(
B: natural:=8; -- number of bits
W: natural:=4 -- number of address bits
);
port(
clk, reset: in std_logic;
rd, wr: in std_logic;
w_data: in std_logic_vector (B-1 downto 0);
empty,
notempty,
full: out std_logic;
r_data: out std_logic_vector (B-1 downto 0)
);
end fifo;
architecture arch of fifo is
type reg_file_type is array (2**W-1 downto 0) of
std_logic_vector(B-1 downto 0);
signal array_reg: reg_file_type;
signal w_ptr_reg, w_ptr_next, w_ptr_succ:
std_logic_vector(W-1 downto 0);
signal r_ptr_reg, r_ptr_next, r_ptr_succ:
std_logic_vector(W-1 downto 0);
signal full_reg, empty_reg, full_next, empty_next:
std_logic;
signal wr_op: std_logic_vector(1 downto 0);
signal wr_en: std_logic;
begin
--=================================================
-- register file
--=================================================
process(clk,reset)
begin
if (reset='1') then
array_reg <= (others=>(others=>'0'));
elsif (clk'event and clk='1') then
if wr_en='1' then
array_reg(to_integer(unsigned(w_ptr_reg)))
<= w_data;
end if;
end if;
end process;
-- read port
r_data <= array_reg(to_integer(unsigned(r_ptr_reg)));
-- write enabled only when FIFO is not full
wr_en <= wr and (not full_reg);
--=================================================
-- fifo control logic
--=================================================
-- register for read and write pointers
process(clk,reset)
begin
if (reset='1') then
w_ptr_reg <= (others=>'0');
r_ptr_reg <= (others=>'0');
full_reg <= '0';
empty_reg <= '1';
elsif (clk'event and clk='1') then
w_ptr_reg <= w_ptr_next;
r_ptr_reg <= r_ptr_next;
full_reg <= full_next;
empty_reg <= empty_next;
end if;
end process;
-- successive pointer values
w_ptr_succ <= std_logic_vector(unsigned(w_ptr_reg)+1);
r_ptr_succ <= std_logic_vector(unsigned(r_ptr_reg)+1);
-- next-state logic for read and write pointers
wr_op <= wr & rd;
process(w_ptr_reg,w_ptr_succ,r_ptr_reg,r_ptr_succ,wr_op,
empty_reg,full_reg)
begin
w_ptr_next <= w_ptr_reg;
r_ptr_next <= r_ptr_reg;
full_next <= full_reg;
empty_next <= empty_reg;
case wr_op is
when "00" => -- no op
when "01" => -- read
if (empty_reg /= '1') then -- not empty
r_ptr_next <= r_ptr_succ;
full_next <= '0';
if (r_ptr_succ=w_ptr_reg) then
empty_next <='1';
end if;
end if;
when "10" => -- write
if (full_reg /= '1') then -- not full
w_ptr_next <= w_ptr_succ;
empty_next <= '0';
if (w_ptr_succ=r_ptr_reg) then
full_next <='1';
end if;
end if;
when others => -- write/read;
w_ptr_next <= w_ptr_succ;
r_ptr_next <= r_ptr_succ;
end case;
end process;
-- output
full <= full_reg;
empty <= empty_reg;
notempty <= not empty_reg;
end arch;
------------------mod_m_counter.vhd
-- Listing 4.11
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity mod_m_counter is
generic(
N: integer := 4; -- number of bits
M: integer := 10 -- mod-M
);
port(
clk,
reset : in std_logic;
max_tick : out std_logic;
q : out std_logic_vector(N-1 downto 0)
);
end mod_m_counter;
architecture arch of mod_m_counter is
signal r_reg: unsigned(N-1 downto 0);
signal r_next: unsigned(N-1 downto 0);
begin
-- register
process(clk,reset)
begin
if (reset='1') then
r_reg <= (others=>'0');
elsif (clk'event and clk='1') then
r_reg <= r_next;
end if;
end process;
-- next-state logic
r_next <= (others=>'0') when r_reg=(M-1) else
r_reg + 1;
-- output logic
q <= std_logic_vector(r_reg);
max_tick <= '1' when r_reg=(M-1) else '0';
end arch;
---------uart_tx40.vhd
-- Listing 7.3
-- JL 090309 changing hard coded '15' to (sb_tick-1) for length of
-- each bit. hard coded '7' for databits now (dbit-1) as
well.
-- JL 090312 custom version of uart_tx for the BAE comm link.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart40_tx is
generic(
DBIT: integer:=8; -- # data bits
SB_TICK: integer:=16 -- # ticks for stop bits
);
port(
clk, reset: in std_logic;
tx_start: in std_logic;
s_tick: in std_logic;
din: in std_logic_vector((dbit-1) downto 0);
tx_done_tick: out std_logic;
tx: out std_logic
);
end uart40_tx ;
architecture arch of uart40_tx is
type state_type is (idle, start, data, stop);
constant go_high : std_logic := '1';
constant go_low : std_logic := '0';
signal state_reg, state_next: state_type;
signal s_reg, s_next: unsigned(7 downto 0);
signal n_reg, n_next: unsigned(7 downto 0);
signal b_reg, b_next: std_logic_vector((dbit-1) downto 0);
signal tx_reg, tx_next: std_logic;
signal bit_length: std_logic := '0'; -- testbench watching
only. use with din watch.
begin
-- FSMD state & data registers
process(clk,reset)
begin
if reset='1' then
state_reg <= idle;
s_reg <= (others=>'0');
n_reg <= (others=>'0');
b_reg <= (others=>'0');
tx_reg <= go_high;
elsif (clk'event and clk='1') then
state_reg <= state_next;
s_reg <= s_next;
n_reg <= n_next;
b_reg <= b_next;
tx_reg <= tx_next;
end if;
end process;
-- next-state logic & data path functional units/routing
process(state_reg,s_reg,n_reg,b_reg,s_tick,
tx_reg,tx_start,din)
begin
state_next <= state_reg;
s_next <= s_reg;
n_next <= n_reg;
b_next <= b_reg;
tx_next <= tx_reg ;
tx_done_tick <= '0';
case state_reg is
when idle =>
tx_next <= go_low;
if tx_start='1' then
state_next <= start;
s_next <= (others=>'0');
b_next <= din;
end if;
when start =>
tx_next <= go_high;
if (s_tick = '1') then
if s_reg=(sb_tick-1) then
state_next <= data;
s_next <= (others=>'0');
n_next <= (others=>'0');
else
s_next <= s_reg + 1;
end if;
end if;
when data =>
tx_next <= b_reg(0);
if (s_tick = '1') then
if s_reg=(sb_tick-1) then
bit_length <= not bit_length; -- measure a bit.
s_next <= (others=>'0');
b_next <= '0' & b_reg((dbit-1) downto 1) ;
if n_reg=(DBIT-1) then
state_next <= idle; -- stop ; --lets skip the
stop bit.
tx_done_tick <= '1'; -- moved in from
stop
else
n_next <= n_reg + 1;
end if;
else
s_next <= s_reg + 1;
end if;
end if;
when stop =>
tx_next <= go_high;
if (s_tick = '1') then
if s_reg=(SB_TICK*4-1) then -- lets make it stick out
for now.
state_next <= idle;
tx_done_tick <= '1';
else
s_next <= s_reg + 1;
end if;
end if;
end case;
end process;
tx <= tx_reg;
end arch;
---------------uart_rx40.vhd ----
-- Listing 7.1
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart40_rx is
generic(
DBIT: integer:=8; -- # data bits
SB_TICK: integer:=16 -- # ticks for stop bits
);
port(
clk, reset: in std_logic;
rx: in std_logic;
s_tick: in std_logic;
rx_done_tick: out std_logic;
dout: out std_logic_vector((dbit-1) downto 0)
);
end uart40_rx ;
architecture arch of uart40_rx is
type state_type is (idle, start, data, stop);
signal state_reg, state_next: state_type;
signal s_reg, s_next: unsigned(3 downto 0);
signal n_reg, n_next: unsigned(2 downto 0);
signal b_reg, b_next: std_logic_vector((dbit-1) downto 0);
begin
-- FSMD state & data registers
process(clk,reset)
begin
if reset='1' then
state_reg <= idle;
s_reg <= (others=>'0');
n_reg <= (others=>'0');
b_reg <= (others=>'0');
elsif (clk'event and clk='1') then
state_reg <= state_next;
s_reg <= s_next;
n_reg <= n_next;
b_reg <= b_next;
end if;
end process;
-- next-state logic & data path functional units/routing
process(state_reg,s_reg,n_reg,b_reg,s_tick,rx)
begin
state_next <= state_reg;
s_next <= s_reg;
n_next <= n_reg;
b_next <= b_reg;
rx_done_tick <='0';
case state_reg is
when idle =>
if rx='0' then
state_next <= start;
s_next <= (others=>'0');
end if;
when start =>
if (s_tick = '1') then
if s_reg=(sb_tick/2 -1) then
state_next <= data;
s_next <= (others=>'0');
n_next <= (others=>'0');
else
s_next <= s_reg + 1;
end if;
end if;
when data =>
if (s_tick = '1') then
if s_reg=(sb_tick-1) then
s_next <= (others=>'0');
b_next <= rx & b_reg((dbit-1) downto 1) ;
if n_reg=(DBIT-1) then
state_next <= stop ;
else
n_next <= n_reg + 1;
end if;
else
s_next <= s_reg + 1;
end if;
end if;
when stop =>
if (s_tick = '1') then
if s_reg=(SB_TICK-1) then
state_next <= idle;
rx_done_tick <='1';
else
s_next <= s_reg + 1;
end if;
end if;
end case;
end process;
dout <= b_reg;
end arch;