有四个输入:
1、时钟信号clk
2、复位信号rst
3、16位数据信号d
4、控制信号sel
两个输出:
1、5位结果输出out
2、输出标志信号valid_out
这个题的意思是这样的:如果sel为0,模块不输出out,并将valid_out拉低表示无输出;同时将d的结果存入模块。如果sel为1,valid_out置高,并且输出d[3:0]+d[7:4]的结果。如果sel为2,valid_out置高,并且输出d[3:0]+d[11:8]的结果。如果sel为3,valid_out置高,并且输出d[3:0]+d[15:11]的结果。注意:只有在sel为0时,数据d才会进入模块。
这道题其实不是很难,因为Verilog可以使用位操作,例如:要输出d的前四位与后四位的和,只需要写:out = d[3:0] +d[7:4]即可。
这道题有clk输入,所以必然是在always模块下的时序电路,同时根据不同的sel有不同的输出,很自然的就想到了case函数。最后程序如下:
`timescale 1ns/1ns

module data_cal(
input clk,
input rst,
input [15:0]d,
input [1:0]sel,

output [4:0]out,   //题的输出是wire型,所以要有一个reg型的中间变量才能在always中赋值
output validout    //题的输出是wire型,所以要有一个reg型的中间变量才能在always中赋值
);
//*************code***********//
reg [15:0]  flag;          //用来储存输入d的中间变量
reg [4:0]  out_reg;          //out的reg形式
reg      validout_reg;     //validout的reg形式

assign out      = out_reg;      //用assign将两者连起来
assign validout      = validout_reg;

always@(posedge clk or negedge rst)
	if(rst == 1'b0)               //复位
		begin
			out_reg         <= 5'd0;
			validout_reg         <= 1'b0;
			flag         <= 16'd0;
		end
	else case(sel)            //使用case将不同的sel对应不同的操作
		2'd0:begin        //0时将validout置0,输出置0,并将d存入中间变量
			validout_reg     <= 1'b0;
			out_reg		 <= 5'd0;
			flag           <= d;
			end
		2'd1:begin        //1时将validout置1,输出[3:0]+[7:4]
			validout_reg     <= 1'b1;
			out_reg		 <= flag[3:0] + flag[7:4];
			end
		2'd2:begin        //2时将validout置1,输出[3:0]+[11:8]
			validout_reg     <= 1'b1;
			out_reg		 <= flag[3:0] +flag[11:8];
			end
		2'd3:begin        //2时将validout置1,输出[3:0]+[15:12]
			validout_reg     <= 1'b1;
			out_reg		 <= flag[3:0] +flag[15:12];
			end		
		default:begin     //case最后加上default是良好的习惯
			validout_reg     <= 1'b0;
			out_reg		 <= 5'd0;
			end
		endcase

//*************code***********//
endmodule