> 文章列表 > 硬件语言Verilog HDL牛客刷题day10 华W部分 和 DJ部分

硬件语言Verilog HDL牛客刷题day10 华W部分 和 DJ部分

硬件语言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