硬件语言Verilog HDL牛客刷题day03 时序逻辑部分
Posted _She001
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了硬件语言Verilog HDL牛客刷题day03 时序逻辑部分相关的知识,希望对你有一定的参考价值。
1.VL21 根据状态转移表实现时序电路
1.题目:
某同步时序电路转换表如下,请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。
2.解题思路
2.1 首先同步时序电路 , 时钟上升沿触发, 复位信号rst 低电平无效.
2.2 D 触发器 是一个看 A 输入的 触发器。
2.3 使用状态机。
3.解题代码
`timescale 1ns/1ns
module seq_circuit(
input A ,
input clk ,
input rst_n,
output wire Y
);
//根据表格 的要求我们知道,这个需要输出 Y Y与次态的 Q1,Q0 有关
reg q0,q1;
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
q1<=0;
else
begin
q1<= A ^ q0 ^ q1;
end
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
q0<= 0;
else
begin
q0 <= ~q0;
end
end
assign Y = q0 & q1;
endmodule
2.VL22 根据状态转移图实现时序电路
1.题目:
某同步时序电路的状态转换图如下,→上表示“C/Y”,圆圈内为现态,→指向次态。
请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。
2.解题思路
使用三段式
1)一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;
(2)二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;
(3)三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用 同步时序 描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。
3.解题感想
3.1 在硬件电路的时候, 次态和现态,不好表达, 但是总的来说,使用 always 能解决。
3.2 使用三段式 的时候 , 题目解决简单一些。
3.3 列出一个 固定值的变量 使用 parameter 定义。
4.解题代码
`timescale 1ns/1ns
module seq_circuit(
input wire clk ,
input wire rst_n,
input wire C ,
output reg Y
);
reg [1:0] state, next_state;
parameter ST0 = 2'd0;
parameter ST1 = 2'd1;
parameter ST2 = 2'd2;
parameter ST3 = 2'd3;
always@(posedge clk or negedge rst_n) begin
if (~rst_n)
state <= 2'd0;
else
state <= next_state;
end
always@(*) begin
case(state)
ST0: next_state = C ? ST1 : ST0;
ST1: next_state = C ? ST1 : ST3;
ST2: next_state = C ? ST2 : ST0;
ST3: next_state = C ? ST2 : ST3;
default: next_state = ST0;
endcase
end
always@(*) begin
if(((state == ST2) && C) || (state == ST3))
Y = 1'b1;
else
Y = 1'b0;
end
endmodule
3.VL23 ROM的简单实现
1.题目:
实现一个深度为8,位宽为4bit的ROM,数据初始化为0,2,4,6,8,10,12,14。可以通过输入地址addr,输出相应的数据data。
接口信号图如下:
2.解题思路
2.1 开辟一个 深度为 8 ,位宽为 4 bit 的数据寄存器。
2.2 向开辟的寄存器里面 存入数据。
2.3 调取这个寄存器的数据, 直接访问器地址。
3.解题感想
3.1 开辟一个 深度为8 位宽为 4 的寄存器的 方法是 前面是 宽度,后面是深度。
例如: reg[3:0] L[7:0]; //深度为8 ,位宽为4 .
4.解题代码
`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];
always@(posedge clk or negedge rst_n)
begin
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
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
assign data = ROM_DATA[addr];
endmodule
4.VL24 边沿检测
1.题目:
有一个缓慢变化的1bit信号a,编写一个程序检测a信号的上升沿给出指示信号rise,当a信号出现下降沿时给出指示信号down。
注:rise,down应为单脉冲信号,在相应边沿出现时的下一个时钟为高,之后恢复到0,一直到再一次出现相应的边沿。
2.解题思路
2.1 首先是一个 次态 和 现态的问题 ,
2.2 两个 always 分别控制 次态的赋值, 和 次态和现态的对比来输出 rise 和 down 的值.
3. 解题感想
3.1 使用 if else 嵌套 if else 要使模块专一化, 就是每个部分使用 隔断语句区分 (begin end) ( 并行语句) 。
4. 解题代码
`timescale 1ns/1ns
module edge_detect(
input clk,
input rst_n,
input a,
output reg rise,
output reg down
);
reg a1;
//首先搞定a
always@(posedge clk or negedge rst_n)//建立一个寄存器保存上一个时态的信号
begin
if(~rst_n)
a1 <= 0;
else
a1 <= a;
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
rise <= 0;
down <= 0;
end
else
begin
if(a & ~a1)//上一时态为 低电平, 现态为 高点品
begin
rise <=1'b1;
down <=1'b0;
end
else if(~a & a1) //次态为 高点品 , 现态 为 低电平
begin
rise <=0;
down <=1;
end
else
begin
rise <=0;
down <=0;
end
end
end
endmodule
以上是关于硬件语言Verilog HDL牛客刷题day03 时序逻辑部分的主要内容,如果未能解决你的问题,请参考以下文章