uart_rx: rewrite inkl. testbench
authorBernhard Urban <lewurm@gmail.com>
Tue, 25 May 2010 14:28:29 +0000 (16:28 +0200)
committerBernhard Urban <lewurm@gmail.com>
Tue, 25 May 2010 14:28:29 +0000 (16:28 +0200)
src/beh_uart_rx_tb.do
src/beh_uart_rx_tb.vhd
src/uart_rx.vhd

index 4f70701dbb57fb6fe59cb13a9b15ca2c38690423..014c50cf1c878e1d9e8fb375b1143cbba8a7c746 100644 (file)
@@ -2,50 +2,9 @@
 alias rr "restart -f"
 
 #signale hinzufuegen
 alias rr "restart -f"
 
 #signale hinzufuegen
+add wave *
 add wave inst/*
 
 add wave inst/*
 
-delete wave /beh_parser_tb/inst/op1_int
-delete wave /beh_parser_tb/inst/op1
-delete wave /beh_parser_tb/inst/op1_next
-add wave -radix decimal inst/op1_int
-
-delete wave /beh_parser_tb/inst/op2_int
-delete wave /beh_parser_tb/inst/op2
-delete wave /beh_parser_tb/inst/op2_next
-add wave -radix decimal inst/op2_int
-
-delete wave /beh_parser_tb/inst/op3
-add wave -radix decimal inst/op3
-delete wave /beh_parser_tb/inst/opM
-add wave -radix decimal inst/opM
-
-delete wave /beh_parser_tb/inst/z_int
-delete wave /beh_parser_tb/inst/z_next
-add wave -radix decimal inst/z_int
-add wave -radix decimal inst/z_next
-
-delete wave /beh_parser_tb/inst/strich_int
-delete wave /beh_parser_tb/inst/strich_next
-add wave -radix decimal inst/strich_int
-add wave -radix decimal inst/strich_next
-
-delete wave /beh_parser_tb/inst/punkt_int
-delete wave /beh_parser_tb/inst/punkt_next
-add wave -radix decimal inst/punkt_int
-add wave -radix decimal inst/punkt_next
-
-delete wave /beh_parser_tb/inst/wtmp_int
-delete wave /beh_parser_tb/inst/wtmp_next
-add wave -radix decimal inst/wtmp_int
-add wave -radix decimal inst/wtmp_next
-
-delete wave /beh_parser_tb/inst/p_write_int
-delete wave /beh_parser_tb/inst/p_write_next
-delete wave /beh_parser_tb/inst/p_write
-add wave -hex inst/p_write_int
-add wave -hex inst/p_write_next
-
-
 #rauszoomen
 wave zoomout 500.0
 
 #rauszoomen
 wave zoomout 500.0
 
index bca920a315295223640309942b87543f8f2fceeb..26adbda22b46f13419dc05fe61530b19af389af3 100644 (file)
@@ -7,51 +7,83 @@ entity beh_uart_rx_tb is
 end entity beh_uart_rx_tb;
 
 architecture sim of beh_uart_rx_tb is
 end entity beh_uart_rx_tb;
 
 architecture sim of beh_uart_rx_tb is
+       constant CLK_FREQ : integer := 33000000;
+       constant BAUDRATE : integer := 115200;
+       constant BAUD : integer := CLK_FREQ/BAUDRATE;
 
 
-       constant clk_period : time := 2ns;
-       signal clock : std_logic;
-       signal reset : std_logic;
-       signal done : std_logic;
-       signal newsig : std_logic;
-       signal data : std_logic_vector(7 downto 0);
-       signal serial_in: std_logic;
+       signal sys_clk, sys_res_n, rxd, rx_new : std_logic;
+       signal rx_data : std_logic_vector (7 downto 0);
+       signal stop : boolean := false;
 begin
        inst : entity work.uart_rx(beh)
 begin
        inst : entity work.uart_rx(beh)
+       generic map (
+               CLK_FREQ => CLK_FREQ,
+               BAUDRATE => BAUDRATE
+       )
        port map (
        port map (
-               sys_clk => clock,
-               sys_res => reset,
-               txd => serial_in,
-               tx_data => data,
-               tx_new => newsig
+               sys_clk => sys_clk,
+               sys_res_n => sys_res_n,
+               rxd => rxd,
+               rx_data => rx_data,
+               rx_new => rx_new
        );
 
        );
 
-       stimuli : process
+       process
        begin
        begin
-               serial_in <= '0';
-               wait for 10ns;
-               --send 'Hallo Welt'
-               serial_in <= '1';
-               wait for clk_period;
-               serial_in <= '0';
-               wait for 1000ns;
-
-               assert false report "Test finished" severity failure;
-       end process stimuli;
-
-       res_gen : process
-       begin
-               reset <= '0';
-               wait for 20ns;
-               reset <= '1';
-               wait for 1000ns;
-       end process res_gen;
+               sys_clk <= '0';
+               wait for 15 ns;
+               sys_clk <= '1';
+               wait for 15 ns;
+               if stop = true then
+                       wait;
+               end if;
+       end process;
+
+       process
+               procedure exec_tc(testnr : integer;
+                       constant testvector : std_logic_vector(9 downto 0);
+                       constant expectedresult : std_logic_vector(7 downto 0)) is
+               begin
+                       -- vorher auf high setzen um falling edge simulieren zu koennen
+                       rxd <= '1';
+                       icwait(sys_clk, 2);
 
 
-       clock_gen : process
+                       for i in 0 to 9 loop
+                               rxd <= testvector(9-i);
+                               if i /= 9 then
+                                       icwait(sys_clk, BAUD);
+                               end if;
+                       end loop;
+               
+                       wait until rx_new = '1';
+                       if expectedresult = rx_data then
+                               report "testfall " & integer'image(testnr) & " war erfolgreich";
+                       else
+                               report "testfall " & integer'image(testnr) & " schlug fehl";
+                       end if;
+                       icwait(sys_clk, 3);
+               end;
+
+               variable testvector : std_logic_vector(9 downto 0);
+               variable expectedresult : std_logic_vector(7 downto 0);
        begin
        begin
-               clock <= '0';
-               wait for clk_period/2;
-               clock <= '1';
-               wait for clk_period/2;
-       end process clock_gen;
+               sys_res_n <= '0';
+               rxd <= '1';
+               icwait(sys_clk, 10);
+               sys_res_n <= '1';
+               icwait(sys_clk, 2);
+
+               -- 1. parameter: testfallnummer
+               -- 2. parameter: STARTBIT (1 bit) - immer '0' | 8 DATENBITS | 1 STOPBIT - immer '1'
+               -- 3. parameter: byte das rauskommen soll
+               exec_tc(1, b"0000011111", b"00001111");
+               exec_tc(2, b"0101010101", b"10101010");
+               exec_tc(3, b"0110011001", b"11001100");
+               exec_tc(4, b"0001100111", b"00110011");
+               exec_tc(5, b"0010101011", b"01010101");
+               exec_tc(6, b"0100110111", b"10011011");
 
 
+               stop <= true;
+               wait;
+       end process;
 end sim;
 end sim;
index 2f321028aca6ceda92d3e24b6e891e642be8a40a..cee42a30c341d2bdce30d1a3f02d2fd18be5ebd0 100644 (file)
@@ -4,107 +4,110 @@ use ieee.numeric_std.all;
 use work.gen_pkg.all;
 
 entity uart_rx is
 use work.gen_pkg.all;
 
 entity uart_rx is
-port(
-       sys_clk : in std_logic;
-       sys_res : in std_logic;
-       txd : in std_logic; -- warning: this is asynchronous input!
-       tx_data : out std_logic_vector(7 downto 0); -- map this to a larger register with containing input
-       tx_new : out std_logic
-);
+       generic (
+               CLK_FREQ : integer := 33000000;
+               BAUDRATE : integer := 115200
+       );
+       port(
+               sys_clk : in std_logic;
+               sys_res_n : in std_logic;
+               rxd : in std_logic;
+               rx_data : out std_logic_vector(7 downto 0);
+               rx_new : out std_logic
+       );
 end entity uart_rx;
 
 architecture beh of uart_rx is
 end entity uart_rx;
 
 architecture beh of uart_rx is
-       constant timer_max : integer := 35;
-       constant counter_max : integer := 9;
-       constant samples : integer := 8;
+       constant BAUD : integer := CLK_FREQ/BAUDRATE;
 
 
-       type STATE_UART_RX is (IDLE, BUSY, DONE);
+       type STATE_UART_RX is (IDLE, STARTBIT, DBITS, STOPBIT);
+       signal state_int, state_next : STATE_UART_RX;
 
 
-       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 sync1, sync2, txd_next: std_logic; --synchronizers FIXME!
-
-       -- these are internal signals that are actually used as in and output
-       signal tx_data_prev : std_logic_vector(7 downto 0);
-       signal tx_new_i : std_logic;
-       signal shift, shift_value, shift_reset : std_logic;
+       signal rx_data_next, rx_data_int : std_logic_vector(7 downto 0);
+       signal rx_new_next, rx_new_int : std_logic;
+       signal startbitdetection : std_logic_vector(1 downto 0);
+       signal bitcnt_int, bitcnt_next : integer range 0 to 7;
+       signal baudcnt_int, baudcnt_next : integer range 0 to BAUD;
 begin
 begin
+       rx_new <= rx_new_int;
+       rx_data <= rx_data_int;
 
 
-       tx_new <= tx_new_i;
-
-       process(sys_clk, sys_res)
+       process(sys_clk, sys_res_n)
        begin
        begin
-               if (sys_res = '0') then
-                       -- Set reset state
-                       state <= IDLE;
-                       tx_data_prev <= X"00";
-
-                       txd_next <= '0'; --fixme: syncronizers!
-                       sync2 <= '0';
-                       sync1 <= '0';
-                       timer <= 0;
-                       counter <= 0;
+               if (sys_res_n = '0') then
+                       state_int <= IDLE;
+                       rx_data_int <= (others => '0');
+                       rx_new_int <= '0';
+                       bitcnt_int <= 0;
+                       baudcnt_int <= 0;
+                       startbitdetection <= b"11";
                elsif rising_edge(sys_clk) then
                elsif rising_edge(sys_clk) then
-                       -- Store next state
-                       state <= state_next;
-                       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;
+                       state_int <= state_next;
+                       rx_data_int <= rx_data_next;
+                       rx_new_int <= rx_new_next;
+                       bitcnt_int <= bitcnt_next;
+                       baudcnt_int <= baudcnt_next;
+                       startbitdetection(0) <= rxd;
+                       startbitdetection(1) <= startbitdetection(0);
                end if;
        end process;
 
                end if;
        end process;
 
-       process(state, txd, counter)
+       process(state_int, rx_data_int, rxd, bitcnt_int, baudcnt_int,
+               startbitdetection)
        begin
        begin
-               state_next <= state;
+               state_next <= state_int;
+               rx_data_next <= rx_data_int;
+               rx_new_next <= '0';
+               bitcnt_next <= bitcnt_int;
+               baudcnt_next <= baudcnt_int;
 
 
-               shift <= '0';
-               shift_reset <='0';
-               shift_value <= '0';
-               timer_next <= 0;
-               counter_next <= 0;
-
-               case state is
+               case state_int is
                        when IDLE =>
                        when IDLE =>
-                               if (txd = '0') then
-                                       state_next <= BUSY;
-                                       shift_reset <= '1';
-                               end if;
-                       when BUSY =>
-                               if (counter = counter_max) then --FIXME: is this true?
-                                       state_next <= DONE;
+                               -- bei fallender flanke koennte starbit folgen
+                               if startbitdetection = b"10" then
+                                       state_next <= STARTBIT;
+                                       baudcnt_next <= 0;
                                end if;
                                end if;
+                       when STARTBIT =>
+                               rx_data_next <= (others => '0');
 
 
-                               if (timer = timer_max) then
-                                       timer_next <= 0;
-                                       counter_next <= counter + 1;
-                                       if (sample_counter < samples/2) then
-                                               shift_value <= '1';
+                               -- halbe BAUDTIME warten, um immer in der mitte abzutasten
+                               -- vgl. http://upload.wikimedia.org/wikipedia/de/d/de/RS-232_timing.png
+                               if baudcnt_int < BAUD/2 then
+                                       baudcnt_next <= baudcnt_int + 1;
+                               else
+                                       baudcnt_next <= 0;
+                                       if rxd = '0' then
+                                               -- starbit (= '0')? dann kommen daten
+                                               state_next <= DBITS;
+                                               bitcnt_next <= 0;
                                        else
                                        else
-                                               shift_value <= '0';
+                                               -- sonst war das nix...
+                                               state_next <= IDLE;
                                        end if;
                                        end if;
-                                       shift <= '1';
-                               else
-                                       timer_next <= timer + 1;
                                end if;
                                end if;
+                       when DBITS =>
+                               if baudcnt_int < BAUD then
+                                       baudcnt_next <= baudcnt_int + 1;
+                               else
+                                       baudcnt_next <= 0;
+                                       rx_data_next <= rx_data_int(6 downto 0) & rxd;
 
 
-                               if timer = timer_max/samples and txd_next = '1' then
-                                       sample_counter_next <= sample_counter + 1;
+                                       if bitcnt_int = 7 then
+                                               state_next <= STOPBIT;
+                                       else
+                                               bitcnt_next <= bitcnt_int + 1;  
+                                       end if;
+                               end if;
+                       when STOPBIT =>
+                               if baudcnt_int < BAUD then
+                                       baudcnt_next <= baudcnt_int + 1;
+                               else
+                                       state_next <= IDLE;
+                                       if rxd = '1' then
+                                               rx_new_next <= '1';
+                                       end if;
                                end if;
                                end if;
-                       when DONE =>
-                               state_next <= IDLE;
                end case;
        end process;
                end case;
        end process;
-
 end architecture beh;
 end architecture beh;