题意整理

1、寄存器的位是可以分开单独运算的,并不是一个输入就一定是一个数据,在很多情况下,一个输入既包括数据又包括地址等其他有效信息

2、需要考虑数据锁存的问题,一定要在sel为0的时候进行锁存,只有此时的写入才是有效的(validout的下降沿写入有效),同时存在多种情况且没有优先级问题,建议使用case语句

题解主体

可以得到状态转换:

sel

out

validout

0

0  锁存输入

0

1

[3:0]+[7:4] 

1

2

[3:0]+[11:8]

1

3

[3:0]+[15:12]

1

根据激励方程和输出方程以及思路整理,关键电路如下:


这段电路的意思是首先将锁存的16位数据分段移位到4位数据,然后进行相加,再组合成一个20位的数据,按照选择器进行输出其中的5位。



将电路转换成Verilog代码描述如下

reg [15:0]data_lock; 


always@(posedge clk or negedge rst) begin

       if (!rst)

              data_lock <= 0;

       else if(!sel)

              data_lock <= d;

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

因此实现方式为如下的电路,综合得到:

参考答案

`timescale 1ns/1ns

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

output reg[4:0]out,
output reg validout
);

reg [15:0]data_lock;  


always@(posedge clk or negedge rst) begin
	if (!rst)
		data_lock <= 0;
	else if(!sel)
		data_lock <= d;
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


endmodule