虫后:发光信息 f0(正常时是 30%占空比的毫秒脉冲,繁殖季为占空比为50%,年老时占空比逐渐减小,周期逐渐增大,直至死亡)。
信虫:发光信息 f1 与虫后的 f0 同频同相,并且自动调整发光脉冲宽度为 0.4 毫秒。
哨虫:哨虫看到信虫的信号会同步反馈一个防卫信号,如果安全(sta==0),防卫信号是一个与 f1 同相的双脉冲信号 f2a(脉冲宽度 0.1 毫秒);当敌人来犯(sta==1),防卫信号是三脉冲信号 f2b(脉冲宽度 0.1 毫秒)。
哨虫离开边界地区(p=0表示不在边界地区,p=1表示在边界地区)会自动变换职责为信虫。
要求:
1、f0 的频率范围是 0.5kHz~1.2kHz,占空比 1%~40%,实验时由信号发生器产生。
2、 信虫电路的输入是 f0,输出是 f1,电路内部有 6MHz 的高精度时钟源。
3.、哨虫电路的输入是 f1 和 p,以及 sta(状态信息,0 表示安全,1 表示敌人来犯),输出是 f2。
一、实验分析与设计
有输入信号:母虫f0,是否离开边界p,边界是否安全sta。 输出信号:信虫f1,哨虫f2。
母虫的发光信息f0由外部信号发生器产生,此处不进行处理。
信虫f1与母虫f0同向同频,可以通过检测f0的上升沿使f1同频同相;而f1的发光脉冲宽度0.4ms,可以通过6MHz的时钟来进行计时。
哨虫f2需要先通过外部信号p,判断是否离开边界,如果离开边界,则f2与f1相同;为离开边界,则继续通过外部信号sta,判断边界是否安全,如果安全,f2为与f1同相的双脉冲信号(脉冲宽度0.1ms);不安全,则为三脉冲信号(脉冲宽度0.1ms)。通过检测f0的上升沿达到同相,通过6MHz的时钟来进行计时。
二、程序代码
采用层次化设计,将f1与f2分模块实现。
顶层文件
module Test(CLK,f0,p,sta,f1,f2);
input CLK; //6MHZ输入
input f0; //虫后信息,信号发生器产生
input p; //信虫、哨虫模式转换
input sta; //边界安全转换
output f1; //信虫信息
output f2; //哨虫信息
Test_1 t1(CLK,f0,f1); //信虫
Test_2 t2(CLK,f0,p,sta,f2); //哨虫
endmodule
信虫f1
module Test_1(CLK,f0,f1); //f1信虫
input CLK; //6MHZ输入
input f0; //虫后信息,信号发生器产生
output reg f1 = 1'b0;//信虫
parameter X4 = 2400; //6MHz生成0.4ms的计数次数,信虫
integer k = 1; //计数
reg posf0 = 1'b0; //检测f0上升沿,作为计时器开关
reg temp = 1'b0; //f0上一状态
always@(posedge CLK)
begin
if(!temp & f0) posf0 <= 1'b1; //f0上升沿
if(posf0) //开始计时0.4ms
begin
if(k <= X4) //小于2400
begin
f1 <= 1'b1; //输出为1
k <= k + 1; //计数加一
end
else //计时结束
begin
posf0 <= 1'b0; //结束计时
k <= 1; //重置计数器为1
f1 <= 1'b0; //输出为0
end
end
temp <= f0; //f0上一状态
end
endmodule
哨虫f2
module Test_2(CLK,f0,p,sta,f2); //f2哨虫
input CLK,f0,p,sta;
output reg f2 = 1'b0; //哨虫信息
parameter S1 = 600; //6MHz生成0.1ms计时次数,哨虫
parameter X4 = 2400;//6MHz生成0.4ms计时次数,信虫
integer k = 1; //计数
reg posf0 = 1'b0; //检测f0上升沿,作为计时器开关
reg temp = 1'b0; //f0上一状态
always@(posedge CLK)
begin
if(!temp & f0) posf0 <= 1'b1; //f0上升沿
if(!p) //信虫
begin
if(posf0) //开始计时0.4ms
begin
if(k <= X4) //小于2400
begin
f2 <= 1'b1; //输出为1
k <= k + 1; //计数加一
end
else //计时结束
begin
posf0 <= 1'b0; //结束计时
f2 <= 1'b0; //输出为0
k <= 1; //重置计数器为1
end
end
end
if(p & !sta) //哨虫 边界安全
begin
if(posf0) //开始计时高-低-高
begin
if(k <= S1) //第一次高电平
begin
f2 <= 1'b1; //输出为1
k <= k + 1;
end
else if(k <= 2*S1)//第一次低电平
begin
f2 <= 1'b0; //输出为0
k <= k + 1;
end
else if(k <= 3*S1)//第二次高电平
begin
f2 <= 1'b1; //输出为1
k <= k + 1;
end
else //计时结束
begin
posf0 <= 1'b0; //结束计时
f2 <= 1'b0; //输出为0
k <= 1;
end
end
end
if(p & sta) //哨虫 边界危险
begin
if(posf0) //开始计时高-低-高-低-高
begin
if(k <= S1) //第一次高电平
begin
f2 <= 1'b1; //输出为1
k <= k + 1;
end
else if(k <= 2*S1)//第一次低电平
begin
f2 <= 1'b0; //输出为0
k <= k + 1;
end
else if(k <= 3*S1)//第二次高电平
begin
f2 <= 1'b1; //输出为1
k <= k + 1;
end
else if(k <= 4*S1)//第二次低电平
begin
f2 <= 1'b0; //输出为0
k <= k + 1;
end
else if(k <= 5*S1)//第三次高电平
begin
f2 <= 1'b1; //输出为1
k <= k + 1;
end
else //计时结束
begin
posf0 <= 1'b0; //结束计时
f2 <= 1'b0; //输出为0
k <= 1;
end
end
end
temp <= f0; //f0上一状态
end
endmodule
三、ModelSim仿真
1、Test Bench文件
`timescale 1 ns/ 1 ns
module Test_vlg_tst();
reg CLK;
reg f0;
reg p;
reg sta;
wire f1;
wire f2;
Test i1 (
.CLK(CLK),
.f0(f0),
.f1(f1),
.f2(f2),
.p(p),
.sta(sta)
);
initial
begin
CLK = 0;
f0 = 0;
p = 0;
sta = 0;
#6000000 //转变职能为哨虫
p = 1;
#6000000 //边界不安全
sta = 1;
$display("Running testbench");
end
always #83 CLK = ~CLK; //CLK 6MHz
always //母虫f0输入
begin
f0 = 0;#250000
f0 = 1;#500000 //50
f0 = 0;#250000
f0 = 0;#300000
f0 = 1;#400000 //40
f0 = 0;#300000
f0 = 0;#350000
f0 = 1;#300000 //30
f0 = 0;#350000
f0 = 0;#400000
f0 = 1;#200000 //20
f0 = 0;#400000
f0 = 0;#450000
f0 = 1;#100000 //10
f0 = 0;#450000
f0 = 0;#475000
f0 = 1;#50000 //5
f0 = 0;#475000
f0 = 0;
end
endmodule
2、波形图
注:详细操作可查看本专栏其他文章。