summaryrefslogtreecommitdiff
path: root/2004/n/fpga/src
diff options
context:
space:
mode:
authorprot2004-03-14 23:32:28 +0000
committerprot2004-03-14 23:32:28 +0000
commitb2e2ac2333ac00f53cc3b173b6433e7f5b59a36f (patch)
tree3c85a2ee69ae552d2b72e03ca1a69fe6ccabc02b /2004/n/fpga/src
parent9fe03f9a5b0ced6c9d02f0e75c1fb82fbda75424 (diff)
Port série de Bob Villedieu
Diffstat (limited to '2004/n/fpga/src')
-rw-r--r--2004/n/fpga/src/portserie/uart/rxcver.vhd162
-rw-r--r--2004/n/fpga/src/portserie/uart/txmit.vhd139
-rw-r--r--2004/n/fpga/src/portserie/uart/uart.vhd86
-rw-r--r--2004/n/fpga/src/portserie/uart/uart_tb.vhd186
4 files changed, 573 insertions, 0 deletions
diff --git a/2004/n/fpga/src/portserie/uart/rxcver.vhd b/2004/n/fpga/src/portserie/uart/rxcver.vhd
new file mode 100644
index 0000000..6a6679a
--- /dev/null
+++ b/2004/n/fpga/src/portserie/uart/rxcver.vhd
@@ -0,0 +1,162 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+
+entity RXCVER is
+ port (
+ MCLKX16 : in std_logic; -- input clock, 16x baudrate clock used for synchronization
+ READ : in std_logic; -- Read Strobe
+ RX : in std_logic; -- Receive Input Line
+ RESET : in std_logic; -- Global Reset
+
+ RXRDY : out std_logic; -- Receiver data ready to read
+ PARITY_ERR : out std_logic; -- Receiver parity error flag
+ FRAMING_ERR : out std_logic; -- Receiver framing error flag
+ OVERRUN : out std_logic; -- Receiver overrun error flag
+
+ DATA : out std_logic_vector(7 downto 0) -- 8 bit output data bus
+ );
+end RXCVER;
+
+architecture RTL of RXCVER is
+
+signal RXCNT : std_logic_vector(3 downto 0); -- clock cycle count
+signal RX1 : std_logic; -- delayed versions of rx, read, idle
+signal READ1 : std_logic;
+signal READ2 : std_logic;
+signal IDLE1 : std_logic;
+signal HUNT : std_logic; -- hunting for start bit flag
+signal RHR : std_logic_vector(7 downto 0); -- Receiver hold register
+signal RSR : std_logic_vector(7 downto 0); -- Receiver serial -> parallel shift register
+signal RXPARITY : std_logic; -- parity bit of received data
+signal PARITYGEN : std_logic; -- generated parity of received data
+signal RXSTOP : std_logic; -- stop bit of received data
+constant PARITYMODE : std_logic := '1'; -- initializing to 1 = odd parity, 0 = even parity
+signal RXCLK : std_logic; -- Receive data shift clock
+signal IDLE : std_logic; -- = '1' when receiver is idling
+signal RXDATARDY : std_logic; -- = '1' when data is ready to be read
+
+begin
+
+-- Idle requires async preset since it is clocked by rxclk, and it's
+-- value determines whether rxclk gets generated or not.
+-- Idle goes low when shifting in data. This is ensured because all bits
+-- of rsr are preset to all 1's when idle is high. Idle goes high again
+-- when rsr[0] = 0, i.e. when the low "rxstop" bit reach rsr[0].
+-- Next rising edge of rxclk preset idle to high again, and generation of
+-- rxclk is disabled.
+
+ IDLE_PRESET : process (RXCLK, RESET)
+ begin
+ if (RESET = '1') then
+ IDLE <= '1';
+ elsif (RXCLK'event and RXCLK = '1') then
+ IDLE <= (not IDLE) and (not RSR(0));
+ end if;
+ end process;
+
+
+-- Synchronizing rxclk to the centerpoint of low leading startbit.
+-- always @(posedge mclkx16)
+-- begin
+--
+-- A start bit is eight clock times with rx=0 after a falling edge of rx.
+
+ RXCLK_SYNC : process (MCLKX16, RESET)
+ begin
+ if (RESET = '1') then
+ HUNT <= '0';
+ RXCNT <= "0001";
+ RX1 <= '1';
+ RXCLK <= '0';
+ elsif (MCLKX16'event and MCLKX16 = '1') then
+ if (IDLE = '1' and RX = '0' and RX1 = '1') then
+ HUNT <= '1';
+ else
+ if (IDLE = '0' or RX = '1') then
+ HUNT <= '0';
+ end if;
+
+ if (IDLE = '0' or HUNT = '1') then
+ RXCNT <= RXCNT + 1;
+ else
+ RXCNT <= "0001";
+ end if;
+ end if;
+
+ RX1 <= RX;
+ RXCLK <= RXCNT(3);
+ end if;
+ end process;
+
+
+-- When not idling, sample data at the rx input, and generate parity.
+
+ SAMPLE_DATA : process (RXCLK, RESET)
+ begin
+ if (RESET = '1') then -- Idle_reset
+ RSR <= "11111111"; -- All 1's ensure that idle stays low during data shifting.
+ RXPARITY <= '1'; -- Preset to high to ensure idle = 0 during data shifting.
+ PARITYGEN <= PARITYMODE; -- Preset paritygen to parity mode.
+ RXSTOP <= '0';
+ elsif (RXCLK'event and RXCLK = '1') then
+ if (IDLE = '1') then -- Idle_reset
+ RSR <= "11111111"; -- All 1's ensure that idle stays low during data shifting.
+ RXPARITY <= '1'; -- Preset to high to ensure idle = 0 during data shifting.
+ PARITYGEN <= PARITYMODE; -- Preset paritygen to parity mode.
+ RXSTOP <= '0';
+ else
+ -- Shift_data
+ RSR <= '0' & RSR(7 downto 1); -- Right shift receive shift register.
+ RSR(7) <= RXPARITY; -- Load rsr[7] with rxparity.
+ RXPARITY <= RXSTOP; -- Load rxparity with rxstop.
+ RXSTOP <= RX; -- Load rxstop with rx. At 1'st shift rxstop gets low "start bit".
+ PARITYGEN <= PARITYGEN xor RXSTOP; -- Generate parity as data are shifted.
+ end if;
+ end if;
+ end process;
+
+
+-- Generate status & error flags.
+
+ GENERATE_FLAG : process (MCLKX16, RESET)
+ begin
+ if (RESET = '1') then
+ RHR <= "00000000";
+ RXDATARDY <= '0';
+ OVERRUN <= '0';
+ PARITY_ERR <= '0';
+ FRAMING_ERR <= '0';
+ IDLE1 <= '1';
+ READ2 <= '1';
+ READ1 <= '1';
+ elsif (MCLKX16'event and MCLKX16 = '1') then
+ if (IDLE = '1' and IDLE1 = '0') then
+ if (RXDATARDY = '1') then
+ OVERRUN <= '1';
+ else
+ OVERRUN <= '0'; -- No overrun error, since holding register is empty.
+ RHR <= RSR; -- Update holding register with contens of shift register.
+ PARITY_ERR <= PARITYGEN; -- Paritygen = 1, if parity error.
+ FRAMING_ERR <= not RXSTOP; -- Framingerror, if stop bit is not 1.
+ RXDATARDY <= '1'; -- Data is ready for reading flag.
+ end if;
+ end if;
+
+ if (READ2 = '0' and READ1 = '1') then
+ RXDATARDY <= '0';
+ PARITY_ERR <= '0';
+ FRAMING_ERR <= '0';
+ OVERRUN <= '0';
+ end if;
+
+ IDLE1 <= IDLE; -- Idle delayed 1 cycle for edge detect.
+ READ2 <= READ1; -- 2 cycle delayed version of read, used for edge detection.
+ READ1 <= READ; -- 1 cycle delayed version of read, used for edge detection.
+ end if;
+ end process;
+
+ RXRDY <= RXDATARDY;
+ DATA <= RHR;
+
+end RTL;
diff --git a/2004/n/fpga/src/portserie/uart/txmit.vhd b/2004/n/fpga/src/portserie/uart/txmit.vhd
new file mode 100644
index 0000000..0088729
--- /dev/null
+++ b/2004/n/fpga/src/portserie/uart/txmit.vhd
@@ -0,0 +1,139 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+
+entity TXMIT is
+ port (
+ MCLKX16 : in std_logic;
+ WRITE : in std_logic;
+ RESET : in std_logic;
+ DATA : in std_logic_vector(7 downto 0);
+
+ TX : out std_logic;
+ TXRDY : out std_logic
+ );
+end TXMIT;
+
+architecture RTL of TXMIT is
+
+ signal WRITE1 : std_logic;
+ signal WRITE2 : std_logic;
+ signal TXDONE1 : std_logic;
+ signal TXDONE : std_logic;
+ signal THR : std_logic_vector(7 downto 0);
+ signal TSR : std_logic_vector(7 downto 0);
+ signal TAG1 : std_logic;
+ signal TAG2 : std_logic;
+ constant PARITYMODE : std_logic :='1';
+ signal TXPARITY : std_logic;
+ signal TXCLK : std_logic;
+ signal PARITYCYCLE : std_logic;
+ signal TXDATARDY : std_logic;
+ signal CNT : std_logic_vector(2 downto 0);
+
+
+begin
+
+ -- Paritycycle = 1 on next to last cycle, this means when tsr[1] gets tag2.
+
+ PARITYCYCLE <= TSR(1) and not (TAG2 or TAG1 or TSR(7) or TSR(6) or TSR(5)
+ or TSR(4) or TSR(3) or TSR(2));
+
+
+ -- txdone = 1 when done shifting, this means when tx gets tag2.
+
+ TXDONE <= not (TAG2 or TAG1 or TSR(7) or TSR(6) or TSR(5) or TSR(4) or TSR(3)
+ or TSR(2) or TSR(1) or TSR(0));
+
+
+ -- Ready for new date to be written, when no data is in transmit hold register.
+
+ TXRDY <= not TXDATARDY;
+
+
+ -- Latch data[7:0] into the transmit hold register at posedge of write.
+
+ THR_WRITE : process (RESET, WRITE)
+ begin
+ if (RESET = '1') then
+ THR <= "00000000";
+ elsif (WRITE'event and WRITE = '1') then
+ THR <= DATA;
+ end if;
+ end process;
+
+
+ -- Toggle txclk every 8 counts, which divides the clock by 16, to generate the baud clock
+
+ BAUD_CLOCK_GEN : process (MCLKX16, RESET)
+ begin
+ if (RESET = '1') then
+ TXCLK <= '0';
+ CNT <= "000";
+ elsif (MCLKX16'event and MCLKX16 = '1') then
+ if (CNT = "000") then
+ TXCLK <= not TXCLK;
+ end if;
+ CNT <= CNT + 1;
+ end if;
+ end process;
+
+
+ SHIFT_OUT : process (TXCLK, RESET)
+ begin
+ -- idle_reset;
+ if (RESET = '1') then
+ TSR <= (others => '0');
+ TAG2 <= '0';
+ TAG1 <= '0';
+ TXPARITY <= PARITYMODE;
+ TX <= '1';
+ elsif (TXCLK'event and TXCLK = '1') then
+ if (TXDONE = '1' and TXDATARDY = '1') then
+ -- load_data;
+ TSR <= THR;
+ TAG2 <= '1';
+ TAG1 <= '1';
+ TXPARITY <= PARITYMODE;
+ TX <= '0';
+ else
+ -- shift_data;
+ TSR <= '0'&tsr(7 downto 1);
+ TSR(7) <= TAG1;
+ TAG1 <= TAG2;
+ TAG2 <= '0';
+ TXPARITY <= TXPARITY xor TSR(0);
+
+ if (TXDONE = '1') then
+ TX <= '1';
+ elsif (PARITYCYCLE = '1') then
+ TX <= TXPARITY;
+ else
+ TX <= TSR(0);
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ process (MCLKX16, RESET)
+ begin
+ if (RESET = '1') then
+ TXDATARDY <= '0';
+ WRITE2 <= '1';
+ WRITE1 <= '1';
+ TXDONE1 <= '1';
+ elsif (MCLKX16'event and MCLKX16 = '1') then
+ if (WRITE1 = '1' and WRITE2 = '0') then
+ TXDATARDY <= '1';
+ elsif (TXDONE = '0' and TXDONE1 = '1') then
+ TXDATARDY <= '0';
+ end if;
+ WRITE2 <= WRITE1;
+ WRITE1 <= WRITE;
+ TXDONE1 <= TXDONE;
+ end if;
+ end process;
+
+end RTL;
+
diff --git a/2004/n/fpga/src/portserie/uart/uart.vhd b/2004/n/fpga/src/portserie/uart/uart.vhd
new file mode 100644
index 0000000..89ff76d
--- /dev/null
+++ b/2004/n/fpga/src/portserie/uart/uart.vhd
@@ -0,0 +1,86 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+
+entity UART is
+ port (
+ MCLKX16 : in std_logic;
+ READ : in std_logic;
+ WRITE : in std_logic;
+ RESET : in std_logic;
+
+ DATA : inout std_logic_vector(7 downto 0);
+
+ -- receiver input signal, error, and status flags
+
+ RX : in std_logic;
+ RXRDY : out std_logic;
+ PARITY_ERR : out std_logic;
+ FRAMING_ERR : out std_logic;
+ OVERRUN : out std_logic;
+
+ -- transmitter output signal and status flag
+
+ TX : out std_logic;
+ TXRDY : out std_logic
+ );
+end UART;
+
+architecture TOP OF UART is
+
+signal RXDATA : std_logic_vector(7 downto 0);
+
+component TXMIT
+ port (
+ MCLKX16 : in std_logic;
+ WRITE : in std_logic;
+ RESET : in std_logic;
+ DATA : in std_logic_vector(7 downto 0);
+ TX : out std_logic;
+ TXRDY : out std_logic
+ );
+end component;
+
+component RXCVER
+ port (
+ MCLKX16 : in std_logic;
+ READ : in std_logic;
+ RX : in std_logic;
+ RESET : in std_logic;
+
+ RXRDY : out std_logic;
+ PARITY_ERR : out std_logic;
+ FRAMING_ERR : out std_logic;
+ OVERRUN : out std_logic;
+ DATA : out std_logic_vector(7 downto 0)
+ );
+end component;
+
+begin
+
+ TRANSMITTER : TXMIT port map
+ (
+ MCLKX16 => MCLKX16,
+ WRITE => WRITE,
+ RESET => RESET,
+ DATA => DATA,
+ TX => TX,
+ TXRDY => TXRDY
+ );
+
+
+ RECEIVER : RXCVER port map
+ (
+ MCLKX16 => MCLKX16,
+ READ => READ,
+ RX => RX,
+ RESET => RESET,
+ RXRDY => RXRDY,
+ PARITY_ERR => PARITY_ERR,
+ FRAMING_ERR => FRAMING_ERR,
+ OVERRUN => OVERRUN,
+ DATA => RXDATA
+ );
+
+ DATA <= RXDATA when (READ = '0') else "ZZZZZZZZ";
+
+end TOP;
diff --git a/2004/n/fpga/src/portserie/uart/uart_tb.vhd b/2004/n/fpga/src/portserie/uart/uart_tb.vhd
new file mode 100644
index 0000000..1ff67d1
--- /dev/null
+++ b/2004/n/fpga/src/portserie/uart/uart_tb.vhd
@@ -0,0 +1,186 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+USE ieee.std_logic_unsigned.all;
+USE ieee.std_logic_arith.all;
+LIBRARY work;
+USE work.all;
+--LIBRARY simprim;
+--USE simprim.vcomponents.all;
+--USE simprim.vpackage.all;
+
+ENTITY TestBench IS
+END TestBench;
+
+ARCHITECTURE HTWTestBench OF TestBench IS
+
+COMPONENT uart
+ PORT (
+ mclkx16 : IN std_logic;
+ read : IN std_logic;
+ write : IN std_logic;
+ reset : IN std_logic;
+
+ data : INOUT std_logic_vector(7 downto 0);
+
+ -- receiver input signal, error, and status flags
+ rx : IN std_logic;
+ rxrdy : OUT std_logic;
+ parity_err : OUT std_logic;
+ framing_err : OUT std_logic;
+ overrun : OUT std_logic;
+
+ -- transmitter output signal and status flag
+ tx : OUT std_logic;
+ txrdy : OUT std_logic
+ );
+END COMPONENT;
+
+SIGNAL mclkx16 : std_logic := '1'; -- initialized to 1
+SIGNAL read : std_logic := '1'; -- de-assert read initially
+SIGNAL write : std_logic := '1'; -- de-assert write initially
+SIGNAL reset : std_logic := '1'; -- initialized to 1
+
+SIGNAL data_int : std_logic_vector(7 downto 0);
+
+-- receiver input signal, error, and status flags
+
+SIGNAL rx : std_logic;
+SIGNAL rxrdy : std_logic;
+SIGNAL parity_err : std_logic;
+SIGNAL framing_err : std_logic;
+SIGNAL overrun : std_logic;
+
+-- transmitter output signal and status flag
+
+SIGNAL tx : std_logic;
+SIGNAL txrdy : std_logic;
+
+-- storage of data
+
+SIGNAL data_written : std_logic_vector(7 downto 0);
+SIGNAL data_received : std_logic_vector(7 downto 0);
+
+CONSTANT baudrate : time := 500 ns; -- specify the baudrate for the simulation
+
+
+BEGIN
+
+-- instantiate UART top level entity into test bench
+
+ U1 : uart port map
+ (
+ mclkx16 => mclkx16,
+ read => read,
+ write => write,
+ reset => reset,
+ data => data_int,
+ rx => rx,
+ rxrdy => rxrdy,
+ parity_err => parity_err,
+ framing_err => framing_err,
+ overrun => overrun,
+ tx => tx,
+ txrdy => txrdy
+ );
+
+
+-------------------------------------------------------------------------------
+-- Begin test bench --
+-------------------------------------------------------------------------------
+
+-- generate 16 times baudrate clock frequency
+-- (mclkx16 = baudrate/16)
+-- baudrate/(16*2) used to generate half clock cycle;
+
+mclkx16 <= (Not mclkx16) after (baudrate/(16*2));
+
+-- Reset Uart
+
+reset <= '0' after 2000 ns;
+
+-- feeding back output from transmitter to the input of receiver
+
+rx <= tx after 1 ns;
+
+
+-- core test program
+
+self_check : PROCESS
+
+ -- procedure declaration
+ -- declared in process due to assignment to write.
+ -- this procedure writes data to the transmitter
+ -- timing can be modified to model any CPU write cycle
+
+ PROCEDURE write_to_transmitter (data : IN integer) IS
+ VARIABLE din : std_logic_vector(7 downto 0);
+ BEGIN
+ din := conv_std_logic_vector(data,8);
+ write <= '0';
+ WAIT FOR 100 ns;
+ data_int <= din;
+ WAIT FOR 50 ns;
+ write <= '1';
+ data_written <= din;
+ WAIT FOR 20 ns;
+ END write_to_transmitter;
+
+
+ -- procedure declaration
+ -- declared in process due to assignment to read
+ -- this procedure reads out data from the receiver
+ -- timing can be modified to model any CPU read cycle
+
+ PROCEDURE read_out_receiver (data_in : IN std_logic_vector(7 downto 0)) IS
+ BEGIN
+ read <= '0';
+ WAIT FOR 25 ns;
+ data_received <= data_in;
+ WAIT FOR 75 ns;
+ read <= '1';
+ END read_out_receiver;
+
+
+ -- this procedure compares the data sent and received,
+ -- and flags for any error it encounters.
+ -- Comparison is done just prior to next data transmission,
+ -- and after previous received data has been read out.
+
+ PROCEDURE compare_data (dataw, datar : IN std_logic_vector(7 downto 0)) IS
+ VARIABLE data_wr, data_rv : integer range 0 to 255;
+ BEGIN
+ data_wr := conv_integer(dataw);
+ data_rv := conv_integer(datar);
+ ASSERT (data_wr = data_rv)
+ REPORT "Simulation FAILED!! data_written = "& integer'image(data_wr) &
+ " ===> data_received = "& integer'image(data_rv) SEVERITY FAILURE;
+ END compare_data ;
+
+ BEGIN
+ WAIT UNTIL mclkx16'EVENT and mclkx16 = '1';
+ IF reset = '0' THEN
+ FOR i IN 0 TO 255 LOOP -- start test loop;
+ write_to_transmitter(i); -- write_to_transmitter procedure call;
+ WAIT UNTIL (rxrdy = '1'); -- wait for rxrdy;
+ read_out_receiver(data_int); -- read_out_receiver procedure call;
+ compare_data(data_written, data_received); -- compare_data procedure call;
+ END LOOP;
+
+ REPORT "Simulation OK! Passed all possible combinations successfully!" SEVERITY NOTE;
+ REPORT " Simulation OK! Passed all possible combinations successfully! "
+ SEVERITY WARNING;
+ END IF;
+ END PROCESS;
+
+END HTWTestBench;
+
+
+-- Configuration simulation
+
+configuration TestBench1 of TestBench is
+ for HTWTestBench
+ for U1: UART use entity work.uart(TOP);
+ end for;
+ end for;
+end TestBench1;
+