硬件语言Verilog HDL牛客刷题day10 华W部分 和 DJ部分
1. VL63 并串转换
1.题目:
设计一个模块进行并串转换,要求每四位d输为转到一位dout输出,输出valid_in表示此时的输入有效。
2.解题思路
2.1 计数记录输出的位数。
2.2 数据 有一个延时。
2.3 思路就是 搞一个寄存器存储数据,然后根据数据的位数来决定 计数的大小。
3.解题代码
`timescale 1ns/1ns
module huawei5(input wire clk ,input wire rst ,input wire [3:0]d ,output wire valid_in ,output wire dout);//*************code***********//
parameter s0 = 3'd0;
parameter s1 = 3'd1;
parameter s2 = 3'd2;
parameter s3 = 3'd3;
reg[3:0] cnt;
reg[3:0] data;
reg valid;assign dout = data[3];
assign valid_in = valid;always@(posedge clk or negedge rst)beginif(~rst)begincnt <=s0;valid <=0;data <=0;endelsebeginif(cnt == s3)begincnt <=s0;valid <=1;data <= d;endelsebegincnt <= cnt +1;valid<=0;data <= {data[2:0],data[3]};endendend//*************code***********//endmodule
2.VL64 时钟切换
1.题目:
存在两个同步的倍频时钟clk0 clk1,已知clk0是clk1的二倍频,现在要设计一个切换电路,sel选择时候进行切换,要求没有毛刺。
2.解题思路
2.1 两个同步的倍频时钟clk0 clk1,已知clk0是clk1的二倍频,属于相关时钟,避免切换时毛刺出现,只需要在组合逻辑的基础上添加下降沿触发的DFF。原理图如下: (专业知识无语)(新手小白我也不是懂,只能查资料)
链接:手撕代码2 | 无毛刺时钟切换 - 知乎 (zhihu.com)
2.2 我看这个题 需要自己看代码,了解一下。
2.3 这个问题是关于 时钟的变化。防止出现毛刺, 就是防止信号突然变换。
2.4 关于信号的突然变化 需要一个信号来决定是否现在输出 一个D 触发器来控制。
2.5 主要是D触发器 有时钟,可以决定 信号是1/0 ,还有多余的口来输出相反的信号。
3.解题代码
`timescale 1ns/1nsmodule huawei6(input wire clk0 ,input wire clk1 ,input wire rst ,input wire sel ,output wire clk_out
);reg q0, q1;always@(negedge clk0 or negedge rst)if(!rst)q0 <= 0;else q0 <= ~sel & ~q1;always@(negedge clk1 or negedge rst)if(!rst) q1 <= 0;else q1 <= sel & ~q0;assign clk_out = (q0 & clk0) | (q1 & clk1);endmodule
3.VL65 状态机与时钟分频
1.题目:
题目描述:
使用状态机实现时钟分频,要求对时钟进行四分频,占空比为0.25
2.解题思路
2.1 输出时序 1000
2.1 使用状态机
3.解题代码
`timescale 1ns/1nsmodule huawei7(input wire clk ,input wire rst ,output reg clk_out
);
parameter s0=2'd0;
parameter s1=2'd1;
parameter s2=2'd2;
parameter s3=2'd3;
reg[1:0]cnt;
//*************code***********//
always@(posedge clk or negedge rst)beginif(~rst)begincnt <=s0;endelsebegincase (cnt)s0 : cnt <=s1;s1 : cnt <=s2;s2 : cnt <=s3;s3 : cnt <=s0;endcaseendendalways@(posedge clk or negedge rst)beginif(~rst)beginclk_out <=0;endelsebegincase (cnt)s0 : clk_out <=1;default: clk_out <=0;endcaseendend//*************code***********//
endmodule
4.VL66 超前进位加法器
1.题目:
2.解题思路
2.1 暴力直接位和位 的对应相加。
2.2 采用模块化
3.解题代码
暴力方式
`timescale 1ns/1nsmodule huawei8//四位超前进位加法器
(input wire [3:0]A,input wire [3:0]B,output wire [4:0]OUT
);
wire[3:0] C;
//*************code***********//
assign OUT[0]=A[0]^B[0]^1'b0;
assign OUT[1]=A[1]^B[1]^C[0];
assign OUT[2]=A[2]^B[2]^C[1];
assign OUT[3]=A[3]^B[3]^C[2];
assign OUT[4]=C[3];
assign C[0]=A[0]&B[0]|(A[0]|B[0])&1'b0;
assign C[1]=A[1]&B[1]|(A[1]|B[1])&C[0];
assign C[2]=A[2]&B[2]|(A[2]|B[2])&C[1];
assign C[3]=A[3]&B[3]|(A[3]|B[3])&C[2];//*************code***********//
endmodule//下面是两个子模块module Add1 //计算 1 位数的C
(input a,input b,input C_in,output f,output g,output p);assign g = a & b; assign p = a | b;assign f = a ^ b ^ C_in;endmodulemodule CLA_4(input [3:0]P,input [3:0]G,input C_in,output [4:1]Ci,output Gm,output Pm);endmodule
模块化的方式
`timescale 1ns/1nsmodule huawei8//四位超前进位加法器
(input wire [3:0]A,input wire [3:0]B,output wire [4:0]OUT
);//*************code***********//wire [3:0] G,P,F;wire [4:1] C;Add1 inst0(.a (A[0]),.b (B[0]),.C_in (1'b0),.f (F[0]),.g (G[0]),.p (P[0]));genvar i;generate for(i=1;i<4;i=i+1) begin:Add1_instAdd1 inst(.a (A[i]),.b (B[i]),.C_in (C[i]),.f (F[i]),.g (G[i]),.p (P[i]));endendgenerateCLA_4 inst_cal(.P (P),.G (G),.C_in (1'b0),.Ci (C),.Gm (),.Pm ());assign OUT = {C[4],F};//*************code***********//
endmodule//下面是两个子模块module Add1
(input a,input b,input C_in,output f,output g,output p);assign g = a & b;assign p = a | b;assign f = a ^ b ^ C_in; //sumendmodulemodule CLA_4(input [3:0]P,input [3:0]G,input C_in,output [4:1]Ci,output Gm,output Pm);assign Ci[1] = G[0] | P[0] & C_in;assign Ci[2] = G[1] | P[1] & (G[0] | P[0] & C_in);assign Ci[3] = G[2] | P[2] & (G[1] | P[1] & (G[0] | P[0] & C_in));assign Ci[4] = G[3] | P[3] & (G[2] | P[2] & (G[1] | P[1] & (G[0] | P[0] & C_in)));assign Gm = G[3] | (P[3]&G[2]) | (P[3]&P[2]&G[1]) | (P[3]&P[2]&P[1]&G[0]);assign Pm = P[3]&P[2]&P[1]&P[0];endmodule
5.VL67 十六进制计数器
题目:
请用Verilog设计十六进制递增计数器电路,每个时钟周期递增1。
电路的接口如下图所示。Q[3:0]中,Q[3]是高位。
2. 解题代码
`timescale 1ns/1nsmodule counter_16(input clk ,input rst_n ,output reg [3:0] Q
);always@(posedge clk or negedge rst_n)beginif(~rst_n)beginQ <=0;endelsebeginif(Q == 4'd15)beginQ<=0;endelsebeginQ <= Q+1;endendendendmodule
6.VL70 序列检测器(Moore型)
1.题目:
请用Moore型状态机实现序列“1101”从左至右的不重叠检测。
电路的接口如下图所示。当检测到“1101”,Y输出一个时钟周期的高电平脉冲。
接口电路图如下:
2. 解题思路
2.1 主要是我们采用 状态机
2.2 注意一个 不重叠检测。 (当我们检测到不对时,直接重新开始)
2.3 注意 检测是连续的, 数据输出需要一个延时,不是当时满足直接输出。
3.解题代码
`timescale 1ns/1nsmodule det_moore(input clk ,input rst_n ,input din ,output reg Y
);
//状态机 (先设置状态)
parameter s0 = 5'b00000;
parameter s1 = 5'b00001;
parameter s2 = 5'b00011;
parameter s3 = 5'b00110;
parameter s4 = 5'b01101;
reg[4:0] flag;always@(posedge clk or negedge rst_n)beginif(~rst_n)beginflag <=s0;endelsebegincase (flag)s0 : flag <= din ? s1 : s0;s1 : flag <= din ? s2 : s0;s2 : flag <= din ? s0 : s3;s3 : flag <= din ? s4 : s0;s4 : flag <= din ? s1 : s0;endcaseendendalways@(posedge clk or negedge rst_n)beginif(~rst_n)beginY <=0;endelsebeginif(flag == s4)beginY <= 1;endelsebeginY <=0;endendendendmodule
7.VL71 乘法与位运算
1.题目:
进行一个运算单元的电路设计,A[7:0]*11111011,尽量用最少的资源实现,写出对应的 RTL 代码。
2. 解题思路
2.1 一个简单的 乘法运算, 9'd1000_0000_0 = 8'b1111_1011 + 3'b100 + 1'b1;
2.2 换算过来: 8'b1111_1011 = 9'd1000_0000_0 - 3'b100 - 1'b1;
2.2 再转换思维 数据* 8’b1111_1011 = 左移8位 - 左移 2位 - 数据*1;
3.解题代码
`timescale 1ns/1nsmodule dajiang13(input [7:0] A,output [15:0] B);
wire[15:0] A1;
//*************code***********//// 9'b1000_0000_0 = 3'b100 + 1'b1 + 8'b1111_1011
assign A1 = {8'b0000_0000,A};
assign B = (A1<<8) - (A1 <<2) -A1; //*************code***********//endmodule