高手看过来:简易鉴相器问题(附代码)
我编译后QII报错,各位看看
原作者——yayapei
其原代码见下:
module top_jianxiang(reference_frq, local_frq, pf_up, pf_down );
input reference_frq;
input local_frq;
output pf_up;
output pf_down ;
reg pf_up,pf_down;
always @(posedge reference_frq or posedge local_frq)
begin
if (local_frq == 0) // reference_frq的上升沿先到
pf_down <= 1;
else
if (local_frq == 1) // local_frq的上升沿先到
pf_down <= 0;
end
always @(posedge reference_frq or posedge local_frq)
begin
if (reference_frq == 0)
pf_up <= 1;
else
if (reference_frq == 1)
pf_up <= 0;
end
endmodule
在用Quartus II编译时报错:“Error (10200): Verilog HDL Conditional Statement error at top_jianxiang.v(11): cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct”
很明显这是指代码中always部分有问题,将local_frq要求为上升沿启动always导致了错误!但小弟却担心改动此处将造成一发而动全身的结果,望高手支招!
posedge 加 ==0 ? 你觉得合适吗?
谢谢回复。关于这一点我注意到的。问题在于就是要对上升沿进行判别啊。
2楼的正解
谢谢回复。下面是我改写的VHDL代码,但仍有一些bug,小弟贴出来,就算是抛砖引玉一下,望各位路过高手支招。
说明: puls1(本地估算时钟)和puls2(输入信号)是两个周期相同但相位不同的方波。pf_up、ps_down用于向其他模块输出超前或滞后信号。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity phase_detect is
port( reset :in std_logic;
clk :in std_logic;
puls1 :in std_logic;
puls2 :in std_logic;
pf_up : out std_logic; --pf_up表示puls1 比puls2超前
pf_down : out std_logic; --pf_down表示puls1 比puls2滞后
cnt : out std_logic_vector(3 downto 0) --超前或滞后的计数值输出
);
end phase_detect;
architecture behav of phase_detect is
signal cnt_start :std_logic; --开始计数标志
signal cnt1:std_logic_vector(3 downto 0); --计数器
signal puls :std_logic;
begin
puls<=puls1 or puls2; --用于检测puls1或者puls2的上跳沿
P1:process(puls,puls1,puls2)
begin
if puls='1' then --出现上跳沿,则置cnt_start标志位
cnt_start<='1';
end if;
if (puls1 and puls2)='1' then --当puls1和puls2同时出现时,清除标志位
cnt_start<='0';
end if;
end process;
P2:process(reset,clk)
begin
if reset='0' then
cnt1<="0000";
pf_up<='0';
pf_down<='0';
elsif clk'event and clk='1' then
if cnt_start='1' then
if puls1='1' and puls2='0' then --当puls1脉冲先到的时候
if cnt1>="0011" then --如果相位误差大于3个时钟,pf_up有输出
pf_up<='1';
cnt1<="0000";
else
cnt1<=cnt1+1;
end if;
elsif puls1='0' and puls2='1' then --当puls2脉冲先到的时候
if cnt1>="0011" then --如果相位误差大于3个时钟,pf_down有输出
pf_down<='1';
cnt1<="0000";
else
cnt1<=cnt1+1;
end if;
end if;
else
cnt1<="0000";
end if;
end if;
end process;
cnt<=cnt1;
end behav;
从下面仿真图可见,在puls1比puls2先到的情形下,cnt1的确能进行相位误差计数。但是,在两条红线之间,cnt1仍在计数!这不是我所需要的。产生的原因在于上面代码中的红色语句部分。但我暂时不愿去修改了,以免牵一发而动全身!

第一个代码是个初学者,只知HDL,不知电路的人,第二个代码没看.
好了,终于把图弄上来了。大家看看吧
别沉了
cnt_start这个信号是用来控制计数的吧?但是根本没用上。
还有程序写的太乱。建议用case。
第一个进程中关于上升沿的到来,以及cnt_star的判断的确有可以改进的地方。但代码的总体结构不算太乱吧。
再顶上去!
顶上去,在线等
从你的程序看。仿真结果非常符合。
13# wycawyc
我的仿真结果当然体现了代码中存在的问题。可我想让puls1和puls2同时为高电平时,使计数器停止计数!关键是如何改进?兄弟有没有好的建议。
if puls = '1' then 并不是描述上升沿。而是描述高电平。改成 if puls'event and puls = '1' 就行了。你可以单独综合一下这段。看看rtl结构的区别。
15# wycawyc
呵呵,我不想弄成多时钟,怕造成其他麻烦。
不能沉了
我觉得还是用高速时钟来驱动这个计数条件。否则就要在判断条件里加入cnt_start的状态判断。会形成锁存。另外如果相位刚好180度的情况要特别考虑。
18# wycawyc 兄弟能否给出个示范代码?
从你的图形看应该已经有了180度相差判断的限制。给你想个简单的办法吧。加个限制。在计数使能一次以后。在7个时钟内禁止再次打开使能。
20# wycawyc
是有180°的相差限制。但我认为最好不要再增加一个计数器来控制使能,这样会使代码显得太过于“数学化”。个人倾向于还是从“两个脉冲先后到来”——这个关键特征来寻找突破口并改进代码。哥们,能留下个QQ吗
顶上去
顶上去
顶上去
一个多月了,还见到它,激动呀
