Interface (インターフェース) 2009年 09月号 [雑誌], pp.116-118
今度は受信。
シリアル通信用クロックはボーレートの16倍にする。シリアルラインがHからLに下がってそこから6クロック目(0から数えて6クロック目)がやはりLであったら確かにスタートビットであると見なし、それ以降16クロックごとにデータを読み取る。
↓ これがシミュレーション結果:
↓ これが本体:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity serial_rx is generic( F_CLK: positive := 48_000_000; BAUD : positive := 9600 ); port( clk : in std_logic; aclr_n: in std_logic; din : in std_logic; pol_inv: in std_logic; -- 0: 正論理; 1: 負論理 rd : out std_logic; dout: out std_logic_vector(7 downto 0) ); end entity; architecture rtl of serial_rx is signal buf : std_logic_vector(7 downto 0) := (others => '0'); signal start: std_logic := '1'; signal cbit : natural range 0 to 150 := 0 ; signal rx_en: std_logic := '0'; signal din_temp: std_logic := '1'; begin module_clk_gen: entity work.clk_gen generic map( F_CLK => F_CLK, OUT_FREQ => BAUD * 16 ) port map( aclr_n => aclr_n, clk => clk, clk_out => rx_en ); din_temp <= din when pol_inv = '0' else not din; process(aclr_n, rx_en) begin if aclr_n = '0' then start <= '0'; cbit <= 0 ; buf <= (others => '0'); dout <= (others => '0'); elsif rising_edge(rx_en) then if start = '0' then rd <= '0'; if din_temp = '0' then -- HからLに変化して、 start <= '1'; end if; cbit <= 0; else case cbit is when 6 => -- それが本当にスタートビットであったら、 if din_temp = '1' then cbit <= 0 ; start <= '0'; else cbit <= cbit + 1; end if; when 22|38|54|70|86|102|118|134 => cbit <= cbit + 1; buf <= din_temp & buf(7 downto 1); -- lsbから順番に読み取る。 when 150 => cbit <= 0 ; dout <= buf; start <= '0'; rd <= '1'; when others => cbit <= cbit + 1; end case; end if; end if; end process; end architecture;
↓ これがテストベンチ:
-- Copyright (C) 2020 Intel Corporation. All rights reserved. -- Your use of Intel Corporation's design tools, logic functions -- and other software and tools, and any partner logic -- functions, and any output files from any of the foregoing -- (including device programming or simulation files), and any -- associated documentation or information are expressly subject -- to the terms and conditions of the Intel Program License -- Subscription Agreement, the Intel Quartus Prime License Agreement, -- the Intel FPGA IP License Agreement, or other applicable license -- agreement, including, without limitation, that your use is for -- the sole purpose of programming logic devices manufactured by -- Intel and sold by Intel or its authorized distributors. Please -- refer to the applicable agreement for further details, at -- https://fpgasoftware.intel.com/eula. -- *************************************************************************** -- This file contains a Vhdl test bench template that is freely editable to -- suit user's needs .Comments are provided in each section to help the user -- fill out necessary details. -- *************************************************************************** -- Generated on "10/03/2021 08:45:28" -- Vhdl Test Bench template for design : serial_rx -- -- Simulation tool : ModelSim-Altera (VHDL) -- LIBRARY ieee; USE ieee.std_logic_1164.all; ENTITY serial_rx_vhd_tst IS END serial_rx_vhd_tst; ARCHITECTURE serial_rx_arch OF serial_rx_vhd_tst IS -- constants -- signals SIGNAL aclr_n : STD_LOGIC; SIGNAL clk : STD_LOGIC; SIGNAL din : STD_LOGIC; SIGNAL dout : STD_LOGIC_VECTOR(7 DOWNTO 0); SIGNAL pol_inv : STD_LOGIC; SIGNAL rd : STD_LOGIC; COMPONENT serial_rx PORT ( aclr_n : IN STD_LOGIC; clk : IN STD_LOGIC; din : IN STD_LOGIC; dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); pol_inv : IN STD_LOGIC; rd : OUT STD_LOGIC ); END COMPONENT; BEGIN i1 : serial_rx PORT MAP ( -- list connections between master ports and signals aclr_n => aclr_n, clk => clk, din => din, dout => dout, pol_inv => pol_inv, rd => rd ); process begin aclr_n <= '1'; pol_inv <= '0'; wait; end process; process begin clk <= '1'; wait for 10417 ps; clk <= '0'; wait for 10417 ps; end process; process type char_array_t is array(natural range <>) of std_logic_vector; variable d: char_array_t(0 to 3)(7 downto 0) := (8x"3E", 8x"3F", 8x"40", 8x"41"); begin din <= '1'; wait for 500 us; for i in d'range loop din <= '0'; wait for 104167 ns; -- スタートビット for j in d(i)'reverse_range loop din <= d(i)(j); wait for 104167 ns; end loop; din <= '1'; wait for 104167 ns; -- ストップビット din <= '1'; wait for 100 ns; end loop; wait; end process; END serial_rx_arch;