generic (
ADDR : std_logic_vector (15 downto 0) := X"0150");
port (
- mclk : in std_logic;
- per_addr : in std_logic_vector (7 downto 0);
- per_din : in std_logic_vector (15 downto 0); -- unused
- per_en : in std_logic;
- per_wen : in std_logic_vector (1 downto 0); -- unused
- puc : in std_logic; -- unused
- per_irq_acc : in std_logic; -- unused
- per_irq : out std_logic;
- per_dout : out std_logic_vector (15 downto 0);
-
- qcount : in std_logic_vector (31 downto 0)
- );
+ -- MCU peripheral interface
+ mclk : in std_logic;
+ puc : in std_logic;
+ per_addr : in std_logic_vector (7 downto 0);
+ per_en : in std_logic;
+ per_irq : out std_logic;
+ per_dout : out std_logic_vector (15 downto 0);
+ -- QCounter component interface
+ qclk : in std_logic;
+ qreset : in std_logic;
+ a0, b0 : in std_logic;
+ qcount : out std_logic_vector (31 downto 0));
end omsp_quadcount;
--------------------------------------------------------------------------------
-- qcount higher word logic address
constant QCNTH : std_logic_vector (15 downto 0) := ADDR + 2;
+ -- Address read decoder
signal qcntl_sel : boolean;
signal qcnth_sel : boolean;
- signal qcnth_latch : std_logic_vector (15 downto 0) := (others => '0');
-
- signal qcount_prev : std_logic_vector (31 downto 0) := (others => '0');
-
+ -- Latch of high work of qcounter component
+ signal qcnth_latch : std_logic_vector (15 downto 0);
+
+ signal qcount_out : std_logic_vector (31 downto 0);
+ -- AB error of qcounter component (lead in peripheral irq)
+ signal ab_error : std_logic;
+
+
+ component qcounter is
+ port (
+ clock : in std_logic;
+ reset : in std_logic;
+ a0, b0 : in std_logic;
+ qcount : out std_logic_vector (31 downto 0);
+ a_rise : out std_logic;
+ a_fall : out std_logic;
+ b_rise : out std_logic;
+ b_fall : out std_logic;
+ ab_event : out std_logic;
+ ab_error : out std_logic);
+ end component qcounter;
+
--------------------------------------------------------------------------------
begin
+ qcounter_1: qcounter
+ port map (
+ clock => qclk,
+ reset => qreset,
+ a0 => a0,
+ b0 => b0,
+ qcount => qcount_out,
+ a_rise => open,
+ a_fall => open,
+ b_rise => open,
+ b_fall => open,
+ ab_event => open,
+ ab_error => ab_error);
+
+
qcntl_sel <= (per_addr = QCNTL(8 downto 1)) and (per_en = '1');
qcnth_sel <= (per_addr = QCNTH(8 downto 1)) and (per_en = '1');
- per_dout <= qcount (15 downto 0) when qcntl_sel else
- qcnth_latch when qcnth_sel else
+ per_dout <= qcount_out (15 downto 0) when qcntl_sel else
+ qcnth_latch when qcnth_sel else
(others => '0');
-
- process (mclk)
+ qcount <= qcount_out;
+
+
+ -- QCNTL latch.
+ process (mclk, puc)
begin
- if (rising_edge(mclk) and qcntl_sel) then
- qcnth_latch <= qcount (31 downto 16);
+ if (puc = '1') then
+ qcnth_latch <= (others => '0');
+
+ elsif (rising_edge(mclk) and qcntl_sel) then
+ qcnth_latch <= qcount_out (31 downto 16);
+
end if;
end process;
- -- Generation of IRQ signal. (changes in lower 2 bits are suppresed)
- process (mclk)
+ -- Generation of IRQ signal. IRQ is cleared by QCNTL read operation.
+ process (mclk, puc)
begin
- if (rising_edge(mclk)) then
- qcount_prev <= qcount;
-
- if (qcntl_sel) then
- per_irq <= '0';
- elsif (qcount_prev (31 downto 2) /= qcount (31 downto 2)) then
+ if (puc = '1') then
+ per_irq <= '0';
+
+ elsif (rising_edge(mclk)) then
+ if (ab_error = '1') then
per_irq <= '1';
+
+ elsif (qcntl_sel) then
+ per_irq <= '0';
+
end if;
end if;
end process;
end component;
component omsp_quadcount is
+ generic (
+ ADDR : std_logic_vector (15 downto 0));
port (
- mclk : in std_logic;
- per_addr : in std_logic_vector (7 downto 0);
- per_din : in std_logic_vector (15 downto 0); -- unused
- per_en : in std_logic;
- per_wen : in std_logic_vector (1 downto 0); -- unused
- puc : in std_logic; -- unused
- per_irq_acc : in std_logic; -- unused
- per_irq : out std_logic; -- unused
- per_dout : out std_logic_vector (15 downto 0);
-
- qcount : in std_logic_vector (31 downto 0)
- );
- end component;
+ mclk : in std_logic;
+ puc : in std_logic;
+ per_addr : in std_logic_vector (7 downto 0);
+ per_en : in std_logic;
+ per_irq : out std_logic;
+ per_dout : out std_logic_vector (15 downto 0);
+ qclk : in std_logic;
+ qreset : in std_logic;
+ a0, b0 : in std_logic;
+ qcount : out std_logic_vector (31 downto 0));
+ end component omsp_quadcount;
component uart is
port (
);
end component;
- component qcounter is
- port (
- clock : in std_logic;
- reset : in std_logic;
- a0, b0 : in std_logic;
- qcount : out std_logic_vector (31 downto 0);
- a_rise, a_fall, b_rise, b_fall, ab_event : out std_logic;
- ab_error : out std_logic
- );
- end component;
-
signal mclk : std_logic;
signal puc : std_logic;
signal uart_dout : std_logic_vector (15 downto 0);
signal uart_irq : std_logic;
- signal qcount : std_logic_vector (31 downto 0);
--------------------------------------------------------------------------------
we => '1'
);
- omsp_quadcount_0 : omsp_quadcount port map (
- mclk => mclk,
- per_addr => per_addr,
- per_din => (others => '0'),
- per_en => per_en,
- per_wen => "00",
- puc => '0',
- per_irq_acc => '0',
- per_irq => omsp_quadcount_irq,
- per_dout => omsp_quadcount_dout,
-
- qcount => qcount
+ omsp_quadcount_1: omsp_quadcount
+ generic map (
+ ADDR => X"0150")
+ port map (
+ mclk => mclk,
+ puc => puc,
+ per_addr => per_addr,
+ per_en => per_en,
+ per_irq => omsp_quadcount_irq,
+ per_dout => omsp_quadcount_dout,
+ qclk => mclk,
+ qreset => ROT_PRESS,
+ a0 => ROT_A,
+ b0 => ROT_B,
+ qcount => open
);
uart_o : uart port map (
txd => RXD
);
- qcounter_0 : qcounter port map (
- clock => mclk,
- reset => ROT_PRESS,
- a0 => ROT_A,
- b0 => ROT_B,
- qcount => qcount,
- a_rise => open,
- a_fall => open,
- b_rise => open,
- b_fall => open,
- ab_event => open,
- ab_error => open
- );
--------------------------------------------------------------------------------
peripheral <git@rtime.felk.cvut.cz:fpga/uart> and quadcount peripheral.
First of all "Hello world" is printed and then application works like echo and
-also prints quadrature count whenever its value is changed (only whole turns
-are reported).
+also prints quadrature count whenever its value is changed.
+
+AB error of quadrature counter peripheral is handled by irq routine which prints
+message "IRQ: QCounter AB error!".
Baudrate is set to 115200.
*/
Handling of QuadCounter IRQ
*/
interrupt(QCNT_VECTOR) qcount_isr() {
- printf("[QCount = 0x%08lX]\n", qcount() >> 2);
+ puts("IRQ: QCounter AB error!");
+ qcount();
}
Main function with init and an endless loop.
*/
int main(void) {
+ uint32_t qcnt = qcount();
+ uint32_t qcnt_new;
//UBAUD = 0x04E1; //24.00MHz - 9600 baud
UBAUD = 0x0067; //24.00MHz - 115200 baud
puts("Hello world\n");
- for (;;) {
- putchar(getchar());
+ for (;;) {
+ while (!isRxEmpty()) {
+ putchar(URX);
+ }
+
+ qcnt_new = qcount();
+ if (qcnt != qcnt_new) {
+ printf("[QCount = 0x%08lX]\n", qcnt_new);
+ qcnt = qcnt_new;
+ }
}
}