目录

VL5 位拆分与运算

题目描述

信号示意图

波形示意图

输入描述

输出描述

题目分析

RTL 设计

testbench 设计

仿真测试

VL6 多功能数据处理器

题目描述

接口信号图 

题目分析

RTL 设计

testbench 设计

仿真测试

VL7 求两个数的差值

题目描述

输入描述

输出描述

RTL 设计

testbench 设计

仿真测试


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]

信号示意图

【牛客网刷题】VL5-VL7位拆分与运算、数据处理器、求差值-LMLPHP

波形示意图

【牛客网刷题】VL5-VL7位拆分与运算、数据处理器、求差值-LMLPHP

输入描述

在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 得到相应的计算值。

【牛客网刷题】VL5-VL7位拆分与运算、数据处理器、求差值-LMLPHP

VL6 多功能数据处理器

题目描述

根据指示信号select的不同,对输入信号a,b实现不同的运算。输入信号a,b为8bit有符号数,当select信号为0,输出a;当select信号为1,输出b;当select信号为2,输出a+b;当select信号为3,输出a-b.

接口信号图 

【牛客网刷题】VL5-VL7位拆分与运算、数据处理器、求差值-LMLPHP

使用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

仿真测试

仿真结果显示正确!

【牛客网刷题】VL5-VL7位拆分与运算、数据处理器、求差值-LMLPHP

VL7 求两个数的差值

题目描述

根据输入信号a,b的大小关系,求解两个数的差值:输入信号a,b为8bit位宽的无符号数。如果a>b,则输出a-b,如果a≤b,则输出b-a。接口信号图如下:

【牛客网刷题】VL5-VL7位拆分与运算、数据处理器、求差值-LMLPHP

使用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数据,在延一拍出结果。

【牛客网刷题】VL5-VL7位拆分与运算、数据处理器、求差值-LMLPHP

10-24 16:24