题意整理
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