牛客 Verilog 刷题入门篇1~24 + 进阶篇1~34 题解代码,所有代码均能通过测试,配合视频讲解效果更佳。为避免内容冗余,本文只给出代码,部分题目给出必要说明。
很多题目本身出题有些问题,着重理解题目,没必要钻牛角尖。
本文作者:FPGA探索者

目录
文章目录
-
- 视频讲解合集
- 入门篇1~24题
-
- VL1 四选一多路器
- VL2 异步复位的串联T触发器
- VL3 奇偶校验(实际上应该是奇偶检测)
- VL4 移位运算与乘法
- VL5 位拆分与运算
- VL6 多功能数据处理器
- VL7 求两个数的差值
- VL8 使用generate...for语句简化代码
- VL9 使用子模块实现三输入数的大小比较
- VL10 使用函数实现数据大小端转换
- VL11 4位数值比较器电路
- VL12 4bit超前进位加法器电路
- VL13 优先编码器电路1
- VL14 用优先编码器1实现键盘编码电路
- VL15 优先编码器2——8线-3线优先编码器
- VL16 使用8线-3线优先编码器实现16线-4线优先编码器
- VL17~20 不建议做
- VL21 根据状态转移表实现时序电路
- VL22 使用状态转移图实现时序电路
- VL23 ROM的简单实现
- VL24 边沿检测
- 进阶篇1~34题
-
- VL1 输入序列连续的序列检测
- VL2 还有无关项的序列检测
- VL3 不重叠序列检测
- VL4 输入序列不连续的序列检测
- VL5 信号发生器
- VL6 数据串转并电路
- VL7 数据累加输出
- VL8 非整数倍数据位宽转换24to128
- VL9 非整数倍数据位宽转换8to12
- VL10 整数倍数据位宽转换8to16
- VL11 非重叠的序列检测
- VL12 重叠序列检测
- VL13 时钟分频(偶数)
- VL14 自动贩售机1
- VL15 自动贩售机2
- VL16 占空比50%的奇数分频
- VL17 任意小数分频
- VL18 无占空比要求的奇数分频
- VL19 根据状态转移写状态机-三段式
- VL20 根据状态转移写状态机-两段式
- VL21 异步FIFO
- VL22 同步FIFO
- VL23 格雷码计数器
- VL24 多bit MUX同步器
- VL25 脉冲同步电路
- VL26 简易秒表
- VL27 可置位计数器
- VL28 加减计数器
- VL29 单端口RAM
- VL30 RAM的简单实现
- VL31 Johnson Counter 约翰逊计数器
- VL32 流水线乘法器
- VL33 交通灯
- VL34 游戏机计费程序
- 结束
视频讲解合集
FPGA数字IC刷题Verilog讲解
https://space.bilibili.com/507257163/channel/collectiondetail?sid=260755

刷题链接点击转到
https://www.nowcoder.com/exam/oj?tab=Verilog%E7%AF%87&topicId=302&fromPut=pc_zh_s_1540795715

入门篇1~24题
VL1 四选一多路器
讲解视频:FPGA数字IC牛客Verilog刷题01-四选一多路器
解法一 三目运算符
使用assign连续赋值语句 + 三目运算符 ? :
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module mux4_1(
input [1:0]d1,d2,d3,d0,
input [1:0]sel,
output [1:0]mux_out
);
//*************code***********//
assign mux_out = (sel == 2'b00) ? d3 : ((sel == 2'b01) ? d2 : (sel == 2'b10) ? d1 : d0);
//*************code***********//
endmodule
解法二 case语句
使用always过程赋值语句 + case语句
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module mux4_1(
input [1:0]d1,d2,d3,d0,
input [1:0]sel,
output [1:0]mux_out
);
//*************code***********//
reg [1:0] mux_out_reg;
always @ (*)
begin
case(sel)
2'b00:mux_out_reg = d3;
2'b01:mux_out_reg = d2;
2'b10:mux_out_reg = d1;
2'b11:mux_out_reg = d0;
default : mux_out_reg = d0;
endcase
end
assign mux_out = mux_out_reg;
//*************code***********//
endmodule
三目运算符?:
d = c ? a : b;
其中,a、b、c均可以是表达式也可以是变量等,等效于if…else语句。if…else只能在always语句描述中使用,所以有时候为了在描述组合逻辑时,一般就用?:来实现这种条件判断效果。

case语句
case(表达式)
条件分支1: xxx;
条件分支2: xxx;
...
条件分支n: xxx;
缺省default: xxx;
endcase
case的使用注意点:
(1)要在always块里使用,如果是用always块描述组合逻辑,注意括号里的敏感变量列表都是电平触发,并且赋值时都要用阻塞赋值“=”;
(2)always块里的变量必须声明成reg类型,当然声明成reg类型不代表一定会综合成寄存器,只是语法要求always块里要这样;
(3)always块描述组合逻辑时,用*可以代表所有always块内敏感信号;
(4)分支条件要写全,最好补齐default缺省条件,不然在组合逻辑中可能会由于条件不全导致出现锁存器Latch;
VL2 异步复位的串联T触发器
注意 T 触发器的概念,来 1 翻转,来 0 保持。
注意理解同步复位和异步复位。
联发科数字IC简答题(9)——异步复位同步释放问题
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module Tff_2 (
input wire data, clk, rst,
output reg q
);
// 1. 复位
//2. T触发器,D触发器
//*************code***********//
reg q1;
always @ (posedge clk or negedge rst)
begin
if(!rst) begin
q1 <= 1'b0;
end
else begin
if( data )
q1 <= ~q1;
else
q1 <= q1;
end
end
always @ (posedge clk or negedge rst)
begin
if(!rst) begin
q <= 1'b0;
end
else begin
if( q1 )
q <= ~q;
else
q <= q;
end
end
//*************code***********//
endmodule
VL3 奇偶校验(实际上应该是奇偶检测)
实际上这里做的是奇偶检测,如果是奇数个 1 则结果为 1,使用单目运算符 ^ 即可。
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module odd_sel(
input [31:0] bus,
input sel,
output check
);
//*************code***********//
wire check_tmp;
// 单目运算符
assign check_tmp = ^bus;
// assign check = (sel == 1'b1) ? check_tmp : ~check_tmp;
reg check_reg;
always @ (*) begin
if(sel) begin
check_reg = check_tmp;
end
else begin
check_reg = ~check_tmp;
end
end
assign check = check_reg;
//*************code***********//
endmodule


VL4 移位运算与乘法
FSM 有限状态机思想,计数值就是状态。
注意在第一次获得数据的时候进行暂存。
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module multi_sel(
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
);
//*************code***********//
reg [1:0] count; // 0 1 2 3
always @ (posedge clk or negedge rst)
begin
if(~rst) begin
count <= 2'b0;
end
else begin
count <= count + 1'b1;
end
end
// FSM 有限状态机思想,计数值就是状态
reg [7:0] d_reg;
always @ (posedge clk or negedge rst)
begin
if(~rst) begin
out <= 11'b0;
input_grant <= 1'b0;
d_reg <= 8'b0;
end
else begin
case( count )
2'b00 : begin
out <= d;
d_reg <= d;
input_grant <= 1'b1;
end
2'b01 : begin
out <= d_reg + {d_reg, 1'b0}; // *1 + *2
input_grant <= 1'b0;
end
2'b10 : begin
out <= d_reg + {d_reg, 1'b0} + {d_reg, 2'b0};
input_grant <= 1'b0;
end
2'b11 : begin
out <= {d_reg, 3'b0};
input_grant <= 1'b0;
end
default : begin
out <= d;
input_grant <= 1'b0;
end
endcase
end
end
//*************code***********//
endmodule



VL5 位拆分与运算
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,
output [4:0]out, // wire
output validout // wire
);
//*************code***********//
reg [15:0] d_reg;
wire [3:0] d0;
wire [3:0] d1;
wire [3:0] d2;
wire [3:0] d3;
assign d0 = d_reg[3:0];
assign d1 = d_reg[7:4];
assign d2 = d_reg[11:8];
assign d3 = d_reg[15:12];
reg [4:0] out_reg;
reg validout_reg;
always @ (posedge clk or negedge rst)
begin
if( ~rst ) begin
out_reg <= 5'b0;
validout_reg <= 1'b0;
d_reg <= 16'b0;
end
else begin
case( sel )
2'b00 : begin
d_reg <= d;
out_reg <= 5'b0;
validout_reg <= 1'b0;
end
2'b01 : begin
d_reg <= d_reg;
out_reg <= d_reg[3:0] + d_reg[7:4];// d0 + d1;
validout_reg <= 1'b1;
end
2'b10 : begin
d_reg <= d_reg;
out_reg <= d0 + d2;
validout_reg <= 1'b1;
end
2'b11 : begin
d_reg <= d_reg;
out_reg <= d0 + d3;
validout_reg <= 1'b1;
end
default : begin
out_reg <= 5'b0;
validout_reg <= 1'b0;
end
endcase
end
end
assign out = out_reg;
assign validout = validout_reg;
//*************code***********//
endmodule
VL6 多功能数据处理器
讲解视频:06-多功能数据处理器
题解 | Verilog刷题解析及对应笔试面试注意点【6-9】(涉及==和===、for展开问题等)
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module data_select(
input clk,
input rst_n,
input signed[7:0]a,
input signed[7:0]b,
input [1:0]select,
output reg signed [8:0]c
);
always @ (posedge clk or negedge rst_n)
begin
if( ~rst_n ) begin
c <= 9'b0;
end
else begin
case ( select )
2'b00 : begin
c <= {a[7], a};
end
2'b01 : begin
c <= {b[7], b};
end
2'b10 : begin
c <= {a[7], a} + {b[7], b};
end
2'b11 : begin
c <= {a[7], a} - {b[7], b};
end
default : begin
c <= 9'b0;
end
endcase
end
end
endmodule
VL7 求两个数的差值
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module data_minus(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
output reg [8:0]c
);
always @ (posedge clk or negedge rst_n)
begin
if( ~rst_n ) begin
c <= 8'b0;
end
else begin
if( a > b ) begin
c <= a - b;
end
else begin
c <= b - a;
end
end
end
endmodule
VL8 使用generate…for语句简化代码
分别给出generate…for和for的代码,可以对比不同点。
使用generate…for
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module gen_for_module(
input [7:0] data_in,
output [7:0] data_out
);
// 1. 必须使用 genvar 声明循环变量
// begin后面必须起个名字
genvar ii;
generate for(ii = 0; ii < 8; ii = ii+1)
begin : aaa_i
assign data_out[ii] = data_in[7-ii];
end
endgenerate
endmodule
使用for
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module gen_for_module(
input [7:0] data_in,
output [7:0] data_out
);
// 2. for
integer i;
reg [7:0] dout_reg;
always @ (*) begin
for(i = 0; i < 8; i = i+1) begin
dout_reg[i] = data_in[7-i];
end
end
assign data_out = dout_reg;
endmodule
VL9 使用子模块实现三输入数的大小比较
解法一 使用时序逻辑子模块
需要调用3个模块,这里很多同学可能疑惑为什么用3个而不是2个。
第一个模块:比较 T 时刻的 a 和 b,T+1 时刻出来 tmp1;
第二个模块:比较 T 时刻的 a 和 c,T+1 时刻出来 tmp2;
第三个模块:比较 T+1 时刻的 tmp1 和 tmp2,T+2 时刻出来 d;
如果只用2个子模块,那么 T 时刻比较 a 和 b 得到 tmp1,再比较 tmp1 和 c 的时候是 T+1 时刻的 c 和 T+1 时刻的 tmp1,而 tmp1 代表的是 T 时刻 a 和 b 的较小值,所以这时候比较的 T 时刻的 a、b 和 T+1 时刻的 c,显然不符合要求。
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module main_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
input [7:0]c,
output [7:0]d
);
// T 时刻的 a 和 b,T+1 时刻出来 tmp1
wire [7:0] tmp1; // a b 的最小值
child_mod U0(
.clk ( clk ),
.rst_n ( rst_n ),
.a ( a ),
.b ( b ),
.d ( tmp1 )
);
// T 时刻的 a 和 c,T+1 时刻出来 tmp2
wire [7:0] tmp2; // a c 的最小值
child_mod U1(
.clk ( clk ),
.rst_n ( rst_n ),
.a ( a ),
.b ( c ),
.d ( tmp2 )
);
// T+1 时刻的 tmp1 和 tmp2,T+2 时刻出来 d
child_mod U2(
.clk ( clk ),
.rst_n ( rst_n ),
.a ( tmp1 ),
.b ( tmp2 ),
.d ( d )
);
endmodule
// 子模块
module child_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
output [7:0]d
);
reg [7:0] d_reg;
always @ (posedge clk or negedge rst_n)
begin
if( ~rst_n ) begin
d_reg <= 8'b0;
end
else begin
if( a > b )
d_reg <= b;
else
d_reg <= a;
end
end
assign d = d_reg;
endmodule
解法二 使用组合逻辑子模块,需要打两拍
组合逻辑的子模块,就不存在时序逻辑中的延时问题,所以调用的时候用2个子模块就可以完成3个数的比较,为了符合时序波形的要求,多打一拍。
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module main_mod(
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
input [7:0]c,
output [7:0]d
);
wire [7:0] tmp1; // a b 的最小值
child_mod U0(
.a ( a ),
.b ( b ),
.d ( tmp1 )
);
wire [7:0] tmp2; // a c 的最小值
child_mod U1(
.a ( tmp1 ),
.b ( c ),
.d ( tmp2 )
);
reg [7:0] d_reg;
reg [7:0] d_reg2;
always @ (posedge clk or negedge rst_n)
begin
if( ~rst_n ) begin
d_reg <= 8'b0;
d_reg2 <= 8'b0;
end
else begin
d_reg <= tmp2;
d_reg2 <= d_reg;
end
end
assign d = d_reg2;
endmodule
module child_mod(
input [7:0]a,
input [7:0]b,
output [7:0]d
);
assign d = (a>b) ? b : a;
endmodule
VL10 使用函数实现数据大小端转换
讲解视频:10-函数与任务function和task
题解 | Verilog刷题解析【10】function和task的使用、相关笔试题
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module function_mod(
input clk,
input rst_n,
input [3:0]a,
input [3:0]b,
output [3:0]c,
output [3:0]d
);
/*
function <返回值的类型或范围>函数名;
<端口说明语句>
<变量类型说明语句>
begin
<语句>
end
endfunction
*/
function [3:0] begin_end;
input [3:0] data_in;
begin
begin_end[0] = data_in[3];
begin_end[1] = data_in[2];
begin_end[2] = data_in[1];
begin_end[3] = data_in[0];
end
endfunction
assign c = begin_end(a);
assign d = begin_end(b);
endmodule
VL11 4位数值比较器电路
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module comparator_4(
input [3:0] A ,
input [3:0] B ,
output wire Y2 , //A>B
output wire Y1 , //A=B
output wire Y0 //A<B
);
assign Y2 = (A[3]>B[3]) | ((A[3]==B[3])&&(A[2]>B[2])) | ((A[3]==B[3])&&(A[2]==B[2])&&(A[1]>B[1])) | ((A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]>B[0]));
assign Y1 = (A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]==B[0]);
assign Y0 = (~Y2) & (~Y1);
endmodule
VL12 4bit超前进位加法器电路
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module lca_4(
input [3:0] A_in ,
input [3:0] B_in ,
input C_1 ,
output wire CO ,
output wire [3:0] S
);
wire [3:0] G;
wire [3:0] P;
assign G[0] = A_in[0] & B_in[0];
assign G[1] = A_in[1] & B_in[1];
assign G[2] = A_in[2] & B_in[2];
assign G[3] = A_in[3] & B_in[3];
assign P[0] = A_in[0] ^ B_in[0];
assign P[1] = A_in[1] ^ B_in[1];
assign P[2] = A_in[2] ^ B_in[2];
assign P[3] = A_in[3] ^ B_in[3];
wire [3:0] C;
assign S[0] = P[0] ^ C_1;
assign S[1] = P[1] ^ C[0];
assign S[2] = P[2] ^ C[1];
assign S[3] = P[3] ^ C[2];
assign CO = C[3];
assign C[0] = G[0] | P[0]&C_1;
assign C[1] = G[1] | P[1]&C[0];
assign C[2] = G[2] | P[2]&C[1];
assign C[3] = G[3] | P[3]&C[2];
endmodule
1320不建议做了,没有太大意义,这里只给出1316的代码。
VL13 优先编码器电路1
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module encoder_0(
input [8:0] I_n ,
output reg [3:0] Y_n
);
always @ (*)
begin
casex(I_n)
9'b1_1111_1111 : Y_n = 4'b1111;
9'b0_xxxx_xxxx : Y_n = 4'b0110;
9'b1_0xxx_xxxx : Y_n = 4'b0111;
9'b1_10xx_xxxx : Y_n = 4'b1000;
9'b1_110_xxxx : Y_n = 4'b1001;
9'b1_1110_xxxx : Y_n = 4'b1010;
9'b1_1111_0xxx : Y_n = 4'b1011;
9'b1_1111_10xx : Y_n = 4'b1100;
9'b1_1111_110x : Y_n = 4'b1101;
9'b1_1111_1110 : Y_n = 4'b1110;
default : Y_n = 4'b1111;
endcase
end
endmodule
VL14 用优先编码器1实现键盘编码电路
`timescale 1ns/1ns
//
// 作者: FPGA探索者,FPGA_Explorer
//
module encoder_0(
input [8:0] I_n ,
output reg [3:0] Y_n
);
always @(*)
begin
casex(I_n)
9'b111111111 : Y_n = 4'b1111;
9'b0xxxxxxxx : Y_n = 4'b0110;
9'b10xxxxxxx : Y_n = 4'b0111;
9'b110xxxxxx : Y_n = 4'b1000;
9'b1110xxxxx : Y_n = 4'b1001;
9'b11110xxxx : Y_n = 4'b1010;
9'b111110xxx : Y_n = 4'b1011;
9'b1111110xx : Y_n = 4'b1100;
9'b11111110x : Y_n = 4'b1101;
9'b111111110 : Y_n = 4'b1110;
default : Y_n = 4'b1111;
endcase
end
endmodule
module key_encoder(
input [9:0] S_n ,
output wire[3:0] L ,
output wire GS
);
wire [3:0] LL;
encoder_0 U0(
.I_n( S_n[9:1] ) ,
.Y_n( LL )
);
assign L = ~LL;
assign GS = ((LL == 4'b1111) && (S_n[0] == 1)) ? 0 : 1;
endmodule
VL15 优先编码器2——8线-3线优先编码器
`timescale 1ns/1ns

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



