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)
begin
if(~rst)
begin
cnt <=s0;
valid <=0;
data <=0;
end
else
begin
if(cnt == s3)
begin
cnt <=s0;
valid <=1;
data <= d;
end
else
begin
cnt <= cnt +1;
valid<=0;
data <= {data[2:0],data[3]};
end
end
end
//*************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/1ns
module 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/1ns
module 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)
begin
if(~rst)
begin
cnt <=s0;
end
else
begin
case (cnt)
s0 : cnt <=s1;
s1 : cnt <=s2;
s2 : cnt <=s3;
s3 : cnt <=s0;
endcase
end
end
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
clk_out <=0;
end
else
begin
case (cnt)
s0 : clk_out <=1;
default: clk_out <=0;
endcase
end
end
//*************code***********//
endmodule
4.VL66 超前进位加法器
1.题目:
2.解题思路
2.1 暴力直接位和位 的对应相加。
2.2 采用模块化
3.解题代码
暴力方式
`timescale 1ns/1ns
module 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;
endmodule
module CLA_4(
input [3:0]P,
input [3:0]G,
input C_in,
output [4:1]Ci,
output Gm,
output Pm
);
endmodule
模块化的方式
`timescale 1ns/1ns
module 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_inst
Add1 inst(
.a (A[i]),
.b (B[i]),
.C_in (C[i]),
.f (F[i]),
.g (G[i]),
.p (P[i])
);
end
endgenerate
CLA_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; //sum
endmodule
module 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/1ns
module counter_16(
input clk ,
input rst_n ,
output reg [3:0] Q
);
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
Q <=0;
end
else
begin
if(Q == 4'd15)
begin
Q<=0;
end
else
begin
Q <= Q+1;
end
end
end
endmodule
6.VL70 序列检测器(Moore型)
1.题目:
请用Moore型状态机实现序列“1101”从左至右的不重叠检测。
电路的接口如下图所示。当检测到“1101”,Y输出一个时钟周期的高电平脉冲。
接口电路图如下:
2. 解题思路
2.1 主要是我们采用 状态机
2.2 注意一个 不重叠检测。 (当我们检测到不对时,直接重新开始)
2.3 注意 检测是连续的, 数据输出需要一个延时,不是当时满足直接输出。
3.解题代码
`timescale 1ns/1ns
module 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)
begin
if(~rst_n)
begin
flag <=s0;
end
else
begin
case (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;
endcase
end
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
Y <=0;
end
else
begin
if(flag == s4)
begin
Y <= 1;
end
else
begin
Y <=0;
end
end
end
endmodule
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/1ns
module 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