# o source files der module
# o reihenfolge ist wichtig
# o keine testbechnes hier angeben
-SRCFILES := alu parser scanner display sp_ram history uart_tx uart_rx
+SRCFILES := alu parser scanner display sp_ram history uart_tx uart_rx pc_communication
# o files der packages
# o keine testbechnes hier angeben
use work.textmode_vga_pkg.all;
use work.textmode_vga_platform_dependent_pkg.all;
+-- this is for test file io
+use std.textio.all;
+
entity beh_pc_communication_tb is
end entity beh_pc_communication_tb;
architecture sim of beh_pc_communication_tb is
+ type byte_file_type is file of hbyte;
+ signal sys_clk : std_logic;
+ signal sys_res_n : std_logic;
+ signal btn_a : std_logic;
+ signal tx_new : std_logic;
+ signal tx_done : std_logic;
+ signal rx_new : std_logic;
+ signal d_get : std_logic;
+ signal d_done : std_logic;
+ signal rx_data, tx_data : std_logic_vector(7 downto 0);
+
+ signal d_zeile : hzeile;
+ signal d_spalte : hspalte;
+ signal d_char : hbyte;
begin
-- display
inst : entity work.pc_communication(beh)
sys_clk => sys_clk,
sys_res_n => sys_res_n,
- --button=> ,
+ --button
btn_a => btn_a,
- --uart_tx=> ,
+ --uart_tx
tx_data => tx_data,
tx_new => tx_new,
tx_done => tx_done,
- --uart_rx=> ,
+ --uart_rx
rx_data => rx_data,
rx_new => rx_new,
- -- History=> ,
+ -- History
d_zeile => d_zeile,
d_spalte => d_spalte,
d_get => d_get,
d_done => d_done,
- d_char => d_char--,
+ d_char => d_char
);
clk : process
wait for 15 ns;
sys_clk <= '1';
wait for 15 ns;
- if stop = true then
- wait;
- end if;
end process clk;
- stub_history process (d_get)
- file f : text open read_mode is "../../src/pc_communication.test";
+ stub_history : process
+ file f : byte_file_type open read_mode is "../../src/pc_communication.test";
+ variable rb : hbyte;
begin
- if rising_edge(d_get) then
- read(f, d_char);
- wait 30 ns;
- done <= d_done;
- end if;
+ wait until rising_edge(d_get);
+ assert not endfile(f) report "test beendet" severity failure;
+ read(f, rb);
+ wait for 30 ns;
+ d_char <= rb;
+ d_done <= '1';
+ wait for 15 ns;
+ d_done <= '0';
end process stub_history;
- process
+ reset_and_button : process
begin
-- init & reset
-- we only simulate pressing of button a by now!
- sys_res_n <= 0;
+ sys_res_n <= '0';
wait for 100 ns;
- sys_res_n <= 1;
+ sys_res_n <= '1';
- btn_a <= 1;
+ btn_a <= '1';
+ wait for 15ns;
+ btn_a <= '0';
wait;
- end process;
+ end process reset_and_button;
+
end architecture sim;
use ieee.numeric_std.all;
use work.gen_pkg.all;
-
entity pc_communication is
port (
sys_clk : in std_logic;
tx_done : in std_logic;
--uart_rx
- rx_data : in std_logic_vector(7 downt 0); --not really required
- rx_new : in std_logic_vector;
+ rx_data : in std_logic_vector(7 downto 0); --not really required
+ rx_new : in std_logic;
-- History
d_zeile : out hzeile;
d_spalte : out hspalte;
d_get : out std_logic;
d_done : in std_logic;
- d_char : in hbyte --;
+ d_char : in hbyte
);
end entity pc_communication;
+architecture beh of pc_communication is
+ signal push_history, push_history_next : std_logic;
+ signal spalte, spalte_next : hspalte;
+ signal zeile , zeile_next : hzeile;
+ signal spalte_up, spalte_up_next : std_logic;
+
+ signal char, char_next : hbyte;
+ signal char_en : std_logic;
+ type STATE_PC is (IDLE, FETCH, FORWARD, DONE);
+ signal state, state_next : STATE_PC ;
-architecture beh of display is
- signal push_history, push_history_next : std_logic;
begin
- sync_push_history : process (sys_clk, sys_res_n)
+ sync: process (sys_clk, sys_res_n)
begin
if sys_res_n = '0' then
+ state <= IDLE;
push_history <= '0';
+ spalte <= "0000000";
+ zeile <= "0000000";
elsif rising_edge(sys_clk) then
push_history <= push_history_next;
+ spalte <= spalte_next;
+ zeile <= zeile_next;
+ state <= state_next;
+ if (char_en = '1') then
+ state <= state_next;
+ end if;
end if;
- end process sync_push_history;
+ end process sync;
- push_history : process(rx_new, rx_data, btn_a)
+ process (spalte_up)
+ variable spalte_tmp, zeile_tmp : integer;
begin
- if ( (rx_new = '1' and rx_data = X"41") or btn_a '1') then
- push_history_next <= '1';
+ if (spalte_up = '1') then
+ if (spalte > X"45") then
+ spalte_next <= "0000000";
+ zeile_tmp := to_integer(unsigned(zeile));
+ zeile_tmp := zeile_tmp + 1;
+ zeile_next <= hbyte(to_unsigned(zeile_tmp,8));
+ else
+ spalte_tmp := to_integer(unsigned(spalte));
+ spalte_tmp := spalte_tmp + 1;
+ spalte_next <= hbyte(to_unsigned(spalte_tmp,8));
+ zeile_next <= zeile;
+ end if;
+ spalte_up <= '0';
+ end if;
+ end process;
+
+ async_push_history : process (rx_new, rx_data, btn_a)
+ begin
+ if rx_new = '1' then
+ if rx_data = X"41" then
+ push_history_next <= '1';
+ else
+ push_history_next <= '0';
+ end if;
+ elsif btn_a = '1' then
+ push_history_next <= '1';
else
push_history_next <= '0';
end if;
- end process push_history;
+ end process async_push_history;
+
+ output_pc : process (zeile, spalte)
+ begin
+ case state is
+ when IDLE =>
+ spalte_next <= "0000000";
+ zeile_next <= "0000000";
+ when FETCH =>
+ d_zeile <= zeile;
+ d_spalte <= spalte;
+ d_get <= '1';
+ char_en <= '1';
+ -- wait for timer overflow
+ -- increment counter
+ when FORWARD =>
+ char_en <= '0';
+ tx_data <= char;
+ tx_new <= '1';
+ when DONE =>
+ null;
+ -- be there for a single cycle and then
+ end case;
+ end process output_pc;
+
+ next_state_pc : process (rx_new, btn_a)
+ begin
+ case state is
+ when IDLE =>
+ if rx_new= '1' or btn_a = '1' then
+ state_next <= FETCH;
+ char <= d_char; --latch
+ end if;
+ when FETCH =>
+ if (d_done = '1') then
+ state_next <= FORWARD;
+ end if;
+ when FORWARD =>
+ if (tx_done = '1') then
+ state_next <= FETCH;
+ end if;
+ when DONE =>
+ -- be there for a single cycle and then
+ state_next <= IDLE;
+ end case;
+ end process next_state_pc;
--- sync_pc : process ()
--- begin
--- end process sync_pc;
---
--- next_state_pc : process ()
--- begin
--- end process next_state_pc;
---
--- output_pc : process ()
--- begin
--- end process output_pc;
end architecture beh;
architecture beh of uart_rx is
constant timer_max : integer := 35;
+ constant counter_max : integer := 9;
+ constant samples : integer := 8;
type STATE_UART_RX is (IDLE, BUSY, DONE);
signal timer, timer_next : integer range 0 to 65535;
signal counter, counter_next : integer range 0 to 15;
+ signal sample_counter, sample_counter_next : integer range 0 to counter_max-1;
signal state, state_next : STATE_UART_RX;
- signal tx_data_prev : std_logic_vector(7 downto 0); -- FIXME: this isnt named next so that the interface isn't called tx_data_next ...
+ signal sync1, sync2, txd_next: std_logic; --synchronizers FIXME!
-- these are internal signals that are actually used as in and output
- signal tx_data_i : std_logic_vector(7 downto 0);
+ signal tx_data_prev : std_logic_vector(7 downto 0);
signal tx_new_i : std_logic;
+ signal shift, shift_value, shift_reset : std_logic;
begin
---FIXME:
tx_new <= tx_new_i;
- tx_data <= tx_data_i;
process(sys_clk, sys_res)
begin
-- Set reset state
state <= IDLE;
tx_data_prev <= X"00";
+
+ txd_next <= '0'; --fixme: syncronizers!
+ sync2 <= '0';
+ sync1 <= '0';
+ timer <= 0;
+ counter <= 0;
elsif rising_edge(sys_clk) then
-- Store next state
state <= state_next;
- tx_data_prev <= tx_data_i;
+ if (shift = '1') then
+ tx_data(7 downto 1) <= tx_data_prev(6 downto 1);
+ tx_data(0) <= shift_value;
+ elsif ( shift_reset = '1') then
+ tx_data <= X"00";
+ end if;
+
+ txd_next <= sync2; --fixme: syncronizers!
+ sync2 <= sync1;
+ sync1 <= txd;
+ counter <= counter_next;
+ sample_counter <= sample_counter_next;
+ timer <= timer_next;
end if;
end process;
process(state, txd, counter)
begin
state_next <= state;
+
+ shift <= '0';
+ shift_reset <='0';
+ shift_value <= '0';
+ timer_next <= 0;
+ counter_next <= 0;
+
case state is
when IDLE =>
if (txd = '0') then
state_next <= BUSY;
- else
- state_next <= IDLE;
+ shift_reset <= '1';
end if;
when BUSY =>
- if (counter = 9) then --FIXME: is this true?
+ if (counter = counter_max) then --FIXME: is this true?
state_next <= DONE;
- else
- state_next <= BUSY;
end if;
- when DONE =>
- state_next <= IDLE;
- end case;
- end process;
-
- process(state)
- begin
- -- Set default values
- -- for the outputs
- tx_new_i <= '0';
-
- -- Calculate the outputs
- -- based on the current
- -- state
- case state is
- when IDLE =>
- tx_new_i <= '0';
- when BUSY =>
- tx_new_i <= '0';
- when DONE =>
- tx_new_i <= '1';
- end case;
- end process;
--- END FIXME: do fill this out CORRECTLY
-
- process (sys_clk, sys_res)
- begin
- if sys_res = '0' then
- counter <= 0;
- timer <= 0;
- elsif rising_edge(sys_clk) then
- counter <= counter_next;
- timer <= timer_next;
- end if;
- end process;
-
- process (timer)
- begin
- if (timer = timer_max) then
- timer_next <= 0;
- else
- timer_next <= timer + 1;
- end if;
- end process;
- process (timer, counter, tx_new_i)
- begin
- if (tx_new_i = '1') then
- if (timer = timer_max) then
- if (counter > 10) then
- counter_next <= 0;
- else
+ if (timer = timer_max) then
+ timer_next <= 0;
counter_next <= counter + 1;
+ if (sample_counter < samples/2) then
+ shift_value <= '1';
+ else
+ shift_value <= '0';
+ end if;
+ shift <= '1';
+ else
+ timer_next <= timer + 1;
end if;
- else
- counter_next <= counter;
- end if;
- else
- counter_next <= 0;
- end if;
- end process;
- process (counter, txd)
- begin
- tx_data_i <= tx_data_prev;
- -- TODO: we probably want oversampling and averaging + failure!
- -- FIXME: this is per se not synthesisable
- case (counter) is
- when 0 => --start bit
- assert (txd = '0');
- when 1 =>
- tx_data_i(0) <= txd;
- when 2 =>
- tx_data_i(1) <= txd;
- when 3 =>
- tx_data_i(2) <= txd;
- when 4 =>
- tx_data_i(3) <= txd;
- when 5 =>
- tx_data_i(4) <= txd;
- when 6 =>
- tx_data_i(5) <= txd;
- when 7 =>
- tx_data_i(6) <= txd;
- when 8 =>
- tx_data_i(7) <= txd;
- when 9 => -- stop bit
- assert (txd = '1');
- when others => -- idle
- assert (txd = '1');
+ if timer = timer_max/samples and txd_next = '1' then
+ sample_counter_next <= sample_counter + 1;
+ end if;
+ when DONE =>
+ state_next <= IDLE;
end case;
end process;