📄 ip4290307.vhd
字号:
--程序功能:接收ARINC429信号,自动识别速度大小,读取的数据不存储,在间歇周期输出
--程序接口:5M时钟输入,片选,复位,同步时钟输入,串行数据输入,输出间歇周期指示,
-- 输出速度指示,输出并行数据
--其他说明:2008年3月7日由徐志兵创建
library ieee;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_1164.all;
entity ip4290307 is
port(
clk20m : in std_logic;
cs : in std_logic;
reset : in std_logic;
syn_clk : in std_logic;
serial_data : in std_logic;
speed : out std_logic_vector(1 downto 0);
inter : out std_logic;
saveclk : out std_logic;--增加为了给下级存储器存储用。
-- tregdata : out std_logic_vector(31 downto 0);--仿真查看用
-- cchk_count : out std_logic_vector(7 downto 0);--仿真查看用
parallel_data : out std_logic_vector(31 downto 0)
);
end ip4290307;
architecture a of ip4290307 is
signal sampling_reg : std_logic_vector(9 downto 0);--采样寄存器,判断间歇周期用
signal count : std_logic_vector(7 downto 0);--用来做延时1us,读取数据用
signal sampling_clk : std_logic_vector(6 downto 0);--采用时钟
signal reg_data : std_logic_vector(31 downto 0);--32位寄存器,读取数据时用
signal chk_count : std_logic_vector(7 downto 0);--识别速度用
signal temp_count : std_logic_vector(3 downto 0);--给chk_count清零用
signal high_low : std_logic_vector(1 downto 0);--速度指示
signal reg_count : std_logic_vector(7 downto 0);--存储频率计计数值
signal clk5ma : std_logic;
signal clk10m : std_logic;
signal clk5mc : std_logic;
signal clk10ma : std_logic;
signal divcount : std_logic_vector(1 downto 0);
signal savecount : std_logic_vector(7 downto 0);
signal clearance : std_logic;--间歇周期指示
begin
--12.5K 半周期40us 80*4 = 320us 40/0.2=200 1100 1000
-- 48K 半周期10us 20*4 = 80us 10/0.2=50 11 0010
-- 100K 半周期 5us 10*4 = 40us 5/0.2=25 1 1001
-- 250K 半周期 2us 4*4 = 16us 2/0.2=10 1010
-- 为了测试增加的寄存器
-- cchk_count <= count;
-- tregdata <= reg_data;
speed <= high_low;
inter <= clearance;
-- 为了测试增加的寄存器
process(clk20m)
begin
if rising_edge(clk20m) then
divcount <= divcount+1;
end if;
end process;
clk5ma <= not divcount(1);
clk10m <= divcount(0);
clk5mc <= divcount(1);
clk10ma <= not divcount(0);
process(clk5ma,syn_clk,chk_count,temp_count,reg_count)--识别速度,0.2us
begin
if (syn_clk = '1') then
temp_count <= "0000";
if falling_edge(clk5ma) then--对同步时钟为高时进行计数相当于频率计
chk_count <= chk_count + 1;
end if;
else
if temp_count = "0101" then--同步时钟为低时,把计数值存起来,一个低电平只赋一次
reg_count <= chk_count;
end if;
if falling_edge(clk5ma) then--一个低电平只能赋值一次,不然计数器清零时,寄存器的值跟着变
if temp_count = "0110" then--一直留在“0110”上
temp_count <= temp_count;
chk_count <= "00000000";--低电平时要给高电平计数器清零以备下次频率采集
else
temp_count <= temp_count + 1;
end if;
end if;
end if;
--本身频率是有误差的,25%的范围,以前没有考虑这个问题
if (reg_count >= "00001000") and (reg_count <= "00001100") then--250k(0.25的余量)
high_low <= "00";
elsif (reg_count >= "00010011") and (reg_count <= "00011111") then--100k(0.25的余量)
high_low <= "01";
elsif (reg_count >= "00100110") and (reg_count <= "00111110") then--48k(0.25的余量)
high_low <= "10";
elsif (reg_count >= "10010110") and (reg_count <= "11111010") then--12.5K(0.25的余量)
high_low <= "11";
else
high_low <= "10";
end if;
end process;
--12.5K 半周期40us 80*4 = 320us 40/0.2=200 1100 1000
-- 48K 半周期10us 20*4 = 80us 10/0.2=50 11 0010
-- 100K 半周期 5us 10*4 = 40us 5/0.2=25 1 1001
-- 250K 半周期 2us 4*4 = 16us 2/0.2=10 1010
process(clk10m)--分频产生采样周期 sampling_clk(2):1.25M(0.8us),
-- sampling_clk(3):0.625M(1.6us),
-- sampling_clk(4):0.3125M(3.2us),
-- sampling_clk(5):0.15625M(6.4us),
-- sampling_clk(6):0.078125M(12.8us),
begin
if rising_edge(clk10m) then
sampling_clk<=sampling_clk + 1;
end if;
end process;
process(sampling_clk,syn_clk,high_low,cs,reset,sampling_reg)--寻找间歇周期
variable i,j,k,l : natural range 0 to 9 := 0;--从0开始,不是1
begin
if (cs = '1') then--片选
if (reset = '1') then--非复位
if (high_low = "00") then--250k 2us 4*4 = 16us 2/0.2=10 1010
if syn_clk = '1' then--同步时钟过来立即进入非间隙周期
clearance <= '0';
i := 0;--不清零会重复启动,复位到初始状态
else--同步时钟为低电平时寻找间歇周期
if rising_edge(sampling_clk(2)) then--sampling_clk(2):1.25M(0.8us)
if i >= 6 then--因为在非间歇周期的低电平中根本到不了6,所有就没有赋值的过程
i := 0;
if sampling_reg = "0000000000" then
clearance <= '1';
end if;
else
sampling_reg(i)<=syn_clk;
i := i + 1;
end if;
end if;
end if;
elsif (high_low = "01") then--100k 5us 10*4 = 40us 5/0.2=25 1 1001
if syn_clk = '1' then
clearance <= '0';
j := 0;
else
if rising_edge(sampling_clk(3)) then--sampling_clk(3):0.625M(1.6us)
if j = 9 then
j := 0;
if sampling_reg = "0000000000" then
clearance <= '1';
end if;
else
sampling_reg(j)<=syn_clk;
j := j + 1;
end if;
end if;
end if;
elsif (high_low = "10") then--48k 10us 20*4 = 80us 10/0.2=50 11 0010
if syn_clk = '1' then
clearance <= '0';
k := 0;
else
if rising_edge(sampling_clk(4)) then--sampling_clk(4):0.3125M(3.2us)
if k = 9 then
k := 0;
if sampling_reg = "0000000000" then
clearance <= '1';
end if;
else
sampling_reg(k)<=syn_clk;
k := k + 1;
end if;
end if;
end if;
elsif (high_low = "11") then--12.5k 40us 80*4 = 320us 40/0.2=200 1100 1000
if syn_clk = '1' then
clearance <= '0';
l := 0;
else
if rising_edge(sampling_clk(6)) then--sampling_clk(6):0.078125M(12.8us)
if l = 9 then
l := 0;
if sampling_reg = "0000000000" then
clearance <= '1';
end if;
else
sampling_reg(l)<=syn_clk;
l := l + 1;
end if;
end if;
end if;
end if;
else--复位
sampling_reg <= "0000000000";
clearance <= '0';
i := 0;
j := 0;
k := 0;
l := 0;
end if;
else--非片选
sampling_reg <= "0000000000";
clearance <= '0';
i := 0;
j := 0;
k := 0;
l := 0;
end if;
end process;
--最大的半祯40us,5M 0.2us,40/0.2=200 1100 1000 count至少需8位才能 保证只读1次
process(cs,reset,clearance,clk5mc,syn_clk,reg_data)
variable m : natural range 0 to 31 := 0;
begin
if (cs = '1') then--片选
if (reset = '1') then--非复位
if clearance = '1' then--间歇周期
parallel_data <= reg_data;--输出数据到并口
m := 0;
else--非间歇周期
if syn_clk = '1' then--同步时钟过来
if rising_edge(clk5mc) then
count <= count + 1;--只要同步时钟是高电平就不停止计数
if count = "00000101" then--延时1us
reg_data(m) <= serial_data;--读取串行数据
m := m+1;
end if;
end if;
else
count <= "00000000";
end if;
end if;
else--复位
m := 0;
count <= "00000000";
reg_data <= "00000000000000000000000000000000";
end if;
else--非片选
m := 0;
count <= "00000000";
reg_data <= "00000000000000000000000000000000";
end if;
end process;
process(clk10ma,clearance,savecount)
begin
if clearance = '1' then
if rising_edge(clk10ma) then
if savecount = "11111110" then
savecount <= "11111110";
else
savecount <= savecount + 1;
end if;
end if;
else
savecount <= "00000000";
end if;
if savecount = "00101000" then
saveclk <= '1';
end if;
if savecount = "01111000" then
saveclk <= '0';
end if;
end process;
end a;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -