Ver Fonte

generic prescaler seems to be working as desired.

Jonatan Gezelius há 4 anos atrás
pai
commit
550cf3b275

+ 3 - 3
uart_module/Makefile

@@ -7,7 +7,7 @@ VIEWERTCL = simulation/gtkwave.tcl
 #TOP_DESIGN = top.vhd # Not used when not synthesizing..
 #TOP_DESIGN = top.vhd # Not used when not synthesizing..
 
 
 # Add design files to this row
 # Add design files to this row
-DESIGN_FILES = generic_counter.vhd ha.vhd
+DESIGN_FILES = generic_counter.vhd ha.vhd generic_prescaler.vhd
 
 
 DESIGN_FILES_DIR = hdl_design
 DESIGN_FILES_DIR = hdl_design
 DESIGN_FILES_FULL_PATH = $(addprefix $(DESIGN_FILES_DIR)/,$(DESIGN_FILES))
 DESIGN_FILES_FULL_PATH = $(addprefix $(DESIGN_FILES_DIR)/,$(DESIGN_FILES))
@@ -17,10 +17,10 @@ WORK_LIBRARY = work
 GHDL_OPTIONS = --work=$(WORK_LIBRARY) --workdir=$(WORK_DIR)
 GHDL_OPTIONS = --work=$(WORK_LIBRARY) --workdir=$(WORK_DIR)
 
 
 # Name of the testbench entity to simulate
 # Name of the testbench entity to simulate
-TOP_TESTBENCH = generic_counter_tb
+TOP_TESTBENCH = generic_prescaler_tb
 
 
 # Add all testbench-related files on this row
 # Add all testbench-related files on this row
-TEST_BENCHES = generic_counter_tb.vhd
+TEST_BENCHES = generic_prescaler_tb.vhd
 
 
 TEST_BENCHES_DIR = testbench
 TEST_BENCHES_DIR = testbench
 TEST_BENCHES_FULL_PATH = $(addprefix $(TEST_BENCHES_DIR)/,$(TEST_BENCHES))
 TEST_BENCHES_FULL_PATH = $(addprefix $(TEST_BENCHES_DIR)/,$(TEST_BENCHES))

+ 94 - 0
uart_module/hdl_design/generic_prescaler.vhd

@@ -0,0 +1,94 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity generic_prescaler is
+	generic (
+		prescaler_bits : integer := 8
+	);
+	port
+	(
+		clk : in std_logic;
+		rst : in std_logic;
+		en  : in std_logic;
+		load : in std_logic;
+		prescaler_value : in unsigned (prescaler_bits - 1 downto 0);
+		en_out : out std_logic
+	);
+end entity;
+
+architecture beh of generic_prescaler is
+	component generic_counter is
+		generic (
+			counter_bits : integer
+		);
+		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_match_reg : unsigned (prescaler_bits -1 downto 0);
+	signal i_counter_val : unsigned (prescaler_bits -1 downto 0);
+	
+	signal i_match : std_logic;
+	signal i_match_sync : std_logic;
+	signal i_reset_counter : std_logic;
+	
+	-- Signals for the edge detector and output
+	signal i_match_last : std_logic;
+	signal i_en_out : std_logic;
+	signal i_en_out_sync : std_logic;
+	
+begin
+	en_out <= i_en_out;
+	
+	i_match <= '1' when i_match_reg = i_counter_val
+				else '0';
+				
+	i_en_out <= i_match_sync and not i_match_last;
+	
+	i_reset_counter <= (i_match and en) or rst;
+
+	i_cntr : generic_counter
+		generic map(
+			counter_bits => prescaler_bits
+		)
+		port map(
+			clk => clk,
+			rst => i_reset_counter,
+			en => en,
+			cnt => i_counter_val
+		);
+
+	-- Positive edge detector
+	process(clk) is
+	begin
+		if rising_edge(clk) then
+			if rst = '1' then
+				i_match_last <= '0';
+				i_en_out_sync <= '0';
+				if load = '1' then
+					i_match_reg <= prescaler_value - 1;
+				end if;
+			else
+				i_match_last <= i_match_sync;
+				i_en_out_sync <= i_en_out;
+			end if;
+		end if;
+	end process;
+	
+	-- Output sync
+	process(clk) is
+	begin
+		if rising_edge(clk) then
+			if rst = '1' then
+				i_match_sync <= '0';
+			elsif en = '1' then
+				i_match_sync <= i_match;
+			end if;
+		end if;
+	end process;
+end architecture;

+ 96 - 0
uart_module/testbench/generic_prescaler_tb.vhd

@@ -0,0 +1,96 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity generic_prescaler_tb is
+end entity;
+
+architecture beh of generic_prescaler_tb is
+	component generic_prescaler is
+		generic (
+			prescaler_bits : integer := 8
+		);
+		port
+		(
+			clk : in std_logic;
+			rst : in std_logic;
+			en  : in std_logic;
+			load : in std_logic;
+			prescaler_value : in unsigned (prescaler_bits - 1 downto 0);
+			en_out : out std_logic
+		);
+	end component;
+	
+	constant freq : integer := 50; -- MHz
+	constant period : time := 1000 / freq * 1 ns;
+	constant half_period : time := period / 2;
+	signal num_rising_edges : integer := 0;
+
+	signal clock : std_logic := '0';
+	signal enable : std_logic;
+	signal reset : std_logic;
+
+	signal prescaled_clk_en : std_logic;
+	signal prescaled_clk_en2 : std_logic;
+
+	signal running : boolean := true;
+begin
+	running <= true, false after 530 * period;
+	
+	reset <= '0', '1' after 2 * period, '0' after 3 * period;
+	
+	enable <= '0', '1' after 5 * period;
+	
+	DUT : generic_prescaler
+		generic map(
+			prescaler_bits => 9
+		)
+		port map(
+			clk => clock,
+			rst => reset,
+			en => enable,
+			load => '1',
+			prescaler_value => to_unsigned(257, 9),
+			en_out => prescaled_clk_en
+		);
+	
+	DUT2 : generic_prescaler
+		generic map(
+			prescaler_bits => 8
+		)
+		port map(
+			clk => clock,
+			rst => reset,
+			en => prescaled_clk_en,
+			load => '1',
+			prescaler_value => to_unsigned(2, 8),
+			en_out => prescaled_clk_en2
+		);
+	
+	process is
+	begin
+		if running then
+			wait for half_period;
+			clock <= not clock;
+		else
+			report "End of simulation!";
+			wait;
+		end if;
+	end process;
+	
+	
+	process(clock) is
+	begin
+		if rising_edge(clock) then
+			if reset = '1' then
+				num_rising_edges <= 0;
+			elsif enable = '1' then
+				num_rising_edges <= num_rising_edges+1;
+			else
+				-- Explicit no change
+				num_rising_edges <= num_rising_edges;
+			end if;
+		end if;
+	end process;
+
+end architecture;