✅作者简介:大家好我是:嵌入式基地,是一名嵌入式工程师,希望一起努力,一起进步!
📃个人主页:嵌入式基地
🔥系列专栏:FPGA Verilog 习题专栏
微信公众号:嵌入式基地
FPGA硬件工程师Verilog面试题(四)
习题一:根据状态转移表实现时序电路
描述
-
某同步时序电路转换表如下,请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。
-
电路的接口如下图所示
输入描述
- input A
- input clk
- input rst_n
输出描述
- output wire Y
代码实现
`timescale 1ns/1ns
module seq_circuit(
input A ,
input clk ,
input rst_n,
output wire Y
);
reg q0, q1;
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
q1 <= 0;
end
else begin
q1 <= A ^ q0 ^ q1;
end
end
always@(posedge clk or negedge rst_n) begin
if(~rst_n) begin
q0 <= 0;
end
else begin
q0 <= ~q0;
end
end
assign Y = q0 & q1;
endmodule
习题二:根据状态转移图实现时序电路
描述
- 某同步时序电路的状态转换图如下,→上表示“C/Y”,圆圈内为现态,→指向次态。
- 请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。
- 电路的接口如下图所示,C是单bit数据输入端。
输入描述
- input C
- input clk
- input rst_n
输出描述
- output wire Y
代码实现
`timescale 1ns/1ns
module seq_circuit(
input C ,
input clk ,
input rst_n,
output wire Y
);
parameter ST0 = 2'b00;
parameter ST1 = 2'b01;
parameter ST2 = 2'b10;
parameter ST3 = 2'b11;
reg[1:0] cur_state;
reg[1:0] next_state;
reg Y_r;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cur_state <= ST0;
else
cur_state <= next_state;
always@(*)
case (cur_state)
ST0: begin
if(C == 1'b0) begin
next_state = ST0;
end else begin
next_state = ST1;
end
end
ST1: begin
if(C == 1'b0) begin
next_state = ST3;
end else begin
next_state = ST1;
end
end
ST2: begin
if(C == 1'b0) begin
next_state = ST0;
end else begin
next_state = ST2;
end
end
ST3: begin
if(C == 1'b0) begin
next_state = ST3;
end else begin
next_state = ST2;
end
end
endcase
always@(*)
case (cur_state)
ST0: begin
Y_r = 1'b0;
end
ST1: begin
Y_r = 1'b0;
end
ST2: begin
if(C == 1'b1)
Y_r = 1'b1;
else
Y_r = 1'b0;
end
ST3: begin
Y_r = 1'b1;
end
endcase
assign Y = Y_r;
endmodule
习题三:ROM的简单实现
描述
- 实现一个深度为8,位宽为4bit的ROM,数据初始化为0,2,4,6,8,10,12,14。可以通过输入地址addr,输出相应的数据data。
- 接口信号图如下:
- 使用Verilog HDL实现以上功能并编写testbench验证。
输入描述
- clk:系统时钟
- rst_n:异步复位信号,低电平有效
- addr:8bit位宽的无符号数,输入到ROM的地址
输出描述
- data:4bit位宽的无符号数,从ROM中读出的数据
代码实现
`timescale 1ns/1ns
module rom(
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
);
reg [3:0] rom_data [7:0];
assign data = rom_data[addr];
//保持ROM中的数据不变
always @(posedge clk or negedge rst_n)
if (!rst_n)
begin
rom_data[0] <= 4'd0;
rom_data[1] <= 4'd2;
rom_data[2] <= 4'd4;
rom_data[3] <= 4'd6;
rom_data[4] <= 4'd8;
rom_data[5] <= 4'd10;
rom_data[6] <= 4'd12;
rom_data[7] <= 4'd14;
end
else
begin
rom_data[0] <= rom_data[0];
rom_data[1] <= rom_data[1];
rom_data[2] <= rom_data[2];
rom_data[3] <= rom_data[3];
rom_data[4] <= rom_data[4];
rom_data[5] <= rom_data[5];
rom_data[6] <= rom_data[6];
rom_data[7] <= rom_data[7];
end
endmodule
习题四:边沿检测
描述
-
有一个缓慢变化的1bit信号a,编写一个程序检测a信号的上升沿给出指示信号rise,当a信号出现下降沿时给出指示信号down。
-
注:rise,down应为单脉冲信号,在相应边沿出现时的下一个时钟为高,之后恢复到0,一直到再一次出现相应的边沿。
-
使用Verilog HDL实现以上功能并编写testbench验证。
输入描述
- clk:系统时钟信号
- rst_n:异步复位信号,低电平有效
- a:单比特信号,作为待检测的信号
输出描述
- rise:单比特信号,当输入信号a出现上升沿时为1,其余时刻为0
- down:单比特信号,当输入信号a出现下降沿时为1,其余时刻为0
代码实现
`timescale 1ns/1ns
module edge_detect(
input clk,
input rst_n,
input a,
output reg rise,
output reg down
);
reg a_tem;
//缓存a的数值
always @(posedge clk or negedge rst_n)
if (!rst_n)
a_tem <= 1'b0;
else
a_tem <= a;
//检测边沿,给出相应的信号
always @(posedge clk or negedge rst_n)
if (!rst_n)
begin
rise <= 1'b0;
down <= 1'b0;
end
else if (!a_tem && a) //当前一时刻a=0,当前时刻a=1,表示a出现一次上升沿
begin
rise <= 1'b1;
down <= 1'b0;
end
else if (a_tem && !a) //当前一时刻a=1,当前时刻a=0,表示a出现一次下降沿
begin
down <= 1'b1;
rise <= 1'b0;
end
else
begin
down <= 1'b0;
rise <= 1'b0;
end
endmodule