目录
VL5 位拆分与运算
题目描述
现在输入了一个压缩的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]
信号示意图
波形示意图
输入描述
在testbench中,clk为周期5ns的时钟,rst为低电平复位
输出描述
题目分析
由输入的数据,根据 sel 的值输出相应的计算值,很明显就是一个选择器的选择结果,一般可以用两种方式:if 语句或者 case 语句,我使用 case 解决。并且需要注意的是,由于计算结果和输入的sel值是同步的,因为需要用组合逻辑,时序逻辑会延时一拍,不符合要求。
RTL 设计
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Author : Linest-5
// File : data_cal.v
// Create : 2022-10-07 21:48:59
// Revise : 2022-10-07 22:15:07
// Module Name : data_cal
// Description : 位拆分与运算
// Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
`timescale 1ns/1ns
module data_cal(
input clk,
input rst, //复位低有效
input [15:0] d,
input [1:0] sel,
output [4:0] out,
output validout
);
//*************code***********//
reg [15:0] d_reg;
reg [4:0] out_reg;
reg validout_reg;
always @(*) begin
if (!rst) begin
d_reg = 'd0;
out_reg = 'd0;
validout_reg = 'd0;
end
else begin
case(sel)
2'd0: begin
d_reg = d;
out_reg = 'd0;
validout_reg = 'd0;
end
2'd1: begin
d_reg = d_reg;
out_reg = d_reg[3:0] + d_reg[7:4];
validout_reg = 'd1;
end
2'd2: begin
d_reg = d_reg;
out_reg = d_reg[3:0] + d_reg[11:8];
validout_reg = 'd1;
end
2'd3: begin
d_reg = d_reg;
out_reg = d_reg[3:0] + d_reg[15:12];
validout_reg = 'd1;
end
default: begin
d_reg = d_reg;
out_reg = out_reg;
validout_reg = 'd0;
end
endcase
end
end
//结果赋值
assign out = out_reg;
assign validout = validout_reg;
//*************code***********//
endmodule
testbench 设计
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Author : Linest-5
// File : tb_data_cal.v
// Create : 2022-10-07 22:12:35
// Revise : 2022-10-07 22:28:38
// Module Name :
// Description :
// Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
`timescale 1ns/1ns
module tb_data_cal();
reg clk;
reg rst; //复位低有效
reg [15:0] d;
reg [1:0] sel;
wire [4:0] out;
wire validout;
initial begin
clk = 'd1;
rst <= 'd0;
#20
rst <= 'd1;
end
initial begin
d <= 'd0;
sel <= 'd0;
@(posedge rst);
@(posedge clk);
d <= 16'h8765;
@(posedge clk);
sel <= 'd1;
@(posedge clk);
@(posedge clk);
@(posedge clk);
d <= 16'h1234;
sel <= 'd2;
@(posedge clk);
@(posedge clk);
@(posedge clk);
sel <= 'd0;
@(posedge clk);
sel <= 'd3;
@(posedge clk);
@(posedge clk);
d <= 16'h2486;
@(posedge clk);
@(posedge clk);
@(posedge clk);
sel <= 'd0;
@(posedge clk);
sel <= 'd1;
@(posedge clk);
sel <= 'd0;
@(posedge clk);
sel <= 'd2;
@(posedge clk);
sel <= 'd0;
@(posedge clk);
sel <= 'd3;
#20
$finish;
end
always #5 clk = ~clk;
data_cal inst_data_cal (
.clk(clk),
.rst(rst),
.d(d),
.sel(sel),
.out(out),
.validout(validout)
);
//verdi
initial begin
$fsdbDumpfile("tb_data_cal.fsdb");
$fsdbDumpvars(0);
end
endmodule
仿真测试
可以看到输出结果是根据输入的数据和 sel 得到相应的计算值。
VL6 多功能数据处理器
题目描述
根据指示信号select的不同,对输入信号a,b实现不同的运算。输入信号a,b为8bit有符号数,当select信号为0,输出a;当select信号为1,输出b;当select信号为2,输出a+b;当select信号为3,输出a-b.
接口信号图
使用Verilog HDL实现以上功能并编写testbench验证。
输入描述
clk:系统时钟
rst_n:复位信号,低电平有效
a,b:8bit 位宽的有符号数
select:2bit 位宽的无符号数
输出描述
c:9bit位宽的有符号数
题目分析
和上一题很类似,由输入的两个位宽为 8 的有符号数,根据 select 信号的值执行相应的操作,并输出计算结果。这里依然采用 case 语句并采用时序逻辑。
RTL 设计
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Author : Linest-5
// File : data_select.v
// Create : 2022-10-12 21:17:41
// Revise : 2022-10-12 21:21:41
// Module Name :
// Description :
// Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
`timescale 1ns/1ns
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 <= 'd0;
end
else begin
case (select)
2'd0: begin
c <= a;
end
2'd1: begin
c <= b;
end
2'd2: begin
c <= a + b;
end
2'd3: begin
c <= a - b;
end
default: begin
c <= 'd0;
end
endcase
end
end
endmodule
testbench 设计
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Author : Linest-5
// File : tb_data_select.v
// Create : 2022-10-12 21:27:46
// Revise : 2022-10-20 21:35:40
// Module Name :
// Description :
// Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
`timescale 1ns/1ns
module tb_data_select();
reg clk;
reg rst_n;
reg signed [7:0] a,b;
reg [1:0] select;
wire signed [8:0] c;
initial begin
clk = 1'd1;
rst_n <= 1'd0;
a <= 8'b10110011;
b <= 8'b00111000;
#10
rst_n <= 1'd1;
#200
$finish;
end
always #5 clk = ~clk;
always #5 select <= {$random}%4;
data_select dut_inst(
.clk (clk),
.rst_n (rst_n),
.a (a),
.b (b),
.select(select),
.c (c)
);
//verdi
initial begin
$fsdbDumpfile("tb_data_select.fsdb");
$fsdbDumpvars(0);
end
endmodule
仿真测试
仿真结果显示正确!
VL7 求两个数的差值
题目描述
根据输入信号a,b的大小关系,求解两个数的差值:输入信号a,b为8bit位宽的无符号数。如果a>b,则输出a-b,如果a≤b,则输出b-a。接口信号图如下:
使用Verilog HDL实现以上功能并编写testbench验证。
输入描述
clk:系统时钟
rst_n:复位信号,低电平有效
a,b:8bit 位宽的无符号数
输出描述
c:8bit 位宽的无符号数
RTL 设计
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Author : Linest-5
// File : data_minus.v
// Create : 2022-10-19 20:29:34
// Revise : 2022-10-20 21:29:08
// Module Name :
// Description :
// Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
`timescale 1ns/1ns
module data_minus(
input clk,
input rst_n,
input [7:0] a,
input [7:0] b,
output reg [7:0] c
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
c <= 9'd0;
end
else if (a > b) begin
c <= a - b;
end
else begin
c <= b - a;
end
end
endmodule
testbench 设计
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// Author : Linest-5
// File : tb_data_minus.v
// Create : 2022-10-19 20:35:47
// Revise : 2022-10-20 21:33:12
// Module Name :
// Description :
// Editor : sublime text3, tab size (4)
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
`timescale 1ns/1ns
module tb_data_minus();
reg clk;
reg rst_n;
reg [7:0] a;
reg [7:0] b;
wire [7:0] c;
initial begin
clk = 'd1;
rst_n <= 'd0;
#20
rst_n <= 'd1;
#100
$finish;
end
always #5 clk = ~clk;
always #5 a <= {$random} % 9'd256;
always #5 b <= {$random} % 9'd256;
data_minus inst_data_minus (
.clk(clk),
.rst_n(rst_n),
.a(a),
.b(b),
.c(c)
);
//verdi
initial begin
$fsdbDumpfile("tb_data_minus.fsdb");
$fsdbDumpvars(0);
end
endmodule
仿真测试
从仿真图可以看到,根据输入的a、b数据,在延一拍出结果。