FSM Design T2
设计一个脉冲产生电路,当输入信号IN出现正向跳变沿时,输出一个脉冲,该脉冲为持续一个时钟周期的高电平信号。主要波形图如下所示。用Verilog完成设计。(输入信号至少包含reset和clock)注:输出信号名为PULSE,请同学们按照此命名编写Verilog代码。
1. Analysis
根据题中要求需要设计一个边沿检测电路,即:输入信号IN出现正向跳变时,输出信号PLUSE产生一个高电平信号(持续1个时钟周期)。因此,本文需要设置两个reg类型的一位寄存器变量(IN_STATE_0、IN_STATE_1),以保存输入信号IN在当前CLK上升沿、上一个CLK上升沿的电平状态,这代表着实际电路中会存在2个异步复位的D触发器。然后,本文根据这两个寄存器变量保存的输入信号IN的电平,即可判断出输入信号IN是否发生过跳变。
2. Circuit Diagram
3. Port List
Port Name | Attribute | Width | Meaning |
---|---|---|---|
clock | input | 1 bit | 时钟信号 |
reset | input | 1 bit | 复位信号 |
in | input | 1 bit | 输入信号IN |
pluse | output | 1 bit | 脉冲信号PLUSE |
4. Verilog Code
`timescale 1ns/1ps
module exercise2 (CLK, RST, IN, PLUSE);
input wire CLK;
input wire RST;
input wire IN;
output wire PLUSE;
reg in_state_0;
reg in_state_1;
always @ (posedge CLK or negedge RST) begin
if (!RST) begin
in_state_0 <= 1'b0;
in_state_1 <= 1'b0;
end
else begin
in_state_0 <= IN;
in_state_1 <= in_state_0;
end
end
assign PLUSE = in_state_0 & (~ in_state_1);
endmodule
5. Testbench Code
`timescale 1ns/1ps
module exercise2_test_1;
reg RST;
reg CLK;
reg IN;
wire PLUSE;
parameter half_cycle = 5;
exercise2 exercise2_inst (
.CLK(CLK),
.RST(RST),
.IN(IN),
.PLUSE(PLUSE)
);
initial begin
CLK = 0;
forever begin
CLK = # half_cycle ~ CLK;
end
end
initial begin
RST = 1;
# (1 * half_cycle) RST = 0;
# (2 * half_cycle) RST = 1;
end
initial begin
IN = 0;
# (3 * half_cycle) IN = 1;
# (4 * half_cycle) IN = 1;
# (5 * half_cycle) IN = 0;
# (6 * half_cycle) IN = 1;
end
initial begin
# (50 * half_cycle) $finish;
end
initial begin
$fsdbDumpfile("./verdiFsdb/exercise2.fsdb");
$fsdbDumpvars(0);
end
endmodule
`timescale 1ns/1ps
module exercise2_test_2;
reg RST;
reg CLK;
reg IN;
wire PLUSE;
parameter half_cycle = 5;
exercise2 exercise2_inst (
.CLK(CLK),
.RST(RST),
.IN(IN),
.PLUSE(PLUSE)
);
initial begin
CLK = 0;
forever begin
CLK = # half_cycle ~ CLK;
end
end
initial begin
RST = 1;
# (1 * half_cycle) RST = 0;
# (2 * half_cycle) RST = 1;
end
initial begin
IN = 0;
# (5 * half_cycle) IN = 1;
# (6 * half_cycle) IN = 0;
# (7 * half_cycle) IN = 1;
# (8 * half_cycle) IN = 0;
end
initial begin
# (50 * half_cycle) $finish;
end
initial begin
$fsdbDumpfile("./verdiFsdb/exercise2.fsdb");
$fsdbDumpvars(0);
end
endmodule