1. 四选一多路选择器
题目
制作一个四选一的多路选择器,要求输出定义上为线网类型
状态转换:
状态 | 序号 |
---|---|
d0 | 11 |
d1 | 10 |
d2 | 01 |
d3 | 00 |
解法
input [1:0]d1,d2,d3,d0,
input [1:0]sel,
output[1:0]mux_out
1、 使用 assign
赋值,使用多重三目运算符,根据输入 sel
信号的每一位确定选择输入
assign mux_out = sel[1] ? (sel[0] ? d0 : d1) : (sel[0] ? d2 : d3);
2、 使用assign和三目运算符,一个一个确定是否等于输入的d信号
assign mux_out = (sel == 2'b00) ? d3 : ((sel == 2'b01) ? d2 : (sel == 2'b10) ? d1 : d0);
3、 case语句
reg [1:0] mux_out_reg;
assign mux_out = 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
- 要在
always
块里使用,如果是用always
块描述组合逻辑,注意括号里的敏感变量列表都是电平触发,并且赋值时都要用阻塞赋值“=
” - 分支条件要写全,最好补齐
default
缺省条件,不然在组合逻辑中可能会由于条件不全导致出现锁存器Latch
2. 异步复位的串联T触发器
题目
用verilog实现两个串联的异步复位的T触发器的逻辑,结构如图:
解法
input wire data, clk, rst,
output reg q
T 触发器的概念,来 1 翻转,来 0 保持。
reg q1; //定义第一个T触发器,q是第二个作为输出
always @ (posedge clk or negedge rst) begin
if(!rst) begin
q1 <= 1'b0; //复位为0
end
else begin
if( data )
q1 <= ~q1; //来1翻转,来0保持
else
q1 <= q1;
end
end
//第二个T触发器
always @ (posedge clk or negedge rst) begin
if(!rst) begin
q <= 1'b0;
end
else begin
if( q1 )
q <= ~q; //来1翻转,来0保持,q1是第二个的输入
else
q <= q;
end
end
3. 奇偶检测
题目
现在需要对输入的32位数据进行奇偶校验,根据sel输出校验结果(1输出奇校验,0输出偶校验)
解法
input [31:0] bus,
input sel,
output check
assign
直接赋值
assign check = sel ? (^bus) : ~(^bus); //根据sel是奇校验还是偶校验
- 按位异或是将每一位进行异或运算,如果有奇数个1则为1。
- 不存在按位同或
4.移位运算与乘法
题目
已知d为一个8位数,请在每个时钟周期分别输出该数乘1/3/7/8,并输出一个信号通知此时刻输入的d有效(d给出的信号的上升沿表示写入有效)
解法
input [7:0]d ,
input clk,
input rst,
output reg input_grant,
output reg [10:0]out
reg [1:0] count; // 0 1 2 3 计数
reg [7:0] d_reg; //使用reg存储输入的数字d
always @ (posedge clk or negedge rst) begin
if(~rst) begin
count <= 2'b0;
end
else begin
count <= count + 1'b1; //时钟上升沿计数
end
end
// FSM
always @ (posedge clk or negedge rst) begin
//复位
if(~rst) begin
out <= 11'b0;
input_grant <= 1'b0;
d_reg <= 8'b0;
end
//case语句
else begin
case( count )
2'b00 : begin
out <= d; //输出一倍
d_reg <= d; //dreg存放一倍的值
input_grant <= 1'b1; //input_grant只有在倍数为1时输出为1
end
2'b01 : begin
out <= d_reg + {d_reg, 1'b0}; // *1 + *2 左移一倍和0拼接是2倍,再加上1倍等于3倍
input_grant <= 1'b0;
end
2'b10 : begin
out <= d_reg + {d_reg, 1'b0} + {d_reg, 2'b0}; //7倍=1倍+2倍+4倍
input_grant <= 1'b0;
end
2'b11 : begin
out <= {d_reg, 3'b0}; //左移三位,等于8倍
input_grant <= 1'b0;
end
default : begin
out <= d; //默认输出1倍
input_grant <= 1'b0;
end
endcase
end
end
5.位拆分与运算
题目
现在输入了一个压缩的16位数据,其实际上包含了四个数据[3:0][7:4][11:8][15:12],
现在请按照sel选择输出四个数据的相加结果,并输出valid_out信号(在不输出时候拉低)
0: 不输出且只有此时的输入有效
1:输出 [3:0] + [7:4]
2:输出 [3:0] + [11:8]
3:输出 [3:0] + [15:12]
解法
input clk,
input rst,
input [15:0]d,
input [1:0]sel,
output [4:0]out,
output validout
reg [15:0]data_lock;
always@(posedge clk or negedge rst) begin
if (!rst)
data_lock <= 0;
else if(!sel)
data_lock <= d; //16位数据放入data_lock中
end
always@(posedge clk or negedge rst) begin
if (!rst) begin
out <= 'b0;
validout <=0;
end
else begin
case(sel)
0:begin
out <= 'b0;
validout <=0; //无输出
end
1:begin
out <= data_lock[3:0]+data_lock[7:4]; //位拼接即可
validout <=1; //有输出
end
2:begin
out <= data_lock[3:0]+data_lock[11:8];
validout <=1;
end
3:begin
out <= data_lock[3:0]+data_lock[15:12];
validout <=1;
end
endcase
end
end
6.多功能数据处理器
题目
根据指示信号select的不同,对输入信号a,b实现不同的运算。输入信号a,b为8bit有符号数,当select信号为0,输出a;当select信号为1,输出b;当select信号为2,输出a+b;当select信号为3,输出a-b.
输入描述:
clk
:系统时钟
rst_n
:复位信号,低电平有效
a,b
:8bit位宽的有符号数
select
:2bit位宽的无符号数
输出描述:
c
:9 bit 位宽的有符号数
解法
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
7.求两个数的差值
题目
根据输入信号 a,b 的大小关系,求解两个数的差值:输入信号 a,b 为 8 bit 位宽的无符号数。如果 a>b,则输出 a-b,如果 a≤b,则输出 b-a。
**输入描述:**clk
:系统时钟
rst_n
:复位信号,低电平有效
a,b
:8 bit位宽的无符号数
输出描述:
c
:8 bit位宽的无符号数
解法
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
8.使用generate…for语句简化代码
题目
在某个 module
中包含了很多相似的连续赋值语句,请使用 generata…for
语句编写代码,替代该语句,要求不能改变原 module
的功能。
使用 Verilog HDL 实现以上功能并编写 testbench 验证。
module template_module(
input [7:0] data_in,
output [7:0] data_out
);
assign data_out [0] = data_in [7];
assign data_out [1] = data_in [6];
assign data_out [2] = data_in [5];
assign data_out [3] = data_in [4];
assign data_out [4] = data_in [3];
assign data_out [5] = data_in [2];
assign data_out [6] = data_in [1];
assign data_out [7] = data_in [0];
endmodule
输入描述:
data_in
:8bit位宽的无符号数
输出描述:
data_out
:8bit位宽的无符号数
解法
1、
// 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
2、使用 for
integer i;
reg [7:0] dout_reg;
assign data_out = dout_reg;
always @ (*) begin
for(i = 0; i < 8; i = i+1) begin
dout_reg[i] = data_in[7-i];
end
end
9. 使用子模块实现三输入数的大小比较
题目
在数字芯片设计中,通常把完成特定功能且相对独立的代码编写成子模块,在需要的时候再在主模块中例化使用,以提高代码的可复用性和设计的层次性,方便后续的修改。
请编写一个子模块,将输入两个 8 bit 位宽的变量 data_a, data_b,并输出data_a, data_b之中较小的数。并在主模块中例化,实现输出三个 8 bit 输入信号的最小值的功能。
输入描述:
clk
:系统时钟
rst_n
:异步复位信号,低电平有效
a,b,c
:8bit位宽的无符号数
输出描述:
d
:8bit位宽的无符号数,表示a,b,c中的最小值
解法
input clk,
input rst_n,
input [7:0]a,
input [7:0]b,
input [7:0]c,
output [7:0]d
1、使用时序逻辑子模块
需要调用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,显然不符合要求。
// 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 )
);
//子模块
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;
assign d = 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
2、使用组合逻辑子模块,需要打两拍
组合逻辑的子模块,就不存在时序逻辑中的延时问题,所以调用的时候用2个子模块就可以完成3个数的比较,为了符合时序波形的要求,多打一拍。
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;
//子模块
module child_mod(
input [7:0]a,
input [7:0]b,
output [7:0]d
);
assign d = (a>b) ? b : a;
endmodule
10.使用函数实现数据大小端转换
题目
在数字芯片设计中,经常把实现特定功能的模块编写成函数,在需要的时候再在主模块中调用,以提高代码的复用性和提高设计的层次,分别后续的修改。
请用函数实现一个4bit数据大小端转换的功能。实现对两个不同的输入分别转换并输出。
输入描述:
clk
:系统时钟
rst_n
:异步复位信号,低电平有效
a,b
:4bit位宽的无符号数
输出描述:
c,d
:8bit位宽的无符号数
解法
/*
function <返回值的类型或范围>函数名;
<端口说明语句>
<变量类型说明语句>
begin
<语句>
end
endfunction
*/
assign c = begin_end(a);
assign d = begin_end(b);
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
11. 4位数值比较器电路
题目
某4位数值比较器的功能表如下。
请用Verilog语言采用门级描述方式,实现此4位数值比较器
输入描述:
[3:0] A
[3:0] B
输出描述:
wire Y2
, //A>B
wire Y1
, //A=B
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
assign Y1 = (A[3]==B[3])&&(A[2]==B[2])&&(A[1]==B[1])&&(A[0]==B[0]);
assign Y0 = (~Y2) & (~Y1);
12. 4 bit超前进位加法器电路
题目
4 bit超前进位加法器的逻辑表达式如下:
中间变量
\[G_i=A_iB_i, P_i=A_i⊕B_i \]和:
\[S_i =P_i⊕C_{i-1} \]进位:
\[C_i =G_i + P_iC_{i-1} \]请用Verilog语言采用门级描述方式,实现此4bit超前进位加法器,接口电路如下:
输入描述:
输入信号:
A_in[3:0]
B_in[3:0]
C_1
类型:wire
输出描述:
输出信号:
S[3:0]
CO
类型:wire
解法
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];
13. 优先编码器电路①
题目
输入描述:
[8:0] I_n
输出描述:
reg [3:0] Y_n
解法
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
14.用优先编码器①实现键盘编码电路
题目
请使用优先编码器①实现键盘编码电路,可添加并例化题目中已给出的优先编码器代码。
10 个按键分别对应十进制数 0-9,按键 9 的优先级别最高;按键悬空时,按键输出高电平,按键按下时,按键输出低电平;键盘编码电路的输出是 8421BCD 码。
要求:键盘编码电路要有工作状态标志,以区分没有按键按下和按键0按下两种情况。
输入描述:
input [9:0] S_n
**输出描述:
output wire[3:0] L
output wire GS
解法
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;
15. 优先编码器Ⅰ
题目
下表是8线-3线优先编码器Ⅰ的功能表。
①请根据该功能表,用 Verilog 实现该优先编码器Ⅰ。
输入描述:
input [7:0] I
input EI
输出描述:
output wire [2:0] Y
output wire GS
output wire EO
解法
input [7:0] I ,
input EI ,
output wire [2:0] Y ,
output wire GS ,
output wire EO
reg [2:0] Y_Reg;
reg GS_Reg;
reg EO_Reg;
assign Y = Y_Reg;
assign GS = GS_Reg;
assign EO = EO_Reg;
always @ (*) begin
if( EI == 1'b0 ) begin
Y_Reg = 3'b0;
GS_Reg = 1'b0;
EO_Reg = 1'b0;
end
else begin
casex(I)
8'b0000_0000 : begin
Y_Reg = 3'b0;
GS_Reg = 1'b0;
EO_Reg = 1'b1;
end
8'b1xxx_xxxx : begin
Y_Reg = 3'b111;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
8'b01xx_xxxx : begin
Y_Reg = 3'b110;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
8'b001x_xxxx : begin
Y_Reg = 3'b101;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
8'b0001_xxxx : begin
Y_Reg = 3'b100;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
8'b0000_1xxx : begin
Y_Reg = 3'b011;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
8'b0000_01xx : begin
Y_Reg = 3'b010;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
8'b0000_001x : begin
Y_Reg = 3'b001;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
8'b0000_0001 : begin
Y_Reg = 3'b000;
GS_Reg = 1'b1;
EO_Reg = 1'b0;
end
endcase
end
end
16. 使用8线-3线优先编码器Ⅰ实现16线-4线优先编码器
题目
②请使用 2 片该优先编码器 Ⅰ 及必要的逻辑电路实现 16线-4线 优先编码器。优先编码器 Ⅰ 的真值表和代码已给出。
可将优先编码器Ⅰ的代码添加到本题答案中,并例化。
输入描述:
input [15:0] A
input EI
输出描述:
output wire [3:0] L
output wire GS
output wire EO
解法
input [15:0] A ,
input EI ,
output wire [3:0] L ,
output wire GS ,
output wire EO
wire [2:0] Y_1;
wire GS_1;
wire EO_1;
assign GS = GS_1 | GS_0;
assign EO = EO_0;
assign L[3] = GS_1;
assign L[2] = Y_1[2] | Y_0[2];
assign L[1] = Y_1[1] | Y_0[1];
assign L[0] = Y_1[0] | Y_0[0];
encoder_83 U0(
.I(A[15:8]) ,
.EI(EI) ,
.Y(Y_1) ,
.GS(GS_1) ,
.EO(EO_1)
);
wire [2:0] Y_0;
wire GS_0;
wire EO_0;
encoder_83 U1(
.I(A[7:0]) ,
.EI(EO_1) ,
.Y(Y_0) ,
.GS(GS_0) ,
.EO(EO_0)
);
17. 用3-8译码器实现全减器
题目
请使用3-8译码器和必要的逻辑门实现全减器,全减器接口图如下,A是被减数,B是减数,Ci是来自低位的借位,D是差,Co是向高位的借位。
3-8译码器代码如下,可将参考代码添加并例化到本题答案中。
module decoder_38(
input E ,
input A0 ,
input A1 ,
input A2 ,
output reg Y0n ,
output reg Y1n ,
output reg Y2n ,
output reg Y3n ,
output reg Y4n ,
output reg Y5n ,
output reg Y6n ,
output reg Y7n
);
always @(*)begin
if(!E)begin
Y0n = 1'b1;
Y1n = 1'b1;
Y2n = 1'b1;
Y3n = 1'b1;
Y4n = 1'b1;
Y5n = 1'b1;
Y6n = 1'b1;
Y7n = 1'b1;
end
else begin
case({A2,A1,A0})
3'b000 : begin
Y0n = 1'b0; Y1n = 1'b1; Y2n = 1'b1; Y3n = 1'b1;
Y4n = 1'b1; Y5n = 1'b1; Y6n = 1'b1; Y7n = 1'b1;
end
3'b001 : begin
Y0n = 1'b1; Y1n = 1'b0; Y2n = 1'b1; Y3n = 1'b1;
Y4n = 1'b1; Y5n = 1'b1; Y6n = 1'b1; Y7n = 1'b1;
end
3'b010 : begin
Y0n = 1'b1; Y1n = 1'b1; Y2n = 1'b0; Y3n = 1'b1;
Y4n = 1'b1; Y5n = 1'b1; Y6n = 1'b1; Y7n = 1'b1;
end
3'b011 : begin
Y0n = 1'b1; Y1n = 1'b1; Y2n = 1'b1; Y3n = 1'b0;
Y4n = 1'b1; Y5n = 1'b1; Y6n = 1'b1; Y7n = 1'b1;
end
3'b100 : begin
Y0n = 1'b1; Y1n = 1'b1; Y2n = 1'b1; Y3n = 1'b1;
Y4n = 1'b0; Y5n = 1'b1; Y6n = 1'b1; Y7n = 1'b1;
end
3'b101 : begin
Y0n = 1'b1; Y1n = 1'b1; Y2n = 1'b1; Y3n = 1'b1;
Y4n = 1'b1; Y5n = 1'b0; Y6n = 1'b1; Y7n = 1'b1;
end
3'b110 : begin
Y0n = 1'b1; Y1n = 1'b1; Y2n = 1'b1; Y3n = 1'b1;
Y4n = 1'b1; Y5n = 1'b1; Y6n = 1'b0; Y7n = 1'b1;
end
3'b111 : begin
Y0n = 1'b1; Y1n = 1'b1; Y2n = 1'b1; Y3n = 1'b1;
Y4n = 1'b1; Y5n = 1'b1; Y6n = 1'b1; Y7n = 1'b0;
end
default: begin
Y0n = 1'b1; Y1n = 1'b1; Y2n = 1'b1; Y3n = 1'b1;
Y4n = 1'b1; Y5n = 1'b1; Y6n = 1'b1; Y7n = 1'b1;
end
endcase
end
end
endmodule
输入描述:
input A
input B
input Ci
输出描述:
output wire D
output wire Co
解法
input A ,
input B ,
input Ci ,
output wire D ,
output wire Co
wire Y0_n ;
wire Y1_n ;
wire Y2_n ;
wire Y3_n ;
wire Y4_n ;
wire Y5_n ;
wire Y6_n ;
wire Y7_n ;
assign D = ~(Y1_n & Y2_n & Y4_n & Y7_n);
assign Co = ~(Y1_n & Y2_n & Y3_n & Y7_n);
decoder_38 U0(
.E (1'b1),
.A0 (Ci ),
.A1 (B ),
.A2 (A ),
.Y0n (Y0_n),
.Y1n (Y1_n),
.Y2n (Y2_n),
.Y3n (Y3_n),
.Y4n (Y4_n),
.Y5n (Y5_n),
.Y6n (Y6_n),
.Y7n (Y7_n)
);
18. 实现3-8译码器①
题目
下表是 74HC138 译码器的功能表
解法
input E1_n ,
input E2_n ,
input E3 ,
input A0 ,
input A1 ,
input A2 ,
output wire Y0_n ,
output wire Y1_n ,
output wire Y2_n ,
output wire Y3_n ,
output wire Y4_n ,
output wire Y5_n ,
output wire Y6_n ,
output wire Y7_n
wire E ;
assign E = E3 & ~E2_n & ~E1_n;
assign Y0_n = ~(E & ~A2 & ~A1 & ~A0);
assign Y1_n = ~(E & ~A2 & ~A1 & A0);
assign Y2_n = ~(E & ~A2 & A1 & ~A0);
assign Y3_n = ~(E & ~A2 & A1 & A0);
assign Y4_n = ~(E & A2 & ~A1 & ~A0);
assign Y5_n = ~(E & A2 & ~A1 & A0);
assign Y6_n = ~(E & A2 & A1 & ~A0);
assign Y7_n = ~(E & A2 & A1 & A0);
19. 使用 3-8 译码器 ① 实现逻辑函数
题目
请使用 3-8 译码器 ① 和必要的逻辑门实现函数 L=(~A)·C + A·B
输入描述:
input A
input B
input C
输出描述:
output wire L
解法
input A ,
input B ,
input C ,
output wire L
wire Y0_n ;
wire Y1_n ;
wire Y2_n ;
wire Y3_n ;
wire Y4_n ;
wire Y5_n ;
wire Y6_n ;
wire Y7_n ;
assign L = ~(Y1_n & Y3_n & Y6_n & Y7_n);
decoder_38 U0(
.E1_n (1'b0),
.E2_n (1'b0),
.E3 (1'b1),
.A0 (C),
.A1 (B),
.A2 (A),
.Y0_n (Y0_n),
.Y1_n (Y1_n),
.Y2_n (Y2_n),
.Y3_n (Y3_n),
.Y4_n (Y4_n),
.Y5_n (Y5_n),
.Y6_n (Y6_n),
.Y7_n (Y7_n)
);
20. 数据选择器实现逻辑电路
题目
请使用此4选1数据选择器和必要的逻辑门实现下列表达式。
L=A∙B+A∙~C+B∙C
数据选择器代码如下,可在本题答案中添加并例化此数据选择器。
module data_sel(
input S0 ,
input S1 ,
input D0 ,
input D1 ,
input D2 ,
input D3 ,
output wire Y
);
assign Y = ~S1 & (~S0&D0 | S0&D1) | S1&(~S0&D2 | S0&D3);
endmodule
解法
input A ,
input B ,
input C ,
output wire L
data_sel mySel(.S0(A), .S1(B), .D0(0), .D1(~C), .D2(C), .D3(1), .Y(L));
21. 根据状态转移表实现时序电路
题目
某同步时序电路转换表如下,请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。
电路的接口如下图所示。
解法
input A ,
input clk ,
input rst_n,
output wire Y
assign Y = (curr_state == 2'b11) ? 1 : 0;
// one step
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
curr_state <= 2'b00;
next_state <= 2'b00;
end
else begin
curr_state <= next_state;
end
end
// two step
always @ (*) begin
case(curr_state)
2'b00 : next_state = (A == 1'b1) ? 2'b11 : 2'b01;
2'b01 : next_state = (A == 1'b1) ? 2'b00 : 2'b10;
2'b10 : next_state = (A == 1'b1) ? 2'b01 : 2'b11;
2'b11 : next_state = (A == 1'b1) ? 2'b10 : 2'b00;
default : next_state = 2'b00;
endcase
end
22.根据状态转移图实现时序电路
题目
某同步时序电路的状态转换图如下,→上表示“C/Y”,圆圈内为现态,→指向次态。
请使用D触发器和必要的逻辑门实现此同步时序电路,用Verilog语言描述。
输入描述:
input C
input clk
input rst_n
输出描述:
output wire Y
解法
reg [1:0] curr_state;
reg [1:0] next_state;
assign Y = ((curr_state == 2'b11) | ((curr_state == 2'b10)&&(C == 1'b1)) )? 1 : 0;
// one step
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
curr_state <= 2'b00;
next_state <= 2'b00;
end
else begin
curr_state <= next_state;
end
end
// two step
always @ (*) begin
case(curr_state)
2'b00 : next_state = (C == 1'b1) ? 2'b01 : 2'b00;
2'b01 : next_state = (C == 1'b1) ? 2'b01 : 2'b11;
2'b10 : next_state = (C == 1'b1) ? 2'b10 : 2'b00;
2'b11 : next_state = (C == 1'b1) ? 2'b10 : 2'b11;
default : next_state = 2'b00;
endcase
end
23.ROM的简单实现
题目
实现一个深度为 8 ,位宽为 4 bit 的ROM,数据初始化为 0,2,4,6,8,10,12,14。可以通过输入地址 addr ,输出相应的数据 data 。
输入描述:
clk
:系统时钟
rst_n
:异步复位信号,低电平有效
addr
:8 bit 位宽的无符号数,输入到 ROM 的地址
输出描述:
data
:4 bit 位宽的无符号数,从 ROM 中读出的数据
解法
input clk,
input rst_n,
input [7:0]addr,
output [3:0]data
reg [3:0] romreg[7:0];
integer i;
assign data = romreg[addr];
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
romreg[0] <= 4'd0;
romreg[1] <= 4'd2;
romreg[2] <= 4'd4;
romreg[3] <= 4'd6;
romreg[4] <= 4'd8;
romreg[5] <= 4'd10;
romreg[6] <= 4'd12;
romreg[7] <= 4'd14;
end
else begin
// romreg[0] <= romreg[0];
// ...
// romreg[7] <= romreg[7];
for(i = 0; i < 8; i = i+1) begin : rom_i
romreg[i] <= romreg[i];
end
end
end
24.边沿检测
题目
有一个缓慢变化的1bit信号a,编写一个程序检测a信号的上升沿给出指示信号rise,当a信号出现下降沿时给出指示信号down。
注:rise,down应为单脉冲信号,在相应边沿出现时的下一个时钟为高,之后恢复到0,一直到再一次出现相应的边沿。
输入描述:
clk
:系统时钟信号
rst_n
:异步复位信号,低电平有效
a
:单比特信号,作为待检测的信号
输出描述:
rise
:单比特信号,当输入信号a出现上升沿时为1,其余时刻为0
down
:单比特信号,当输入信号a出现下降沿时为1,其余时刻为0
解法
input clk,
input rst_n,
input a,
output reg rise,
output reg down
reg a1;
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
a1 <= 1'b0; //复位
rise <= 1'b0;
down <= 1'b0;
end
else begin
a1 <= a; //阻塞赋值,模块结束才赋值,a1是之前的值,a是现在的值
if(a & ~a1)
rise <= 1'b1; //a1=0,a=1,即出现上升沿
else
rise <= 1'b0;
if(~a & a1)
down <= 1'b1; //a1=1,a=0出现下降沿
else
down <= 1'b0;
end
end
25.输入序列连续的序列检测
题目
请编写一个序列检测模块,检测输入信号a是否满足01110001序列,当信号满足该序列,给出指示信号match。
模块的接口信号图如下:
输入描述:
clk
:系统时钟信号
rst_n
:异步复位信号,低电平有效
a
:单比特信号,待检测的数据
输出描述:
match
:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0
解法
input clk,
input rst_n,
input a,
output reg match
1、 三段式状态机解决。
第一段:时序逻辑,固定写法,cs <= ns;
第二段:组合逻辑,描述状态跳转,cs 和输入下的 ns 变化;
第三段:时序逻辑,描述输出。
// 独热码编码 只有1 bit是1
parameter IDLE = 9'b000000001;
parameter S0 = 9'b000000010;
parameter S1 = 9'b000000100;
parameter S2 = 9'b000001000;
parameter S3 = 9'b000010000;
parameter S4 = 9'b000100000;
parameter S5 = 9'b001000000;
parameter S6 = 9'b010000000;
parameter S7 = 9'b100000000;
reg [8:0] cs, ns;
wire match_tmp;
assign match_tmp = (cs == S7);
// one step
always @ (posedge clk or negedge rst_n)
begin
if( ~rst_n ) begin
cs <= IDLE;
end
else begin
cs <= ns;
end
end
// two step
always @ (*) begin
case(cs)
IDLE : ns = (a == 1'b0) ? S0 : IDLE;
S0 : ns = (a == 1'b1) ? S1 : S0;
S1 : ns = (a == 1'b1) ? S2 : S0;
S2 : ns = (a == 1'b1) ? S3 : S0;
S3 : ns = (a == 1'b0) ? S4 : S0;
S4 : ns = (a == 1'b0) ? S5 : S0;
S5 : ns = (a == 1'b0) ? S6 : S0;
S6 : ns = (a == 1'b1) ? S7 : S0;
S7 : ns = (a == 1'b1) ? IDLE : S0;
default : ns = IDLE;
endcase
end
// three step
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
match <= 1'b0;
end
else begin
match <= match_tmp;
end
end
2、 序列缓存对比法(移位寄存器)
序列缓存对比法,则是将八个时刻的数据缓存,作为一个数组,每个时刻的输入位于数组的末尾,数组其它元素左移,把最早输入的数据移出。然后将数组和目标序列对比,如果数组和目标序列相等,则说明出现目标序列。
序列缓存对比法在实现上比较简单,本题采用该方法实现。首先声明一个数组,缓存八个时刻的a输入的数值。移位可以通过位截取操作和位拼接操作实现:a_tem[6:0]
表示截取a_tem
的低 7 位,{a_tem[6:0],a}
表示把~和新输入的数值 a拼接,a 位于低位。
reg [7:0] a_tem;
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
begin
match <= 1'b0;
end
else if (a_tem == 8'b0111_0001)
begin
match <= 1'b1;
end
else
begin
match <= 1'b0;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
begin
a_tem <= 8'b1; //这里的match复位取决于原本的序列开头,取一个相反值,否则会出现假匹配
end
else
begin
a_tem <= {a_tem[6:0],a}; //这里是左移序列
end
end
26.含有无关项的序列检测
题目
请编写一个序列检测模块,检测输入信号 a 是否满足 011XXX110
序列(长度为9位数据,前三位是 011,后三位是 110,中间三位不做要求),当信号满足该序列,给出指示信号 match
。
输入描述:
clk
:系统时钟信号
rst_n
:异步复位信号,低电平有效
a
:单比特信号,待检测的数据
**输出描述:
match
:当输入信号 a 满足目标序列,该信号为 1,其余时刻该信号为 0
解法
input clk,
input rst_n,
input a,
output reg match
reg [8:0] val;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
val <= 9'b0;
end else begin
val <= {val[7:0],a}; //移位寄存器拼接
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
match <= 1'b0;
end else begin
casex (val)
9'b011xxx110 : match <= 1'b1;
default : match <= 1'b0;
endcase
end
end
27.不重叠序列检测
题目
请编写一个序列检测模块,检测输入信号(a)是否满足011100
序列, 要求以每六个输入为一组,不检测重复序列,例如第一位数据不符合,则不考虑后五位。一直到第七位数据即下一组信号的第一位开始检测。当信号满足该序列,给出指示信号 match
。当不满足时给出指示信号 not_match
。
**输入描述:
clk
:系统时钟信号
rst_n
:异步复位信号,低电平有效
a
:单比特信号,待检测的数据
输出描述:
match
:当输入信号a满足目标序列,该信号为1,其余时刻该信号为0
not_match
:当输入信号a不满足目标序列,该信号为1,其余时刻该信号为0
解法
input clk,
input rst_n,
input data,
output reg match,
output reg not_match
reg [2:0] count;
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
count <= 3'b0;
end
else begin
if(count == 3'd5)
count <= 3'b0;
else
count <= count + 1'b1;
end
end
reg [5:0] seq;
always @ (*) begin
case(count)
3'd0 : seq[5] = data;
3'd1 : seq[4] = data;
3'd2 : seq[3] = data;
3'd3 : seq[2] = data;
3'd4 : seq[1] = data;
3'd5 : seq[0] = data;
default : seq = 6'b0;
endcase
end
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
match <= 1'b0;
not_match <= 1'b0;
end
else begin
if(count == 3'd5) begin
if(seq == 6'b011100) begin
match <= 1'b1;
not_match <= 1'b0;
end
else begin
match <= 1'b0;
ot_match <= 1'b1;
end
end
else begin
match <= 1'b0;
not_match <= 1'b0;
end
end
end
28.输入序列不连续的序列检测
题目
请编写一个序列检测模块,输入信号端口为 data
,表示数据有效的指示信号端口为data_valid
。当data_valid
信号为高时,表示此刻的输入信号data
有效,参与序列检测;当data_valid
为低时,data
无效,抛弃该时刻的输入。当输入序列的有效信号满足0110
时,拉高序列匹配信号match
。
输入描述:
clk
:系统时钟信号
rst_n
:异步复位信号,低电平有效
data
:单比特信号,待检测的数据
data_valid
:输入信号有效标志,当该信号为1时,表示输入信号有效
输出描述:
match
:当输入信号data满足目标序列,该信号为1,其余时刻该信号为0
解法
input clk,
input rst_n,
input data,
input data_valid,
output reg match
注意这道题只有在 data_valid
有效才会检测,其余的数据直接抛弃
// one step
reg [1:0] cs, ns;
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
cs <= 2'b0;
end
else begin
cs <= ns;
end
end
// two step
always @ (*) begin
case(cs)
2'b00 : begin
if(data_valid) begin
ns = (data==1'b0) ? 2'b01 : 2'b00;
end
else begin
ns = cs;
end
end
2'b01 : begin
if(data_valid) begin
ns = (data==1'b1) ? 2'b10 : 2'b01;
end
else begin
ns = cs;
end
end
2'b10 : begin
if(data_valid) begin
ns = (data==1'b1) ? 2'b11 : 2'b00;
end
else begin
ns = cs;
end
end
2'b11 : begin
if(data_valid) begin
ns = 2'b00;
end
else begin
ns = cs;
end
end
endcase
end
// three step
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
match <= 1'b0;
end
else begin
if(cs == 2'b11 && data == 1'b0 && data_valid == 1'b1)
match <= 1'b1;
else
match <= 1'b0;
end
end
29.信号发生器
题目
请编写一个信号发生器模块,根据波形选择信号wave_choice
发出相应的波形:wave_choice=0
时,发出方波信号;wave_choice=1
时,发出锯齿波信号;wave_choice=2
时,发出三角波信号。
输入描述:
clk
:系统时钟信号
rst_n
:异步复位信号,低电平有效
wave_choice
:2比特位宽的信号,根据该信号的取值不同,输出不同的波形信号
输出描述:
wave
:5比特位宽的信号,根据 wave_choice
的值,输出不同波形的信号
解法
input clk,
input rst_n,
input [1:0] wave_choice,
output reg [4:0]wave
reg [4:0] count; // 计数0~19
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
count <= 5'b0;
end
else begin
if(wave_choice == 2'b00) begin
if(count == 5'd19) begin
count <= 5'b0;
end
else begin
count <= count + 1'b1;
end
end
end
end
//刚进入三角波模式时,wave是下降的,所以flag的默认值是0。
reg flag;
always @ (posedge clk or negedge rst_n) begin
if( ~rst_n ) begin
wave <= 5'b0;
flag <= 1'b1; //指示 开始阶段的三角波处在下降
end
else begin
case(wave_choice)
//方波
2'b00 : begin
if(count == 5'd9) begin
wave <= 5'd20; //计数10个上升沿,波形跳跃
end
else if(count >= 5'd19)begin
wave <= 5'd0; //计数20个上升沿,波形跳跃
end
else begin
wave <= wave;
end
end
//锯齿波
2'b01 : begin
if(wave >= 5'd20) begin
wave <= 5'b0; //20的波形立刻跳跃为0
end
else begin
wave <= wave + 1'b1; //其余阶段的波形处于加1状态
end
end
//三角波
2'b10 : begin
if(flag == 1'b0) begin
if(wave >= 5'd20) begin
flag <= 1'b1;
wave <= wave - 1'b1; //其他波形切换三角波处于下降状态
end
else begin
wave <= wave + 1'b1;
end
end
else begin
if(wave == 5'd0) begin
flag <= 1'b0;
wave <= wave + 1'b1;
end
else begin
wave <= wave - 1'b1;
end
end
end
default : wave <= 5'b0;
endcase
end
end
30.数据串转并电路
题目
实现串并转换电路,输入端输入单 bit 数据,每当本模块接收到6个输入数据后,输出端输出拼接后的 6 bit 数据。本模块输入端与上游的采用valid-ready
双向握手机制,输出端与下游采用valid-only
握手机制。数据拼接时先接收到的数据放到data_b
的低位。
电路的接口如下图所示。valid_a
用来指示数据输入 data_a
的有效性,valid_b 用来指示数据输出 data_b
的有效性;ready_a
用来指示本模块是否准备好接收上游数据,本模块中一直拉高;clk
是时钟信号;rst_n
是异步复位信号。
解法
input clk,
input rst_n,
input valid_a,
input data_a,
output reg ready_a,
output reg valid_b,
output reg [5:0] data_b
reg [2:0] cnt;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 3'b0;
else if( cnt == 3'd5 )
cnt <= 3'b0;
else if(valid_a == 1'b1)
cnt <= cnt + 1'b1;
else
cnt <= cnt;
end
reg [5:0] data;
always@(*)
begin
case(cnt)
3'd0:data[0] = data_a;
3'd1:data[1] = data_a;
3'd2:data[2] = data_a;
3'd3:data[3] = data_a;
3'd4:data[4] = data_a;
3'd5:data[5] = data_a;
default:data = 6'b0;
endcase
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
valid_b <= 1'b0;
else if(cnt == 3'd5)
valid_b <= 1'b1;
else
valid_b <= 1'b0;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
data_b <= 6'b0;
else if(cnt == 3'd5 )
data_b <= data;
else
data_b <= data_b;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
ready_a <= 1'b0;
else
ready_a <= 1'b1;
end
标签:begin,wire,30,牛客,b1,output,rst,input,网手
From: https://www.cnblogs.com/accumulagain/p/17226227.html