From: Bernhard Urban Date: Tue, 25 May 2010 14:28:29 +0000 (+0200) Subject: uart_rx: rewrite inkl. testbench X-Git-Tag: abgabe~40^2 X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=hwmod.git;a=commitdiff_plain;h=7ab4feea3c78c90283cf2131cc31f0149e94ea85 uart_rx: rewrite inkl. testbench --- diff --git a/src/beh_uart_rx_tb.do b/src/beh_uart_rx_tb.do index 4f70701..014c50c 100644 --- a/src/beh_uart_rx_tb.do +++ b/src/beh_uart_rx_tb.do @@ -2,50 +2,9 @@ alias rr "restart -f" #signale hinzufuegen +add wave * 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 diff --git a/src/beh_uart_rx_tb.vhd b/src/beh_uart_rx_tb.vhd index bca920a..26adbda 100644 --- a/src/beh_uart_rx_tb.vhd +++ b/src/beh_uart_rx_tb.vhd @@ -7,51 +7,83 @@ entity 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) + generic map ( + CLK_FREQ => CLK_FREQ, + BAUDRATE => BAUDRATE + ) 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 - 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 - 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; diff --git a/src/uart_rx.vhd b/src/uart_rx.vhd index 2f32102..cee42a3 100644 --- a/src/uart_rx.vhd +++ b/src/uart_rx.vhd @@ -4,107 +4,110 @@ use ieee.numeric_std.all; 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 - 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 + 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 - 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 - -- 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; - process(state, txd, counter) + process(state_int, rx_data_int, rxd, bitcnt_int, baudcnt_int, + startbitdetection) 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 => - 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; + 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 - shift_value <= '0'; + -- sonst war das nix... + state_next <= IDLE; end if; - shift <= '1'; - else - timer_next <= timer + 1; 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; - when DONE => - state_next <= IDLE; end case; end process; - end architecture beh;