📄 myself_uart_vhdl.txt
字号:
elsif sample_count="100" then --第五个采样点
ser_sig5<=ser_buf1;
elsif sample_count="101" then --第六个采样点
ser_sig6<=ser_buf1;
end if;
--此处采用多数判断原则,三个值中有两个为同一值者,采样结果为该值.
--所以采用两两相与,再彼此相或的方式,即若其中有两值为1,则相与为1,或逻辑也为1,
--若有两者为0,则三个相与逻辑均为0,或逻辑也为0.
sample<= ( ser_sig4 and ser_sig5 )
or( ser_sig4 and ser_sig6 )
or( ser_sig5 and ser_sig6 );
end if;
data_ready<='0';
data_buf<=data_buf;--采样时数据缓冲不变
bit_count<=bit_count;--位计数器也不变,保证在同一个数据位下进行采样
sample_count<=sample_count+"001";
if sample_count="110" then--第七个采样点,进入get_data状态
state<=get_data; --只要第六次采样完毕,就已经满足了进入get_data的条件
end if; --观察仿真图,分析,采样计数为110时,先执行自加,此时值仍然为110,判断,满足IF条件,
--则下一状态为get_data,执行完该IF语句,进程挂起,计数值变化,为111.
--时钟触发,进程再启动,进入get_data状态,此时计数值不变化,为111.在此状态下bit_count自加,
--即保证了在8个sample_count下bit_count加1,执行完get_data后,若下一状态为idle,因为idle状态中
--设置了sample_count清零,若为sampling,则111加1,自动变成000,重新开始,所以sample_count值正确.
when get_data=>
if bit_count="0000" then --起始位
if sample='1' then --没有检测到起始位
state<=idle; --返回继续等待
else --为0表示检测到起始位
state<=sampling; --进行下一步采样
end if;
elsif bit_count="1001" then --停止位
if sample='1' then --检测到有效停止位
state<=data_ok; --进入data_ok,表示帧准备好
else --不是有效的停止位
state<=sampling; --继续采样,或者返回idle状态也可以.
end if;
else --有效数据位
state<=sampling; --继续下一次采样
end if;
sample_count<="000"; --采样计数器清0
data_ready<='0';
data_buf<=sample & data_buf(9 downto 1); --将得到的数据移位入数据缓存
bit_count<=bit_count+"0001"; --得到一位数据后,位计数器加1,判断下一位
when data_ok=>
state<=idle;
data_ready<='1';--该状态下发送数据
data_buf<=data_buf;
bit_count<=bit_count;
sample_count<=sample_count;
end case;
end if;
end process;
data_out<=data_buf(8 DOWNTO 1) WHEN data_ready='1' ELSE
"00000000";
END behav;
testbench:tb4
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY tb4 IS
END tb4;
ARCHITECTURE be OF tb4 IS
COMPONENT uart_re IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
ser_in: IN STD_LOGIC;
data_ready: INOUT STD_LOGIC;
data_out: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
SIGNAL rst: STD_LOGIC;
SIGNAL clk_in: STD_LOGIC;
SIGNAL ser_in: STD_LOGIC;
SIGNAL data_ready: STD_LOGIC;
SIGNAL data_out: STD_LOGIC_VECTOR(7 DOWNTO 0);
CONSTANT clk_in_period: TIME:= 25ns;
CONSTANT clk_tx_period: TIME:= 50064ns;
BEGIN
uut: uart_re PORT MAP
(rst=>rst,clk_in=>clk_in,ser_in=>ser_in,data_ready=>data_ready,data_out=>data_out);
clk_in_gen: PROCESS
BEGIN
clk_in<='0';
WAIT FOR clk_in_period/2;
clk_in<='1';
WAIT FOR clk_in_period/2;
END PROCESS;
rst_gen: PROCESS
BEGIN
rst<='0';
WAIT FOR clk_tx_period;
rst<='1';
WAIT;
END PROCESS;
data_gen: PROCESS
BEGIN
ser_in<='1';
WAIT FOR clk_tx_period;
ser_in<='0';
WAIT FOR clk_tx_period; --start bit
ser_in<='1';
WAIT FOR clk_tx_period; --first bit
ser_in<='0';
WAIT FOR clk_tx_period; --second bit
ser_in<='1';
WAIT FOR clk_tx_period; --three bit
ser_in<='0';
WAIT FOR clk_tx_period; --four bit
ser_in<='1';
WAIT FOR clk_tx_period; --five bit
ser_in<='0';
WAIT FOR clk_tx_period; --six bit
ser_in<='1';
WAIT FOR clk_tx_period; --seven bit
ser_in<='0';
WAIT FOR clk_tx_period; --eight bit
ser_in<='1';
WAIT FOR clk_tx_period; --stop bit
ser_in<='1';
WAIT;
END PROCESS;
END be;
--模块5 数码管显示模块
--08.07.22 整个程序运行正确
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY segment IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
data_en: IN STD_LOGIC; --数据是否准备好
data_in: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
wei: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--数码管位选
data_out: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)--数码管段码
);
END segment;
ARCHITECTURE behav OF segment IS
COMPONENT clock_tx IS
PORT(
clk_in: IN STD_LOGIC;
rst: IN STD_LOGIC;
clk_out: OUT STD_LOGIC
);
END COMPONENT;
SIGNAL data_temp: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL s: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL clk_out: STD_LOGIC;
SIGNAL wei_temp: STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
uut: clock_tx PORT MAP(clk_in=>clk_in,rst=>rst,clk_out=>clk_out);
PROCESS(rst,clk_in)--敏感信号为clk_in,是为了保证获得data_en的高脉冲
BEGIN
IF rst='0' THEN
data_temp<="00000000";
wei_temp<="0000";--位选全开
ELSIF clk_in'EVENT AND clk_in='1' THEN
IF data_en='1' THEN --实际上,data_en高脉冲持续一个clk_re周期
data_temp<=data_in;
END IF;
END IF;
END PROCESS;
wei<=wei_temp;
PROCESS(data_temp)
BEGIN
CASE data_temp IS
WHEN "00000000" =>s<="11000000";
WHEN "00000001" =>s<="11111001";
WHEN "00000010" =>s<="10100100";
WHEN "00000011" =>s<="10110000";
WHEN "00000100" =>s<="10011001";
WHEN "00000101" =>s<="10010010";
WHEN "00000110" =>s<="10000010";
WHEN "00000111" =>s<="11111000";
WHEN "00001000" =>s<="10000000";
WHEN "00001001" =>s<="10010000"; --9
WHEN "00001010" =>s<="10001000";
WHEN "00001011" =>s<="10000011";
WHEN "00001100" =>s<="11000110";
WHEN "00001101" =>s<="10100001";
WHEN "00001110" =>s<="10000110";
WHEN "11111111" =>s<="10001110";
WHEN OTHERS =>s<="10111111"; -- ‘-’
END CASE;
END PROCESS;
data_out<=s;
END behav;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY tb5 IS
END tb5;
ARCHITECTURE be OF tb5 IS
COMPONENT segment IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
data_in: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
data_out: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
SIGNAL clk_in: STD_LOGIC;
SIGNAL rst: STD_LOGIC;
SIGNAL data_in: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL data_out: STD_LOGIC_VECTOR(7 DOWNTO 0);
CONSTANT clk_period: time:=25 ns;
BEGIN
uut: segment PORT MAP
(rst=>rst,clk_in=>clk_in,data_in=>data_in,data_out=>data_out);
clk_gen: PROCESS
BEGIN
clk_in<='0';
WAIT FOR clk_period/2;
clk_in<='1';
WAIT FOR clk_period/2;
END PROCESS;
rst_gen: PROCESS
BEGIN
rst<='0';
WAIT FOR clk_period/2;
rst<='1';
WAIT;
END PROCESS;
others_gen: PROCESS
BEGIN
data_in<="00000000";
WAIT FOR clk_period;
data_in<="01010101";
WAIT;
END PROCESS;
END be;
--testbench: tb5
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY tb5 IS
END tb5;
ARCHITECTURE be OF tb5 IS
COMPONENT segment IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
data_in: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
data_out: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
SIGNAL clk_in: STD_LOGIC;
SIGNAL rst: STD_LOGIC;
SIGNAL data_in: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL data_out: STD_LOGIC_VECTOR(7 DOWNTO 0);
CONSTANT clk_period: time:=25 ns;
BEGIN
uut: segment PORT MAP
(rst=>rst,clk_in=>clk_in,data_in=>data_in,data_out=>data_out);
clk_gen: PROCESS
BEGIN
clk_in<='0';
WAIT FOR clk_period/2;
clk_in<='1';
WAIT FOR clk_period/2;
END PROCESS;
rst_gen: PROCESS
BEGIN
rst<='0';
WAIT FOR clk_period/2;
rst<='1';
WAIT;
END PROCESS;
others_gen: PROCESS
BEGIN
data_in<="00000000";
WAIT FOR clk_period;
data_in<="01010101";
WAIT;
END PROCESS;
END be;
--模块6 顶层模块
--通过串口调试助手,由PC发送数据给小系统板,板子接收到的数据在数码管上即时显示
--并且通过发送模块发送回PC,在串口调试助手上显示出来。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY uart_top IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
rxd: IN STD_LOGIC; --uart接收,串行数据输入
txd: OUT STD_LOGIC; --uart发送,串行数据输出
led1: INOUT STD_LOGIC; --接收模块数据准备好标志 data_ready
led2: OUT STD_LOGIC; --发送模块忙标志 busy
wei: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);--数码管位选
disp: OUT STD_LOGIC_VECTOR(7 DOWNTO 0) --数码管段选
);
END uart_top;
ARCHITECTURE behav OF uart_top IS
COMPONENT clock_tx IS
PORT(
clk_in: IN STD_LOGIC;
rst: IN STD_LOGIC;
clk_out: OUT STD_LOGIC
);
END COMPONENT;
COMPONENT uart_tx IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
send_data: IN STD_LOGIC;
data_in: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
busy: OUT STD_LOGIC;
data_out: OUT STD_LOGIC
);
END COMPONENT;
COMPONENT clock_re IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
clk_out: OUT STD_LOGIC
);
END COMPONENT;
COMPONENT uart_re IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
ser_in: IN STD_LOGIC;
data_ready: INOUT STD_LOGIC;
data_out: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
COMPONENT segment IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
data_in: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
data_en: IN STD_LOGIC;
wei: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
data_out: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
SIGNAL clk_tx: STD_LOGIC;
SIGNAL data_reg: STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL clk_re: STD_LOGIC;
SIGNAL led1_temp: STD_LOGIC;
SIGNAL led2_temp: STD_LOGIC;
BEGIN
led1<=not led1_temp;--取反赋值,根据板子上接法而定
led2<=not led2_temp;
uut1: clock_tx PORT MAP
(clk_in=>clk_in,rst=>rst,clk_out=>clk_tx);
uut2: uart_tx PORT MAP
(clk_in=>clk_in,rst=>rst,send_data=>led1_temp,data_in=>data_reg,busy=>led2_temp,data_out=>txd);
uut3: clock_re PORT MAP
(clk_in=>clk_in,rst=>rst,clk_out=>clk_re);
uut4: uart_re PORT MAP
(clk_in=>clk_in,rst=>rst,ser_in=>rxd,data_ready=>led1_temp,data_out=>data_reg);
uut5: segment PORT MAP
(clk_in=>clk_in,rst=>rst,data_en=>led1_temp,data_in=>data_reg,wei=>wei,data_out=>disp);
END behav;
--testbench:tb6
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY tb6 IS
END tb6;
ARCHITECTURE be OF tb6 IS
COMPONENT uart_top IS
PORT(
rst: IN STD_LOGIC;
clk_in: IN STD_LOGIC;
rxd: IN STD_LOGIC; --?à¨a¨o??¨?¨o?¨o?¨¨?¨oy?Y?ê???¨?|ser_in
txd: OUT STD_LOGIC; --?à¨a¨o??¤?é?¨a3?|ì?¨oy?Y?ê???¨?|data_out?ê?§uart_tx?ê?
led1: INOUT STD_LOGIC; --?¨??¤?é1a?t??1¨1?ê??à¨a¨o?¨oy?Y?¨?¨o?¨a¨o?à?data_ready
led2: OUT STD_LOGIC; --?à¨a¨o?¨oy?Y?¤?é?¨a¨a¨o?à? busy
disp: OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
SIGNAL rst: STD_LOGIC;
SIGNAL clk_in: STD_LOGIC;
SIGNAL rxd: STD_LOGIC;
SIGNAL txd: STD_LOGIC;
SIGNAL led1: STD_LOGIC;
SIGNAL led2: STD_LOGIC;
SIGNAL disp: STD_LOGIC_VECTOR(7 DOWNTO 0);
CONSTANT clk_in_period: TIME:= 25ns;
CONSTANT clk_tx_period: TIME:= 50064ns;
CONSTANT clk_re_period: TIME:= 6288ns;
BEGIN
uut: uart_top PORT MAP
(rst=>rst,clk_in=>clk_in,rxd=>rxd,txd=>txd,led1=>led1,led2=>led2,disp=>disp);
clk_gen: PROCESS
BEGIN
clk_in<='0';
WAIT FOR clk_in_period/2;
clk_in<='1';
WAIT FOR clk_in_period/2;
END PROCESS;
rst_gen: PROCESS
BEGIN
rst<='0';
WAIT FOR clk_in_period;
rst<='1';
WAIT;
END PROCESS;
data_gen: PROCESS
BEGIN
rxd<='1';
WAIT FOR clk_tx_period;
rxd<='0';
WAIT FOR clk_tx_period; --start bit
rxd<='1';
WAIT FOR clk_tx_period; --first bit
rxd<='0';
WAIT FOR clk_tx_period; --second bit
rxd<='1';
WAIT FOR clk_tx_period; --three bit
rxd<='0';
WAIT FOR clk_tx_period; --four bit
rxd<='1';
WAIT FOR clk_tx_period; --five bit
rxd<='0';
WAIT FOR clk_tx_period; --six bit
rxd<='1';
WAIT FOR clk_tx_period; --seven bit
rxd<='0';
WAIT FOR clk_tx_period; --eight bit
rxd<='1';
WAIT FOR clk_tx_period; --stop bit
rxd<='0';
WAIT;
END PROCESS;
END be;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -