├── LICENSE ├── README.md ├── baudrate_gen.py ├── generated_files ├── baudrate_gen.vhd ├── pck_myhdl_08.vhd ├── serial_rx.vhd └── serial_tx.vhd ├── serial_rx.py ├── serial_tx.py └── tb_serial.py /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 André 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

myhdl_simple_uart

2 | 3 |

A very simple UART implementation in MyHDL

4 | 5 |

This projects implements a simple UART in MyHDL and generates the VHDL files. It has been tested in a DE2-115 board.

6 |

It's a - very - simple implementation, I've done it to learn a little bit more about MyHDL.

7 | 8 |

The project has four files:

9 | 15 | 16 |

Running the project

17 | 18 |

To run the test and generate the VHDL Files go the terminal and execute the command: py.test tb_serial.py

19 |

You can also edit the tb_serial file and just call the toVHDL instructions

20 | 21 |

Viewing the waveforms

22 | 23 |

A bench.vcd file can be generated if you use the TraceSignals function at tb_serial.py, in order to do that you have to comment the VHDL Generation.

24 |

You can also run it without py.test, just call the test_bench function directly

25 | -------------------------------------------------------------------------------- /baudrate_gen.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | 3 | def baudrate_gen(sysclk, reset_n, baud_rate_i, half_baud_rate_tick_o, baud_rate_tick_o): 4 | 5 | """ Serial 6 | This module implements a baudrate generator 7 | 8 | Ports: 9 | ----- 10 | sysclk: sysclk input 11 | reset_n: reset input 12 | baud_rate_i: the baut rate to generate 13 | baud_rate_tick_o: the baud rate enable 14 | ----- 15 | 16 | """ 17 | baud_gen_count_reg = Signal(intbv(0, min = 0, max = 900)) 18 | half_baud_const = baud_rate_i//2 19 | 20 | @always_seq(sysclk.posedge, reset = reset_n) 21 | def sequential_process(): 22 | baud_gen_count_reg.next = baud_gen_count_reg + 1 23 | baud_rate_tick_o.next = 0 24 | half_baud_rate_tick_o.next = 0 25 | if baud_gen_count_reg == baud_rate_i: 26 | baud_gen_count_reg.next = 0 27 | baud_rate_tick_o.next = 1 28 | if baud_gen_count_reg == half_baud_const: 29 | half_baud_rate_tick_o.next = 1 30 | 31 | 32 | return sequential_process 33 | -------------------------------------------------------------------------------- /generated_files/baudrate_gen.vhd: -------------------------------------------------------------------------------- 1 | ----------------------------------------------------------------------------- 2 | -- Title : 3 | -- Project : 4 | ----------------------------------------------------------------------------- 5 | -- File : baudrate_gen.vhd 6 | -- Author : 7 | -- Company : 8 | -- Created : Thu Aug 21 10:54:44 2014 9 | -- Last update : Thu Aug 21 10:54:44 2014 10 | -- Target Device : Cyclone V 11 | -- Standard : VHDL'93 12 | ------------------------------------------------------------------------------ 13 | -- Description : 14 | ------------------------------------------------------------------------------ 15 | -- Generated with MyHDL Version 0.8 16 | ------------------------------------------------------------------------------ 17 | -- Copyright : (c) 2014 18 | ------------------------------------------------------------------------------ 19 | -- Revisions : 20 | -- Date Version Author Description 21 | ------------------------------------------------------------------------------ 22 | 23 | -- Libraries and use clauses 24 | 25 | 26 | library IEEE; 27 | use IEEE.std_logic_1164.all; 28 | use IEEE.numeric_std.all; 29 | use std.textio.all; 30 | 31 | use work.pck_myhdl_08.all; 32 | 33 | entity baudrate_gen is 34 | port ( 35 | sysclk: in std_logic; 36 | reset_n: in std_logic; 37 | half_baud_rate_tick_o: out std_logic; 38 | baud_rate_tick_o: out std_logic 39 | ); 40 | end entity baudrate_gen; 41 | -- Serial 42 | -- This module implements a baudrate generator 43 | -- 44 | -- Ports: 45 | -- ----- 46 | -- sysclk: sysclk input 47 | -- reset_n: reset input 48 | -- baud_rate_i: the baut rate to generate 49 | -- baud_rate_tick_o: the baud rate enable 50 | -- ----- 51 | 52 | architecture MyHDL of baudrate_gen is 53 | 54 | 55 | constant half_baud_const: integer := 434; 56 | constant baud_rate_i: integer := 868; 57 | 58 | 59 | 60 | signal baud_gen_count_reg: unsigned(9 downto 0); 61 | 62 | begin 63 | 64 | 65 | 66 | 67 | BAUDRATE_GEN_SEQUENTIAL_PROCESS: process (sysclk, reset_n) is 68 | begin 69 | if (reset_n = '0') then 70 | baud_gen_count_reg <= to_unsigned(0, 10); 71 | baud_rate_tick_o <= '0'; 72 | half_baud_rate_tick_o <= '0'; 73 | elsif rising_edge(sysclk) then 74 | baud_gen_count_reg <= (baud_gen_count_reg + 1); 75 | baud_rate_tick_o <= '0'; 76 | half_baud_rate_tick_o <= '0'; 77 | if (baud_gen_count_reg = baud_rate_i) then 78 | baud_gen_count_reg <= to_unsigned(0, 10); 79 | baud_rate_tick_o <= '1'; 80 | half_baud_rate_tick_o <= '1'; 81 | end if; 82 | if (baud_gen_count_reg = half_baud_const) then 83 | half_baud_rate_tick_o <= '1'; 84 | end if; 85 | end if; 86 | end process BAUDRATE_GEN_SEQUENTIAL_PROCESS; 87 | 88 | end architecture MyHDL; 89 | -------------------------------------------------------------------------------- /generated_files/pck_myhdl_08.vhd: -------------------------------------------------------------------------------- 1 | -- File: pck_myhdl_08.vhd 2 | -- Generated by MyHDL 0.8 3 | -- Date: Thu Aug 21 10:54:44 2014 4 | 5 | 6 | library ieee; 7 | use ieee.std_logic_1164.all; 8 | use ieee.numeric_std.all; 9 | 10 | package pck_myhdl_08 is 11 | 12 | attribute enum_encoding: string; 13 | 14 | function stdl (arg: boolean) return std_logic; 15 | 16 | function stdl (arg: integer) return std_logic; 17 | 18 | function to_unsigned (arg: boolean; size: natural) return unsigned; 19 | 20 | function to_signed (arg: boolean; size: natural) return signed; 21 | 22 | function to_integer(arg: boolean) return integer; 23 | 24 | function to_integer(arg: std_logic) return integer; 25 | 26 | function to_unsigned (arg: std_logic; size: natural) return unsigned; 27 | 28 | function to_signed (arg: std_logic; size: natural) return signed; 29 | 30 | function bool (arg: std_logic) return boolean; 31 | 32 | function bool (arg: unsigned) return boolean; 33 | 34 | function bool (arg: signed) return boolean; 35 | 36 | function bool (arg: integer) return boolean; 37 | 38 | function "-" (arg: unsigned) return signed; 39 | 40 | end pck_myhdl_08; 41 | 42 | 43 | package body pck_myhdl_08 is 44 | 45 | function stdl (arg: boolean) return std_logic is 46 | begin 47 | if arg then 48 | return '1'; 49 | else 50 | return '0'; 51 | end if; 52 | end function stdl; 53 | 54 | function stdl (arg: integer) return std_logic is 55 | begin 56 | if arg /= 0 then 57 | return '1'; 58 | else 59 | return '0'; 60 | end if; 61 | end function stdl; 62 | 63 | 64 | function to_unsigned (arg: boolean; size: natural) return unsigned is 65 | variable res: unsigned(size-1 downto 0) := (others => '0'); 66 | begin 67 | if arg then 68 | res(0):= '1'; 69 | end if; 70 | return res; 71 | end function to_unsigned; 72 | 73 | function to_signed (arg: boolean; size: natural) return signed is 74 | variable res: signed(size-1 downto 0) := (others => '0'); 75 | begin 76 | if arg then 77 | res(0) := '1'; 78 | end if; 79 | return res; 80 | end function to_signed; 81 | 82 | function to_integer(arg: boolean) return integer is 83 | begin 84 | if arg then 85 | return 1; 86 | else 87 | return 0; 88 | end if; 89 | end function to_integer; 90 | 91 | function to_integer(arg: std_logic) return integer is 92 | begin 93 | if arg = '1' then 94 | return 1; 95 | else 96 | return 0; 97 | end if; 98 | end function to_integer; 99 | 100 | function to_unsigned (arg: std_logic; size: natural) return unsigned is 101 | variable res: unsigned(size-1 downto 0) := (others => '0'); 102 | begin 103 | res(0):= arg; 104 | return res; 105 | end function to_unsigned; 106 | 107 | function to_signed (arg: std_logic; size: natural) return signed is 108 | variable res: signed(size-1 downto 0) := (others => '0'); 109 | begin 110 | res(0) := arg; 111 | return res; 112 | end function to_signed; 113 | 114 | function bool (arg: std_logic) return boolean is 115 | begin 116 | return arg = '1'; 117 | end function bool; 118 | 119 | function bool (arg: unsigned) return boolean is 120 | begin 121 | return arg /= 0; 122 | end function bool; 123 | 124 | function bool (arg: signed) return boolean is 125 | begin 126 | return arg /= 0; 127 | end function bool; 128 | 129 | function bool (arg: integer) return boolean is 130 | begin 131 | return arg /= 0; 132 | end function bool; 133 | 134 | function "-" (arg: unsigned) return signed is 135 | begin 136 | return - signed(resize(arg, arg'length+1)); 137 | end function "-"; 138 | 139 | end pck_myhdl_08; 140 | 141 | 142 | -------------------------------------------------------------------------------- /generated_files/serial_rx.vhd: -------------------------------------------------------------------------------- 1 | -- File: serial_rx.vhd 2 | -- Generated by MyHDL 0.8 3 | -- Date: Thu Aug 21 10:54:44 2014 4 | 5 | 6 | library IEEE; 7 | use IEEE.std_logic_1164.all; 8 | use IEEE.numeric_std.all; 9 | use std.textio.all; 10 | 11 | use work.pck_myhdl_08.all; 12 | 13 | entity serial_rx is 14 | port ( 15 | sysclk: in std_logic; 16 | reset_n: in std_logic; 17 | half_baud_rate_tick_i: in std_logic; 18 | baud_rate_tick_i: in std_logic; 19 | recieve_i: in std_logic; 20 | data_o: out unsigned(7 downto 0); 21 | ready_o: out std_logic 22 | ); 23 | end entity serial_rx; 24 | -- Serial 25 | -- This module implements a reciever serial interface 26 | -- 27 | -- Ports: 28 | -- ----- 29 | -- sysclk: sysclk input 30 | -- reset_n: reset input 31 | -- half_baud_rate_tick_i: half baud rate tick 32 | -- baud_rate_tick_i: the baud rate 33 | -- n_stop_bits_i: number of stop bits 34 | -- recieve_i: rx 35 | -- data_o: the data output in 1 byte 36 | -- ready_o: indicates data_o is valid 37 | -- ----- 38 | 39 | architecture MyHDL of serial_rx is 40 | 41 | 42 | constant n_stop_bits_i: integer := 2; 43 | constant END_OF_BYTE: integer := 7; 44 | 45 | 46 | type t_enum_t_State_1 is ( 47 | ST_WAIT_START_BIT, 48 | ST_GET_DATA_BITS, 49 | ST_GET_STOP_BITS 50 | ); 51 | 52 | signal data_reg: unsigned(7 downto 0); 53 | signal count_8_bits_reg: unsigned(2 downto 0); 54 | signal data: unsigned(7 downto 0); 55 | signal count_8_bits: unsigned(2 downto 0); 56 | signal ready: std_logic; 57 | signal state: t_enum_t_State_1; 58 | signal count_stop_bits_reg: unsigned(2 downto 0); 59 | signal count_stop_bits: unsigned(2 downto 0); 60 | signal state_reg: t_enum_t_State_1; 61 | signal ready_reg: std_logic; 62 | 63 | begin 64 | 65 | 66 | 67 | 68 | 69 | data_o <= data_reg; 70 | ready_o <= ready_reg; 71 | 72 | 73 | SERIAL_RX_SEQUENTIAL_PROCESS: process (sysclk, reset_n) is 74 | begin 75 | if (reset_n = '0') then 76 | count_8_bits_reg <= to_unsigned(0, 3); 77 | count_stop_bits_reg <= to_unsigned(0, 3); 78 | ready_reg <= '0'; 79 | state_reg <= ST_WAIT_START_BIT; 80 | data_reg <= to_unsigned(0, 8); 81 | elsif rising_edge(sysclk) then 82 | state_reg <= state; 83 | data_reg <= data; 84 | ready_reg <= ready; 85 | count_8_bits_reg <= count_8_bits; 86 | count_stop_bits_reg <= count_stop_bits; 87 | end if; 88 | end process SERIAL_RX_SEQUENTIAL_PROCESS; 89 | 90 | 91 | SERIAL_RX_COMBINATIONAL_PROCESS: process (count_8_bits_reg, recieve_i, data_reg, baud_rate_tick_i, count_stop_bits_reg, state_reg, ready_reg) is 92 | begin 93 | state <= state_reg; 94 | data <= data_reg; 95 | ready <= ready_reg; 96 | count_8_bits <= count_8_bits_reg; 97 | count_stop_bits <= count_stop_bits_reg; 98 | case state_reg is 99 | when ST_WAIT_START_BIT => 100 | ready <= '0'; 101 | if (baud_rate_tick_i = '1') then 102 | if (recieve_i = '0') then 103 | state <= ST_GET_DATA_BITS; 104 | end if; 105 | end if; 106 | when ST_GET_DATA_BITS => 107 | if (baud_rate_tick_i = '1') then 108 | data(to_integer(count_8_bits_reg)) <= recieve_i; 109 | if (count_8_bits_reg = END_OF_BYTE) then 110 | count_8_bits <= to_unsigned(0, 3); 111 | state <= ST_GET_STOP_BITS; 112 | else 113 | count_8_bits <= (count_8_bits_reg + 1); 114 | state <= ST_GET_DATA_BITS; 115 | end if; 116 | end if; 117 | when ST_GET_STOP_BITS => 118 | if (baud_rate_tick_i = '1') then 119 | if (signed(resize(count_stop_bits_reg, 4)) = (n_stop_bits_i - 1)) then 120 | count_stop_bits <= to_unsigned(0, 3); 121 | ready <= '1'; 122 | state <= ST_WAIT_START_BIT; 123 | else 124 | count_stop_bits <= (count_stop_bits_reg + 1); 125 | end if; 126 | end if; 127 | when others => 128 | assert False report "End of Simulation" severity Failure; 129 | end case; 130 | end process SERIAL_RX_COMBINATIONAL_PROCESS; 131 | 132 | end architecture MyHDL; 133 | -------------------------------------------------------------------------------- /generated_files/serial_tx.vhd: -------------------------------------------------------------------------------- 1 | -- File: serial_tx.vhd 2 | -- Generated by MyHDL 0.8 3 | -- Date: Thu Aug 21 10:54:44 2014 4 | 5 | 6 | library IEEE; 7 | use IEEE.std_logic_1164.all; 8 | use IEEE.numeric_std.all; 9 | use std.textio.all; 10 | 11 | use work.pck_myhdl_08.all; 12 | 13 | entity serial_tx is 14 | port ( 15 | sysclk: in std_logic; 16 | reset_n: in std_logic; 17 | start_i: in std_logic; 18 | data_i: in unsigned(7 downto 0); 19 | baud_rate_tick_i: in std_logic; 20 | transmit_o: out std_logic 21 | ); 22 | end entity serial_tx; 23 | -- Serial 24 | -- This module implements a transmitter serial interface 25 | -- 26 | -- Ports: 27 | -- ----- 28 | -- sysclk: sysclk input 29 | -- reset_n: reset input 30 | -- baud_rate_tick_i: the baud rate 31 | -- start_i: start sending data 32 | -- data_i: the data to send 33 | -- n_stop_bits_i: number of stop bits 34 | -- transmit_o: data output 35 | -- ----- 36 | 37 | architecture MyHDL of serial_tx is 38 | 39 | 40 | constant n_stop_bits_i: integer := 2; 41 | constant END_OF_BYTE: integer := 7; 42 | 43 | 44 | type t_enum_t_State_1 is ( 45 | ST_WAIT_START, 46 | ST_SEND_START_BIT, 47 | ST_SEND_DATA, 48 | ST_SEND_STOP_BIT 49 | ); 50 | 51 | signal transmit_reg: std_logic; 52 | signal count_8_bits: unsigned(2 downto 0); 53 | signal count_8_bits_reg: unsigned(2 downto 0); 54 | signal state: t_enum_t_State_1; 55 | signal transmit: std_logic; 56 | signal count_stop_bits_reg: unsigned(2 downto 0); 57 | signal count_stop_bits: unsigned(2 downto 0); 58 | signal state_reg: t_enum_t_State_1; 59 | 60 | begin 61 | 62 | 63 | 64 | 65 | 66 | transmit_o <= transmit_reg; 67 | 68 | 69 | SERIAL_TX_SEQUENTIAL_PROCESS: process (sysclk, reset_n) is 70 | begin 71 | if (reset_n = '0') then 72 | count_8_bits_reg <= to_unsigned(0, 3); 73 | count_stop_bits_reg <= to_unsigned(0, 3); 74 | transmit_reg <= '0'; 75 | state_reg <= ST_WAIT_START; 76 | elsif rising_edge(sysclk) then 77 | state_reg <= state; 78 | transmit_reg <= transmit; 79 | count_8_bits_reg <= count_8_bits; 80 | count_stop_bits_reg <= count_stop_bits; 81 | end if; 82 | end process SERIAL_TX_SEQUENTIAL_PROCESS; 83 | 84 | 85 | SERIAL_TX_COMBINATIONAL_PROCESS: process (transmit_reg, start_i, count_8_bits_reg, data_i, baud_rate_tick_i, count_stop_bits_reg, state_reg) is 86 | begin 87 | state <= state_reg; 88 | transmit <= transmit_reg; 89 | count_8_bits <= count_8_bits_reg; 90 | count_stop_bits <= count_stop_bits_reg; 91 | case state_reg is 92 | when ST_WAIT_START => 93 | transmit <= '1'; 94 | if (start_i = '1') then 95 | state <= ST_SEND_START_BIT; 96 | end if; 97 | when ST_SEND_START_BIT => 98 | transmit <= '0'; 99 | if (baud_rate_tick_i = '1') then 100 | state <= ST_SEND_DATA; 101 | end if; 102 | when ST_SEND_DATA => 103 | transmit <= data_i(to_integer(count_8_bits_reg)); 104 | if (baud_rate_tick_i = '1') then 105 | if (count_8_bits_reg = END_OF_BYTE) then 106 | count_8_bits <= to_unsigned(0, 3); 107 | state <= ST_SEND_STOP_BIT; 108 | else 109 | count_8_bits <= (count_8_bits_reg + 1); 110 | state <= ST_SEND_DATA; 111 | end if; 112 | end if; 113 | when ST_SEND_STOP_BIT => 114 | transmit <= '1'; 115 | if (baud_rate_tick_i = '1') then 116 | if (signed(resize(count_stop_bits_reg, 4)) = (n_stop_bits_i - 1)) then 117 | count_stop_bits <= to_unsigned(0, 3); 118 | state <= ST_WAIT_START; 119 | else 120 | count_stop_bits <= (count_stop_bits_reg + 1); 121 | end if; 122 | end if; 123 | when others => 124 | assert False report "End of Simulation" severity Failure; 125 | end case; 126 | end process SERIAL_TX_COMBINATIONAL_PROCESS; 127 | 128 | end architecture MyHDL; 129 | -------------------------------------------------------------------------------- /serial_rx.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | 3 | t_State = enum('ST_WAIT_START_BIT', 'ST_GET_DATA_BITS', 'ST_GET_STOP_BITS' ) 4 | 5 | 6 | def serial_rx(sysclk, reset_n, n_stop_bits_i, half_baud_rate_tick_i, baud_rate_tick_i, recieve_i, data_o, ready_o): 7 | 8 | """ Serial 9 | This module implements a reciever serial interface 10 | 11 | Ports: 12 | ----- 13 | sysclk: sysclk input 14 | reset_n: reset input 15 | half_baud_rate_tick_i: half baud rate tick 16 | baud_rate_tick_i: the baud rate 17 | n_stop_bits_i: number of stop bits 18 | recieve_i: rx 19 | data_o: the data output in 1 byte 20 | ready_o: indicates data_o is valid 21 | ----- 22 | 23 | """ 24 | END_OF_BYTE = 7 25 | 26 | state_reg = Signal(t_State.ST_WAIT_START_BIT) 27 | state = Signal(t_State.ST_WAIT_START_BIT) 28 | 29 | data_reg = Signal(intbv(0, min = 0, max = 256)) 30 | data = Signal(intbv(0, min = 0, max = 256)) 31 | ready_reg = Signal(bool(0)) 32 | ready = Signal(bool(0)) 33 | 34 | count_8_bits_reg = Signal(intbv(0, min = 0, max = 8)) 35 | count_8_bits = Signal(intbv(0, min = 0, max = 8)) 36 | 37 | count_stop_bits_reg = Signal(intbv(0, min = 0, max = 8)) 38 | count_stop_bits = Signal(intbv(0, min = 0, max = 8)) 39 | 40 | @always_comb 41 | def outputs(): 42 | data_o.next = data_reg 43 | ready_o.next = ready_reg 44 | 45 | 46 | @always_seq(sysclk.posedge, reset = reset_n) 47 | def sequential_process(): 48 | state_reg.next = state 49 | data_reg.next = data 50 | ready_reg.next = ready 51 | count_8_bits_reg.next = count_8_bits 52 | count_stop_bits_reg.next = count_stop_bits 53 | 54 | @always_comb 55 | def combinational_process(): 56 | state.next = state_reg 57 | data.next = data_reg 58 | ready.next = ready_reg 59 | count_8_bits.next = count_8_bits_reg 60 | count_stop_bits.next = count_stop_bits_reg 61 | 62 | if state_reg == t_State.ST_WAIT_START_BIT: 63 | ready.next = False 64 | if baud_rate_tick_i == True: 65 | if recieve_i == False: 66 | state.next = t_State.ST_GET_DATA_BITS 67 | 68 | elif state_reg == t_State.ST_GET_DATA_BITS: 69 | if baud_rate_tick_i == True: 70 | data.next[count_8_bits_reg] = recieve_i 71 | if count_8_bits_reg == END_OF_BYTE: 72 | count_8_bits.next = 0 73 | state.next = t_State.ST_GET_STOP_BITS 74 | else: 75 | count_8_bits.next = count_8_bits_reg + 1 76 | state.next = t_State.ST_GET_DATA_BITS 77 | 78 | 79 | elif state_reg == t_State.ST_GET_STOP_BITS: 80 | if baud_rate_tick_i == True: 81 | if count_stop_bits_reg == (n_stop_bits_i - 1): 82 | count_stop_bits.next = 0 83 | ready.next = True 84 | state.next = t_State.ST_WAIT_START_BIT 85 | else: 86 | count_stop_bits.next = count_stop_bits_reg + 1 87 | else: 88 | raise ValueError("Undefined State") 89 | 90 | 91 | 92 | return outputs, sequential_process, combinational_process 93 | 94 | -------------------------------------------------------------------------------- /serial_tx.py: -------------------------------------------------------------------------------- 1 | from myhdl import * 2 | 3 | t_State = enum('ST_WAIT_START', 'ST_SEND_START_BIT', 'ST_SEND_DATA' , 'ST_SEND_STOP_BIT' ) 4 | 5 | 6 | def serial_tx(sysclk, reset_n, start_i, data_i, n_stop_bits_i, baud_rate_tick_i, transmit_o): 7 | 8 | """ Serial 9 | This module implements a transmitter serial interface 10 | 11 | Ports: 12 | ----- 13 | sysclk: sysclk input 14 | reset_n: reset input 15 | baud_rate_tick_i: the baud rate 16 | start_i: start sending data 17 | data_i: the data to send 18 | n_stop_bits_i: number of stop bits 19 | transmit_o: data output 20 | ----- 21 | 22 | """ 23 | END_OF_BYTE = 7 24 | 25 | state_reg = Signal(t_State.ST_WAIT_START) 26 | state = Signal(t_State.ST_WAIT_START) 27 | 28 | transmit_reg = Signal(bool(0)) 29 | transmit = Signal(bool(0)) 30 | 31 | count_8_bits_reg = Signal(intbv(0, min = 0, max = 8)) 32 | count_8_bits = Signal(intbv(0, min = 0, max = 8)) 33 | 34 | count_stop_bits_reg = Signal(intbv(0, min = 0, max = 8)) 35 | count_stop_bits = Signal(intbv(0, min = 0, max = 8)) 36 | 37 | @always_comb 38 | def outputs(): 39 | transmit_o.next = transmit_reg 40 | 41 | @always_seq(sysclk.posedge, reset = reset_n) 42 | def sequential_process(): 43 | state_reg.next = state 44 | transmit_reg.next = transmit 45 | count_8_bits_reg.next = count_8_bits 46 | count_stop_bits_reg.next = count_stop_bits 47 | 48 | @always_comb 49 | def combinational_process(): 50 | state.next = state_reg 51 | transmit.next = transmit_reg 52 | count_8_bits.next = count_8_bits_reg 53 | count_stop_bits.next = count_stop_bits_reg 54 | 55 | if state_reg == t_State.ST_WAIT_START: 56 | transmit.next = True 57 | if start_i == True: 58 | state.next = t_State.ST_SEND_START_BIT 59 | 60 | elif state_reg == t_State.ST_SEND_START_BIT: 61 | transmit.next = False 62 | if baud_rate_tick_i == True: 63 | state.next = t_State.ST_SEND_DATA 64 | 65 | elif state_reg == t_State.ST_SEND_DATA: 66 | transmit.next = data_i[count_8_bits_reg] 67 | if baud_rate_tick_i == True: 68 | if count_8_bits_reg == END_OF_BYTE: 69 | count_8_bits.next = 0 70 | state.next = t_State.ST_SEND_STOP_BIT 71 | else: 72 | count_8_bits.next = count_8_bits_reg + 1 73 | state.next = t_State.ST_SEND_DATA 74 | 75 | 76 | elif state_reg == t_State.ST_SEND_STOP_BIT: 77 | transmit.next = True 78 | if baud_rate_tick_i == True: 79 | if count_stop_bits_reg == (n_stop_bits_i - 1): 80 | count_stop_bits.next = 0 81 | state.next = t_State.ST_WAIT_START 82 | else: 83 | count_stop_bits.next = count_stop_bits_reg + 1 84 | else: 85 | raise ValueError("Undefined State") 86 | 87 | 88 | 89 | return outputs, sequential_process, combinational_process 90 | -------------------------------------------------------------------------------- /tb_serial.py: -------------------------------------------------------------------------------- 1 | from math import * 2 | from myhdl import * 3 | 4 | from serial_tx import serial_tx 5 | from serial_rx import serial_rx 6 | from baudrate_gen import baudrate_gen 7 | 8 | new_header = """\ 9 | ----------------------------------------------------------------------------- 10 | -- Title : 11 | -- Project : 12 | ----------------------------------------------------------------------------- 13 | -- File : $filename 14 | -- Author : 15 | -- Company : 16 | -- Created : $date 17 | -- Last update : $date 18 | -- Target Device : Cyclone V 19 | -- Standard : VHDL'93 20 | ------------------------------------------------------------------------------ 21 | -- Description : 22 | ------------------------------------------------------------------------------ 23 | -- Generated with MyHDL Version $version 24 | ------------------------------------------------------------------------------ 25 | -- Copyright : (c) 2014 26 | ------------------------------------------------------------------------------ 27 | -- Revisions : 28 | -- Date Version Author Description 29 | ------------------------------------------------------------------------------ 30 | 31 | -- Libraries and use clauses 32 | """ 33 | 34 | def bench(): 35 | 36 | CLK_PERIOD = 10 37 | clk_freq = 100000000 38 | baud_const = int(floor(clk_freq / 115200)) 39 | clock = Signal(bool(0)) 40 | reset = ResetSignal(0, active=0, async=True) 41 | start = Signal(False) 42 | rx_rdy = Signal(False) 43 | tx_data = Signal(intbv(0, min = 0, max = 256)) 44 | rx_data = Signal(intbv(0, min = 0, max = 256)) 45 | n_stop_bits = 2 46 | baudrate_tick = Signal(bool(0)) 47 | half_baudrate_tick = Signal(bool(0)) 48 | tx = Signal(bool(0)) 49 | rx = Signal(bool(0)) 50 | 51 | 52 | # design under test 53 | # uncomment if you to test only and skip VHDL generation 54 | #baud_gen_inst = baudrate_gen(clock, reset, baud_const, half_baudrate_tick, baudrate_tick) 55 | #serial_tx_inst = serial_tx(clock, reset, start, tx_data, n_stop_bits, baudrate_tick, tx) 56 | #serial_rx_inst = serial_rx(clock, reset, n_stop_bits, half_baudrate_tick, baudrate_tick, tx, rx_data, rx_rdy) 57 | 58 | # comment if you want to test only and skip VHDL generation 59 | toVHDL.header = new_header 60 | toVHDL.no_myhdl_header = True 61 | baud_gen_inst = toVHDL(baudrate_gen, clock, reset, baud_const, half_baudrate_tick, baudrate_tick) 62 | serial_tx_inst = toVHDL(serial_tx, clock, reset, start, tx_data, n_stop_bits, baudrate_tick, tx) 63 | serial_rx_inst = toVHDL(serial_rx, clock, reset, n_stop_bits, half_baudrate_tick, baudrate_tick, tx, rx_data, rx_rdy) 64 | 65 | 66 | # clock generator 67 | @always(delay(CLK_PERIOD/2)) 68 | def clockgen(): 69 | clock.next = not clock 70 | 71 | @instance 72 | def stimulus(): 73 | tx_data.next = 196 74 | reset.next = 0 75 | for i in range(1): 76 | yield clock.negedge 77 | reset.next = 1 78 | for i in range(10): 79 | yield clock.negedge 80 | start.next = 1 81 | yield clock.negedge 82 | start.next = 0 83 | yield rx_rdy 84 | assert (rx_data == tx_data) 85 | 86 | return baud_gen_inst, serial_tx_inst, serial_rx_inst, clockgen, stimulus 87 | 88 | 89 | def test_bench(): 90 | tb = bench() 91 | #uncomment to generate waveforms 92 | #tb = traceSignals(bench) 93 | sim = Simulation(tb) 94 | sim.run(1000000) 95 | 96 | 97 | 98 | --------------------------------------------------------------------------------