Sfoglia il codice sorgente

Add a second, simpler, implementation of tx module. They also now aggree.

Jonatan Gezelius 4 anni fa
parent
commit
3411f28833

+ 1 - 1
uart_module/Makefile

@@ -7,7 +7,7 @@ VIEWERTCL = simulation/gtkwave.tcl
 #TOP_DESIGN = top.vhd # Not used when not synthesizing..
 
 # Add design files to this row
-DESIGN_FILES = generic_counter.vhd ha.vhd generic_prescaler.vhd async_8n1_tx.vhd
+DESIGN_FILES = generic_counter.vhd ha.vhd generic_prescaler.vhd async_8n1_tx_v2.vhd async_8n1_tx.vhd
 
 DESIGN_FILES_DIR = hdl_design
 DESIGN_FILES_FULL_PATH = $(addprefix $(DESIGN_FILES_DIR)/,$(DESIGN_FILES))

+ 94 - 0
uart_module/hdl_design/async_8n1_tx_v2.vhd

@@ -0,0 +1,94 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity async_8n1_tx_v2 is
+	port
+	(
+		clk : in std_logic;
+		rst : in std_logic;
+		en  : in std_logic;
+		wr  : in std_logic;
+		data_in : in unsigned (7 downto 0);
+		rdy : out std_logic;
+		data_out : out std_logic
+	);
+end entity;
+
+architecture beh of async_8n1_tx_v2 is
+	component generic_counter is
+		generic (
+			counter_bits : integer := 4
+		);
+		port(
+			clk : in std_logic;
+			rst : in std_logic;
+			en  : in std_logic;
+			cnt : out unsigned (counter_bits -1 downto 0)
+		);
+	end component;
+
+	signal i_rdy : std_logic;
+	signal i_data_reg : unsigned(8 downto 0);
+	signal i_cnt : unsigned(3 downto 0);
+	signal i_clear_counter : std_logic;
+
+begin
+	data_out <= i_data_reg(0);
+	rdy <= i_rdy;
+
+	i_counter : generic_counter
+		port map(
+			clk => clk,
+			rst => i_clear_counter,
+			en => en,
+			cnt => i_cnt);
+
+	i_clear_counter <= i_rdy;
+
+	-- Shift register
+	-- Affects registers i_data_reg and i_rdy
+	process(clk) is
+	begin
+		if rising_edge(clk) then
+			if rst = '1' then
+				-- Reset registers
+				i_data_reg <= (others => '1');
+				i_rdy <= '1';
+			elsif en = '1' then
+				-- Take a step
+				if i_rdy = '1' then
+					if wr = '1' then
+						-- Load data with start bit
+						i_data_reg <= data_in & '0';
+						-- and start transfer
+						i_rdy <= '0';
+					else
+						-- Remain idle
+						i_data_reg <= i_data_reg;
+						i_rdy <= i_rdy;
+					end if;
+				else
+					-- In transmission
+					-- Shift one step, add fill with stop bits
+					i_data_reg <= '1' & i_data_reg(8 downto 1);
+					
+					-- Did transfer finish?
+					if i_cnt = to_unsigned(8, 4) then
+						-- Yes, next bit will be stop bit and we're ready for next transfer
+						i_rdy <= '1';
+					else
+						-- No, keep transmitting
+						i_rdy <= i_rdy;
+					end if;
+				end if;
+			else
+				-- don't take a step
+				i_data_reg <= i_data_reg;
+				i_rdy <= i_rdy;
+			end if;
+		end if;
+	end process;
+
+
+end architecture;

+ 44 - 8
uart_module/testbench/async_8n1_tx_tb.vhd

@@ -34,6 +34,19 @@ architecture beh of async_8n1_tx_tb is
 		);
 	end component;
 	
+	component async_8n1_tx_v2 is
+		port
+		(
+			clk : in std_logic;
+			rst : in std_logic;
+			en  : in std_logic;
+			wr  : in std_logic;
+			data_in : in unsigned (7 downto 0);
+			rdy : out std_logic;
+			data_out : out std_logic
+		);
+	end component;
+	
 	constant freq : integer := 50; -- MHz
 	constant period : time := 1000 / freq * 1 ns;
 	constant half_period : time := period / 2;
@@ -45,13 +58,18 @@ architecture beh of async_8n1_tx_tb is
 
 	signal prescaled_clk_en : std_logic;
 	
-	constant prescaler_value : integer := 10;
+	constant prescaler_value : integer := 5;
 	constant prescaler_num_bits : integer := integer(ceil(log2(real(prescaler_value))));
 
 	signal running : boolean := true;
 	
-	signal tx : std_logic;
-	signal rdy : std_logic;
+	signal tx1 : std_logic;
+	signal rdy1 : std_logic;
+	
+	signal tx2 : std_logic;
+	signal rdy2 : std_logic;
+	
+	
 	signal wr : std_logic;
 	signal tx_char : unsigned (7 downto 0);
 	
@@ -71,7 +89,11 @@ begin
 		  '1' after 11 * period;
 	
 	--tx_char <= to_unsigned(character'pos('a'), 8);
-	tx_char <= x"aa";
+	tx_char <= x"aa",
+			   x"55" after 50 * period,
+			   x"00" after 100 * period,
+			   x"ff" after 150 * period,
+			   x"aa" after 200 * period;
 
 	i_prescaler : generic_prescaler
 		generic map(
@@ -86,15 +108,26 @@ begin
 			en_out => prescaled_clk_en
 		);
 	
-	DUT : async_8n1_tx
+	DUT1 : async_8n1_tx
+		port map(
+			clk => clock,
+			rst => reset,
+			en => '1', --prescaled_clk_en,
+			wr => wr,
+			data_in => tx_char,
+			rdy => rdy1,
+			data_out => tx1
+		);
+	
+	DUT2 : async_8n1_tx_v2
 		port map(
 			clk => clock,
 			rst => reset,
-			en => prescaled_clk_en,
+			en => '1', --prescaled_clk_en,
 			wr => wr,
 			data_in => tx_char,
-			rdy => rdy,
-			data_out => tx
+			rdy => rdy2,
+			data_out => tx2
 		);
 	-- clock process
 	process is
@@ -129,6 +162,9 @@ begin
 		if rising_edge(clock) 
 			and num_rising_edges > 1 then
 			assert not (num_rising_edges mod prescaler_value = 0 and prescaled_clk_en /= '1') report "Prescaler not working!" severity error;
+			
+			assert tx1 = tx2 report "Transciever tx disagreement" severity error;
+			assert rdy1 = rdy2 report "Transciever rdy disagreement" severity error;
 		end if;
 	end process;
 end architecture;