From 15bd8348fa6a1a8624e1d8899c2caf602ba850cc Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> Date: Wed, 5 Oct 2011 15:48:19 +0200 Subject: [PATCH] modules: wb_simple_uart: merged with wb_virtual_uart, added WB slave adapter --- modules/wishbone/wb_uart/Manifest.py | 7 + modules/wishbone/wb_uart/build_wb.sh | 2 +- modules/wishbone/wb_uart/manifest.py | 5 - modules/wishbone/wb_uart/simple_uart_pkg.vhd | 86 +++++ modules/wishbone/wb_uart/simple_uart_wb.vhd | 335 ++++++++++++++++++ .../wb_uart/{uart.wb => simple_uart_wb.wb} | 67 +++- modules/wishbone/wb_uart/wb_simple_uart.vhd | 311 ++++++++++------ modules/wishbone/wb_uart/xwb_simple_uart.vhd | 104 ++++++ 8 files changed, 798 insertions(+), 119 deletions(-) create mode 100644 modules/wishbone/wb_uart/Manifest.py delete mode 100644 modules/wishbone/wb_uart/manifest.py create mode 100644 modules/wishbone/wb_uart/simple_uart_pkg.vhd create mode 100644 modules/wishbone/wb_uart/simple_uart_wb.vhd rename modules/wishbone/wb_uart/{uart.wb => simple_uart_wb.wb} (57%) create mode 100644 modules/wishbone/wb_uart/xwb_simple_uart.vhd diff --git a/modules/wishbone/wb_uart/Manifest.py b/modules/wishbone/wb_uart/Manifest.py new file mode 100644 index 00000000..fce05995 --- /dev/null +++ b/modules/wishbone/wb_uart/Manifest.py @@ -0,0 +1,7 @@ +files = [ "uart_async_rx.vhd", + "uart_async_tx.vhd", + "uart_baud_gen.vhd", + "simple_uart_wb.vhd", + "simple_uart_pkg.vhd", + "wb_simple_uart.vhd", + "xwb_simple_uart.vhd"]; diff --git a/modules/wishbone/wb_uart/build_wb.sh b/modules/wishbone/wb_uart/build_wb.sh index 63156eac..6971eecc 100755 --- a/modules/wishbone/wb_uart/build_wb.sh +++ b/modules/wishbone/wb_uart/build_wb.sh @@ -1,4 +1,4 @@ #!/bin/bash mkdir -p doc -wbgen2 -D ./doc/wb_uart.html -V uart_wb_slave.vhd -C ../../../../software/include/hw/wb_uart.h --cstyle defines --lang vhdl -K ../../../sim/wb_uart_defs.v uart.wb +wbgen2 -D ./doc/wb_simple_uart.html -V simple_uart_wb.vhd -p simple_uart_pkg.vhd --cstyle struct -C wb_uart.h --hstyle record --lang vhdl simple_uart_wb.wb diff --git a/modules/wishbone/wb_uart/manifest.py b/modules/wishbone/wb_uart/manifest.py deleted file mode 100644 index 5568ec6a..00000000 --- a/modules/wishbone/wb_uart/manifest.py +++ /dev/null @@ -1,5 +0,0 @@ -files = [ "uart_async_rx.vhd", - "uart_async_tx.vhd", - "uart_baud_gen.vhd", - "uart_wb_slave.vhd", - "wb_simple_uart.vhd"]; diff --git a/modules/wishbone/wb_uart/simple_uart_pkg.vhd b/modules/wishbone/wb_uart/simple_uart_pkg.vhd new file mode 100644 index 00000000..45b27351 --- /dev/null +++ b/modules/wishbone/wb_uart/simple_uart_pkg.vhd @@ -0,0 +1,86 @@ +--------------------------------------------------------------------------------------- +-- Title : Wishbone slave core for Simple Wishbone UART +--------------------------------------------------------------------------------------- +-- File : simple_uart_pkg.vhd +-- Author : auto-generated by wbgen2 from simple_uart_wb.wb +-- Created : Tue Oct 4 18:46:41 2011 +-- Standard : VHDL'87 +--------------------------------------------------------------------------------------- +-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE simple_uart_wb.wb +-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY! +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package uart_wbgen2_pkg is + + + -- Input registers (user design -> WB slave) + + type t_uart_in_registers is record + sr_tx_busy_i : std_logic; + sr_rx_rdy_i : std_logic; + rdr_rx_data_i : std_logic_vector(7 downto 0); + host_tdr_rdy_i : std_logic; + host_rdr_data_i : std_logic_vector(7 downto 0); + host_rdr_rdy_i : std_logic; + host_rdr_count_i : std_logic_vector(15 downto 0); + end record; + + constant c_uart_in_registers_init_value: t_uart_in_registers := ( + sr_tx_busy_i => '0', + sr_rx_rdy_i => '0', + rdr_rx_data_i => (others => '0'), + host_tdr_rdy_i => '0', + host_rdr_data_i => (others => '0'), + host_rdr_rdy_i => '0', + host_rdr_count_i => (others => '0') + ); + + -- Output registers (WB slave -> user design) + + type t_uart_out_registers is record + bcr_o : std_logic_vector(31 downto 0); + bcr_wr_o : std_logic; + tdr_tx_data_o : std_logic_vector(7 downto 0); + tdr_tx_data_wr_o : std_logic; + host_tdr_data_o : std_logic_vector(7 downto 0); + host_tdr_data_wr_o : std_logic; + end record; + + constant c_uart_out_registers_init_value: t_uart_out_registers := ( + bcr_o => (others => '0'), + bcr_wr_o => '0', + tdr_tx_data_o => (others => '0'), + tdr_tx_data_wr_o => '0', + host_tdr_data_o => (others => '0'), + host_tdr_data_wr_o => '0' + ); + function "or" (left, right: t_uart_in_registers) return t_uart_in_registers; + function f_x_to_zero (x:std_logic) return std_logic; +end package; + +package body uart_wbgen2_pkg is +function f_x_to_zero (x:std_logic) return std_logic is +begin +if(x = 'X' or x = 'U') then +return '0'; +else +return x; +end if; +end function; +function "or" (left, right: t_uart_in_registers) return t_uart_in_registers is +variable tmp: t_uart_in_registers; +begin +tmp.sr_tx_busy_i := left.sr_tx_busy_i or right.sr_tx_busy_i; +tmp.sr_rx_rdy_i := left.sr_rx_rdy_i or right.sr_rx_rdy_i; +tmp.rdr_rx_data_i := left.rdr_rx_data_i or right.rdr_rx_data_i; +tmp.host_tdr_rdy_i := left.host_tdr_rdy_i or right.host_tdr_rdy_i; +tmp.host_rdr_data_i := left.host_rdr_data_i or right.host_rdr_data_i; +tmp.host_rdr_rdy_i := left.host_rdr_rdy_i or right.host_rdr_rdy_i; +tmp.host_rdr_count_i := left.host_rdr_count_i or right.host_rdr_count_i; +return tmp; +end function; +end package body; diff --git a/modules/wishbone/wb_uart/simple_uart_wb.vhd b/modules/wishbone/wb_uart/simple_uart_wb.vhd new file mode 100644 index 00000000..058ba1ec --- /dev/null +++ b/modules/wishbone/wb_uart/simple_uart_wb.vhd @@ -0,0 +1,335 @@ +--------------------------------------------------------------------------------------- +-- Title : Wishbone slave core for Simple Wishbone UART +--------------------------------------------------------------------------------------- +-- File : simple_uart_wb.vhd +-- Author : auto-generated by wbgen2 from simple_uart_wb.wb +-- Created : Tue Oct 4 18:46:41 2011 +-- Standard : VHDL'87 +--------------------------------------------------------------------------------------- +-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE simple_uart_wb.wb +-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY! +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.uart_wbgen2_pkg.all; + + +entity simple_uart_wb is + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(2 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + rdr_rack_o : out std_logic; + host_rack_o : out std_logic; + regs_i : in t_uart_in_registers; + regs_o : out t_uart_out_registers + ); +end simple_uart_wb; + +architecture syn of simple_uart_wb is + +signal ack_sreg : std_logic_vector(9 downto 0); +signal rddata_reg : std_logic_vector(31 downto 0); +signal wrdata_reg : std_logic_vector(31 downto 0); +signal bwsel_reg : std_logic_vector(3 downto 0); +signal rwaddr_reg : std_logic_vector(2 downto 0); +signal ack_in_progress : std_logic ; +signal wr_int : std_logic ; +signal rd_int : std_logic ; +signal bus_clock_int : std_logic ; +signal allones : std_logic_vector(31 downto 0); +signal allzeros : std_logic_vector(31 downto 0); + +begin +-- Some internal signals assignments. For (foreseen) compatibility with other bus standards. + wrdata_reg <= wb_data_i; + bwsel_reg <= wb_sel_i; + bus_clock_int <= wb_clk_i; + rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i)); + wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i); + allones <= (others => '1'); + allzeros <= (others => '0'); +-- +-- Main register bank access process. + process (bus_clock_int, rst_n_i) + begin + if (rst_n_i = '0') then + ack_sreg <= "0000000000"; + ack_in_progress <= '0'; + rddata_reg <= "00000000000000000000000000000000"; + regs_o.bcr_wr_o <= '0'; + regs_o.tdr_tx_data_wr_o <= '0'; + rdr_rack_o <= '0'; + regs_o.host_tdr_data_wr_o <= '0'; + host_rack_o <= '0'; + elsif rising_edge(bus_clock_int) then +-- advance the ACK generator shift register + ack_sreg(8 downto 0) <= ack_sreg(9 downto 1); + ack_sreg(9) <= '0'; + if (ack_in_progress = '1') then + if (ack_sreg(0) = '1') then + regs_o.bcr_wr_o <= '0'; + regs_o.tdr_tx_data_wr_o <= '0'; + rdr_rack_o <= '0'; + regs_o.host_tdr_data_wr_o <= '0'; + host_rack_o <= '0'; + ack_in_progress <= '0'; + else + regs_o.bcr_wr_o <= '0'; + regs_o.tdr_tx_data_wr_o <= '0'; + regs_o.host_tdr_data_wr_o <= '0'; + end if; + else + if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then + case rwaddr_reg(2 downto 0) is + when "000" => + if (wb_we_i = '1') then + rddata_reg(0) <= 'X'; + rddata_reg(1) <= 'X'; + else + rddata_reg(0) <= regs_i.sr_tx_busy_i; + rddata_reg(1) <= regs_i.sr_rx_rdy_i; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "001" => + if (wb_we_i = '1') then + regs_o.bcr_wr_o <= '1'; + else + rddata_reg(0) <= 'X'; + rddata_reg(1) <= 'X'; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "010" => + if (wb_we_i = '1') then + regs_o.tdr_tx_data_wr_o <= '1'; + else + rddata_reg(0) <= 'X'; + rddata_reg(1) <= 'X'; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "011" => + if (wb_we_i = '1') then + else + rddata_reg(7 downto 0) <= regs_i.rdr_rx_data_i; + rdr_rack_o <= '1'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "100" => + if (wb_we_i = '1') then + regs_o.host_tdr_data_wr_o <= '1'; + rddata_reg(8) <= 'X'; + else + rddata_reg(8) <= regs_i.host_tdr_rdy_i; + rddata_reg(0) <= 'X'; + rddata_reg(1) <= 'X'; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "101" => + if (wb_we_i = '1') then + rddata_reg(8) <= 'X'; + else + rddata_reg(7 downto 0) <= regs_i.host_rdr_data_i; + host_rack_o <= '1'; + rddata_reg(8) <= regs_i.host_rdr_rdy_i; + rddata_reg(24 downto 9) <= regs_i.host_rdr_count_i; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when others => +-- prevent the slave from hanging the bus on invalid address + ack_in_progress <= '1'; + ack_sreg(0) <= '1'; + end case; + end if; + end if; + end if; + end process; + + +-- Drive the data output bus + wb_data_o <= rddata_reg; +-- TX busy +-- RX ready +-- Baudrate divider setting +-- pass-through field: Baudrate divider setting in register: Baudrate control register + regs_o.bcr_o <= wrdata_reg(31 downto 0); +-- Transmit data +-- pass-through field: Transmit data in register: Transmit data regsiter + regs_o.tdr_tx_data_o <= wrdata_reg(7 downto 0); +-- Received data +-- TX Data +-- pass-through field: TX Data in register: Host VUART Tx register + regs_o.host_tdr_data_o <= wrdata_reg(7 downto 0); +-- TX Ready +-- RX Data +-- RX Ready +-- RX FIFO Count + rwaddr_reg <= wb_addr_i; +-- ACK signal generation. Just pass the LSB of ACK counter. + wb_ack_o <= ack_sreg(0); +end syn; diff --git a/modules/wishbone/wb_uart/uart.wb b/modules/wishbone/wb_uart/simple_uart_wb.wb similarity index 57% rename from modules/wishbone/wb_uart/uart.wb rename to modules/wishbone/wb_uart/simple_uart_wb.wb index d211b76a..38ab2675 100644 --- a/modules/wishbone/wb_uart/uart.wb +++ b/modules/wishbone/wb_uart/simple_uart_wb.wb @@ -3,8 +3,8 @@ peripheral { name = "Simple Wishbone UART"; description = "A simple Wishbone UART (8N1 mode) with programmable baud rate. "; - prefix = "UART"; - hdl_entity = "uart_wb_slave"; + prefix = "uart"; + hdl_entity = "simple_uart_wb"; reg { name = "Status Register"; @@ -41,9 +41,7 @@ peripheral { description = "Baudrate setting. The value can be calculated using the following equation:\ BRATE = ((Baudrate * 8) << 9 + (ClockFreq >> 8)) / (ClockFreq >> 7)"; size = 32; - type = SLV; - access_bus = READ_WRITE; - access_dev = READ_ONLY; + type = PASS_THROUGH; }; }; @@ -55,18 +53,13 @@ peripheral { name = "Transmit data"; prefix = "TX_DATA"; size = 8; - type = SLV; - access_bus = READ_WRITE; - access_dev = READ_WRITE; - load = LOAD_EXT; + type = PASS_THROUGH; }; }; reg { name = "Receive data regsiter"; prefix = "RDR"; - - field { ack_read = "rdr_rack_o"; name = "Received data"; @@ -77,4 +70,56 @@ peripheral { access_dev = WRITE_ONLY; }; }; + + reg { + name = "Host VUART Tx register"; + prefix = "HOST_TDR"; + + field { + name = "TX Data"; + prefix = "DATA"; + type = PASS_THROUGH; + size = 8; + }; + + field { + name = "TX Ready"; + prefix = "RDY"; + type= BIT; + access_dev= WRITE_ONLY; + access_bus=READ_ONLY; + }; + }; + + reg { + name = "Host VUART Rx register"; + prefix = "HOST_RDR"; + + field { + ack_read = "host_rack_o"; + name = "RX Data"; + prefix = "DATA"; + type = SLV; + size = 8; + access_dev= WRITE_ONLY; + access_bus=READ_ONLY; + }; + + field { + name = "RX Ready"; + prefix = "RDY"; + type= BIT; + access_dev= WRITE_ONLY; + access_bus=READ_ONLY; + }; + + field { + name = "RX FIFO Count"; + prefix = "COUNT"; + type = SLV; + size = 16; + access_dev= WRITE_ONLY; + access_bus=READ_ONLY; + }; + }; }; \ No newline at end of file diff --git a/modules/wishbone/wb_uart/wb_simple_uart.vhd b/modules/wishbone/wb_uart/wb_simple_uart.vhd index 437a4f15..cba8b5f9 100644 --- a/modules/wishbone/wb_uart/wb_simple_uart.vhd +++ b/modules/wishbone/wb_uart/wb_simple_uart.vhd @@ -1,43 +1,57 @@ ------------------------------------------------------------------------------- --- Title : Wishbone UART for WR Core --- Project : WhiteRabbit +-- Title : Simple Wishbone UART +-- Project : General Cores Collection (gencores) library ------------------------------------------------------------------------------- --- File : wb_conmax_top.vhd +-- File : wb_simple_uart.vhd -- Author : Tomasz Wlostowski -- Company : CERN BE-Co-HT -- Created : 2011-02-21 --- Last update: 2011-02-21 +-- Last update: 2011-10-04 -- Platform : FPGA-generics --- Standard : VHDL +-- Standard : VHDL'93 ------------------------------------------------------------------------------- --- Description: --- Simple UART port with Wishbone interface --- +-- Description: A simple UART controller, providing two modes of operation +-- (both can be used simultenously): +-- - physical UART (encoding fixed to 8 data bits, no parity and one stop bit) +-- - virtual UART: TXed data is passed via a FIFO to the Wishbone host (and +-- vice versa). ------------------------------------------------------------------------------- --- Copyright (c) 2011 Tomasz Wlostowski +-- Copyright (c) 2011 CERN ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2011-02-21 1.0 twlostow Created +-- 2011-10-04 1.1 twlostow merged with VUART, added adapter ------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; +use work.genram_pkg.all; +use work.wishbone_pkg.all; +use work.UART_wbgen2_pkg.all; + entity wb_simple_uart is + generic( + g_with_virtual_uart : boolean; + g_with_physical_uart : boolean; + g_interface_mode : t_wishbone_interface_mode := CLASSIC; + g_address_granularity : t_wishbone_address_granularity := WORD + ); port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; - wb_addr_i : in std_logic_vector(1 downto 0); - wb_data_i : in std_logic_vector(31 downto 0); - wb_data_o : out std_logic_vector(31 downto 0); - wb_cyc_i : in std_logic; - wb_sel_i : in std_logic_vector(3 downto 0); - wb_stb_i : in std_logic; - wb_we_i : in std_logic; - wb_ack_o : out std_logic; + wb_adr_i : in std_logic_vector(4 downto 0); + wb_dat_i : in std_logic_vector(31 downto 0); + wb_dat_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + wb_stall_o : out std_logic; uart_rxd_i : in std_logic; uart_txd_o : out std_logic @@ -46,30 +60,8 @@ end wb_simple_uart; architecture syn of wb_simple_uart is - constant c_baud_acc_width : integer := 16; - - component uart_wb_slave - port ( - rst_n_i : in std_logic; - wb_clk_i : in std_logic; - wb_addr_i : in std_logic_vector(1 downto 0); - wb_data_i : in std_logic_vector(31 downto 0); - wb_data_o : out std_logic_vector(31 downto 0); - wb_cyc_i : in std_logic; - wb_sel_i : in std_logic_vector(3 downto 0); - wb_stb_i : in std_logic; - wb_we_i : in std_logic; - wb_ack_o : out std_logic; - uart_sr_tx_busy_i : in std_logic; - uart_sr_rx_rdy_i : in std_logic; - uart_bcr_o : out std_logic_vector(31 downto 0); - uart_tdr_tx_data_o : out std_logic_vector(7 downto 0); - uart_tdr_tx_data_i : in std_logic_vector(7 downto 0); - uart_tdr_tx_data_load_o : out std_logic; - - uart_rdr_rx_data_i : in std_logic_vector(7 downto 0); - rdr_rack_o : out std_logic); - end component; + constant c_baud_acc_width : integer := 16; + constant c_vuart_fifo_size : integer := 1024; component uart_baud_gen generic ( @@ -77,19 +69,18 @@ architecture syn of wb_simple_uart is port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; - baudrate_i : in std_logic_vector(g_baud_acc_width downto 0); + baudrate_i : in std_logic_vector(g_baud_acc_width downto 0); baud_tick_o : out std_logic; baud8_tick_o : out std_logic); end component; - component uart_async_rx port ( clk_sys_i : in std_logic; rst_n_i : in std_logic; baud8_tick_i : in std_logic; rxd_i : in std_logic; - rx_ready_o : out std_logic; + rx_ready_o : out std_logic; rx_error_o : out std_logic; rx_data_o : out std_logic_vector(7 downto 0)); end component; @@ -105,88 +96,204 @@ architecture syn of wb_simple_uart is tx_busy_o : out std_logic); end component; + component simple_uart_wb + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(2 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + rdr_rack_o : out std_logic; + host_rack_o : out std_logic; + regs_i : in t_uart_in_registers; + regs_o : out t_uart_out_registers); + end component; + signal rx_ready_reg : std_logic; signal rx_ready : std_logic; - signal uart_sr_tx_busy : std_logic; - signal uart_sr_rx_rdy : std_logic; signal uart_bcr : std_logic_vector(31 downto 0); - signal uart_tdr_tx_data : std_logic_vector(7 downto 0); - signal uart_tdr_tx_data_load : std_logic; - - signal uart_rdr_rx_data : std_logic_vector(7 downto 0); signal rdr_rack : std_logic; + signal host_rack : std_logic; signal baud_tick : std_logic; signal baud_tick8 : std_logic; + + signal resized_addr : std_logic_vector(c_wishbone_address_width-1 downto 0); + + signal wb_in : t_wishbone_slave_in; + signal wb_out : t_wishbone_slave_out; + + signal regs_in : t_UART_in_registers; + signal regs_out : t_UART_out_registers; + + signal fifo_empty, fifo_full, fifo_rd, fifo_wr : std_logic; + signal fifo_count : std_logic_vector(f_log2_size(c_vuart_fifo_size)-1 downto 0); + + signal phys_rx_ready, phys_tx_busy : std_logic; + + signal phys_rx_data : std_logic_vector(7 downto 0); + begin -- syn - BAUD_GEN : uart_baud_gen + gen_check_generics : if(not g_with_physical_uart and not g_with_virtual_uart) generate + assert false report "wb_simple_uart: dummy configuration (use virtual, physical or both uarts)" severity failure; + end generate gen_check_generics; + + resized_addr(4 downto 0) <= wb_adr_i; + resized_addr(c_wishbone_address_width-1 downto 5) <= (others => '0'); + + U_Adapter : wb_slave_adapter generic map ( - g_baud_acc_width => c_baud_acc_width) + g_master_use_struct => true, + g_master_mode => CLASSIC, + g_master_granularity => WORD, + g_slave_use_struct => false, + g_slave_mode => g_interface_mode, + g_slave_granularity => g_address_granularity) port map ( - clk_sys_i => clk_sys_i, - rst_n_i => rst_n_i, - baudrate_i => uart_bcr(c_baud_acc_width downto 0), - baud_tick_o => baud_tick, - baud8_tick_o => baud_tick8); + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + master_i => wb_out, + master_o => wb_in, + sl_adr_i => resized_addr, + sl_dat_i => wb_dat_i, + sl_sel_i => wb_sel_i, + sl_cyc_i => wb_cyc_i, + sl_stb_i => wb_stb_i, + sl_we_i => wb_we_i, + sl_dat_o => wb_dat_o, + sl_ack_o => wb_ack_o, + sl_stall_o => wb_stall_o); - TX : uart_async_tx - port map ( - clk_sys_i => clk_sys_i, - rst_n_i => rst_n_i, - baud_tick_i => baud_tick, - txd_o => uart_txd_o, - tx_start_p_i => uart_tdr_tx_data_load, - tx_data_i => uart_tdr_tx_data, - tx_busy_o => uart_sr_tx_busy); - - RX : uart_async_rx - port map ( - clk_sys_i => clk_sys_i, - rst_n_i => rst_n_i, - baud8_tick_i => baud_tick8, - rxd_i => uart_rxd_i, - rx_ready_o => rx_ready, - rx_error_o => open, - rx_data_o => uart_rdr_rx_data); - - WB_SLAVE : uart_wb_slave + U_WB_SLAVE : simple_uart_wb port map ( rst_n_i => rst_n_i, wb_clk_i => clk_sys_i, - wb_addr_i => wb_addr_i, - wb_data_i => wb_data_i, - wb_data_o => wb_data_o, - wb_cyc_i => wb_cyc_i, - wb_sel_i => wb_sel_i, - wb_stb_i => wb_stb_i, - wb_we_i => wb_we_i, - wb_ack_o => wb_ack_o, - - uart_sr_tx_busy_i => uart_sr_tx_busy, - uart_sr_rx_rdy_i => uart_sr_rx_rdy, - uart_bcr_o => uart_bcr, - uart_tdr_tx_data_o => uart_tdr_tx_data, - uart_tdr_tx_data_i => uart_tdr_tx_data, - uart_tdr_tx_data_load_o => uart_tdr_tx_data_load, - uart_rdr_rx_data_i => uart_rdr_rx_data, - rdr_rack_o => rdr_rack); - - process(clk_sys_i, rst_n_i) + wb_addr_i => wb_in.adr(2 downto 0), + wb_data_i => wb_in.dat, + wb_data_o => wb_out.dat, + wb_cyc_i => wb_in.cyc, + wb_sel_i => wb_in.sel, + wb_stb_i => wb_in.stb, + wb_we_i => wb_in.we, + wb_ack_o => wb_out.ack, + + rdr_rack_o => rdr_rack, + host_rack_o => host_rack, + regs_o => regs_out, + regs_i => regs_in); + + gen_phys_uart : if(g_with_physical_uart) generate + + p_bcr_reg : process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + uart_bcr <= (others => '0'); + elsif(regs_out.bcr_wr_o = '1')then + uart_bcr <= regs_out.bcr_o; + end if; + end if; + end process; + + U_BAUD_GEN : uart_baud_gen + generic map ( + g_baud_acc_width => c_baud_acc_width) + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + baudrate_i => uart_bcr(c_baud_acc_width downto 0), + baud_tick_o => baud_tick, + baud8_tick_o => baud_tick8); + + U_TX : uart_async_tx + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + baud_tick_i => baud_tick, + txd_o => uart_txd_o, + tx_start_p_i => regs_out.tdr_tx_data_wr_o, + tx_data_i => regs_out.tdr_tx_data_o, + tx_busy_o => phys_tx_busy); + + U_RX : uart_async_rx + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + baud8_tick_i => baud_tick8, + rxd_i => uart_rxd_i, + rx_ready_o => phys_rx_ready, + rx_error_o => open, + rx_data_o => phys_rx_data); + + end generate gen_phys_uart; + + gen_vuart : if(g_with_virtual_uart) generate + + fifo_wr <= not fifo_full and regs_out.tdr_tx_data_wr_o; + fifo_rd <= not fifo_empty and not regs_in.host_rdr_rdy_i; + + U_VUART_FIFO : generic_sync_fifo + generic map ( + g_data_width => 8, + g_size => c_vuart_fifo_size, + g_with_count => true) + port map ( + rst_n_i => rst_n_i, + clk_i => clk_sys_i, + d_i => regs_out.tdr_tx_data_o, + we_i => fifo_wr, + q_o => regs_in.host_rdr_data_i, + rd_i => fifo_rd, + empty_o => fifo_empty, + full_o => fifo_full, + count_o => fifo_count); + + regs_in.host_rdr_count_i(fifo_count'left downto 0) <= fifo_count; + regs_in.host_rdr_count_i(15 downto fifo_count'length) <= (others => '0'); + + p_vuart_rx_ready : process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + regs_in.host_rdr_rdy_i <= '0'; + elsif(fifo_rd = '1') then + regs_in.host_rdr_rdy_i <= '1'; + elsif(host_rack = '1') then + regs_in.host_rdr_rdy_i <= '0'; + end if; + end if; + end process; + + end generate gen_vuart; + + p_drive_rx_ready : process(clk_sys_i) begin if rising_edge(clk_sys_i) then if rst_n_i = '0' then - uart_sr_rx_rdy <= '0'; + regs_in.sr_rx_rdy_i <= '0'; + regs_in.rdr_rx_data_i <= (others => '0'); else - if(rx_ready = '1') then - uart_sr_rx_rdy <= '1'; - elsif(rdr_rack = '1') then - uart_sr_rx_rdy <= '0'; + if(rdr_rack = '1' and phys_rx_ready = '0' and regs_out.host_tdr_data_wr_o = '0') then + regs_in.sr_rx_rdy_i <= '0'; + elsif(phys_rx_ready = '1' and g_with_physical_uart) then + regs_in.sr_rx_rdy_i <= '1'; + regs_in.rdr_rx_data_i <= phys_rx_data; + elsif(regs_out.host_tdr_data_wr_o = '1' and g_with_virtual_uart) then + regs_in.sr_rx_rdy_i <= '1'; + regs_in.rdr_rx_data_i <= regs_out.host_tdr_data_o; end if; end if; end if; end process; + + regs_in.sr_tx_busy_i <= phys_tx_busy when (g_with_physical_uart) else '0'; end syn; diff --git a/modules/wishbone/wb_uart/xwb_simple_uart.vhd b/modules/wishbone/wb_uart/xwb_simple_uart.vhd new file mode 100644 index 00000000..0c4da820 --- /dev/null +++ b/modules/wishbone/wb_uart/xwb_simple_uart.vhd @@ -0,0 +1,104 @@ +------------------------------------------------------------------------------ +-- Title : Simple Wishbone UART +-- Project : General Cores Collection (gencores) library +------------------------------------------------------------------------------ +-- File : xwb_simple_uart.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN BE-Co-HT +-- Created : 2010-05-18 +-- Last update: 2011-10-04 +-- Platform : FPGA-generic +-- Standard : VHDL'93 +------------------------------------------------------------------------------- +-- Description: A simple UART controller, providing two modes of operation +-- (both can be used simultenously): +-- - physical UART (encoding fixed to 8 data bits, no parity and one stop bit) +-- - virtual UART: TXed data is passed via a FIFO to the Wishbone host (and +-- vice versa). +------------------------------------------------------------------------------- +-- Copyright (c) 2010 CERN +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2010-05-18 1.0 twlostow Created +-- 2011-10-04 1.1 twlostow xwb module +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.wishbone_pkg.all; + +entity xwb_simple_uart is + generic( + g_with_virtual_uart : boolean := true; + g_with_physical_uart : boolean := true; + g_interface_mode : t_wishbone_interface_mode := CLASSIC; + g_address_granularity : t_wishbone_address_granularity := WORD + ); + + port( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + -- Wishbone + slave_i : in t_wishbone_slave_in; + slave_o : out t_wishbone_slave_out; + desc_o : out t_wishbone_device_descriptor; + + uart_rxd_i: in std_logic; + uart_txd_o: out std_logic + + ); + +end xwb_simple_uart; + +architecture rtl of xwb_simple_uart is + + component wb_simple_uart + generic ( + g_with_virtual_uart : boolean; + g_with_physical_uart : boolean; + g_interface_mode : t_wishbone_interface_mode; + g_address_granularity : t_wishbone_address_granularity); + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + wb_adr_i : in std_logic_vector(4 downto 0); + wb_dat_i : in std_logic_vector(31 downto 0); + wb_dat_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + wb_stall_o : out std_logic; + uart_rxd_i : in std_logic; + uart_txd_o : out std_logic); + end component; + +begin -- rtl + + U_Wrapped_UART: wb_simple_uart + generic map ( + g_with_virtual_uart => g_with_virtual_uart, + g_with_physical_uart => g_with_physical_uart, + g_interface_mode => g_interface_mode, + g_address_granularity => g_address_granularity) + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + wb_adr_i => slave_i.adr(4 downto 0), + wb_dat_i => slave_i.dat, + wb_dat_o => slave_o.dat, + wb_cyc_i => slave_i.cyc, + wb_sel_i => slave_i.sel, + wb_stb_i => slave_i.stb, + wb_we_i => slave_i.we, + wb_ack_o => slave_o.ack, + wb_stall_o => slave_o.stall, + uart_rxd_i => uart_rxd_i, + uart_txd_o => uart_txd_o); + +end rtl; -- GitLab