思路:1、寄存器的位是可以分开单独运算的,并不是一个输入就是一个数据,在很多情况下,一个输入既包括数据又包括地址等其他有效信息。
2、需要考虑数据锁存的问题,一定要在sel为0的时候进行锁存,只有此时的写入才是有效的,同时存在多种情况且没有优先级问题。因此使用case语句。
可以得到状态转换
sel | out | valid_out |
0 | 0锁存输入 | 0 |
1 | [3:0]+[7:4] | 1 |
2 | [3:0]+[11:8] | 1 |
3 | [3:0]+[15:12] | 1 |
解法一
`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 valid_out
);
reg [15:0] data_lock;
always@(posedge clk or negedge rst)
begin
if(!rst)
data_lock <= 1'b0;
else
data_lock <= d;
end
always@(posedge clk or negedge rst)
begin
if(!rst)begin
out <= 5'd0;
valid_out <= 1'b0;
end
else
case(sel)
2'd0:begin
valid_out <= 1'b0;
out <= 0;
end
2'd1:begin
valid_out <= 1'b1;
out <= data_lock[3:0] + data_lock[7:4];
end
2'd2:begin
valid_out <= 1'b1;
out <= data_lock[3:0] + data_lock[11:8];
end
2'd3:begin
valid_out <= 1'b1;
out <= data_lock[3:0] + data_lock[15:12];
end
default:begin
valid_out <= 1'b0;
out <= 5'd0;
end
endcase
end
endmodule
解法二:三目运算符
`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;
always@(posedge clk or negedge rst)
if(rst == 1'b0)
d_reg <= 16'b0;
else if(sel == 2'b0)
d_reg <= d;
else
d_reg <= d_reg;
assign validout = (sel == 2'b0)? 1'b0 : 1'b1;
assign out = (sel == 2'd0)? 5'b0:
(sel == 2'd1)? d_reg[3:0] + d_reg[7:4] :
(sel == 2'd2)? d_reg[3:0] + d_reg[11:8] :
(sel == 2'd3)? d_reg[3:0] + d_reg[15:12] : 5'b0;
//*************code***********//
endmodule
Testbench
`timescale 1ns/1ns
module testbench();
reg clk=1;
//always #5 clk = ~clk; // Create clock with period=10
initial begin
repeat(100)
#5 clk = ~clk;
end
reg rst;
wire [4:0] out;
wire valid_out;
reg [15:0] d;
reg [1:0] sel;
// A testbench
initial
begin
rst =1'b0;
d = 16'd0;
sel = 2'd0;
#2
rst = 1'b1;
d =16'b0000_0000_0000_0000;
sel =2'd0;
#10
rst = 1'b1;
d =16'b1000_0100_0010_0001;
sel =2'd2;
#10
rst = 1'b1;
d =16'b1000_0100_0010_0011;
sel =2'd1;
#10
rst = 1'b1;
d =16'b1000_0100_0010_0011;
sel =2'd0;
#5
rst = 1'b1;
d =16'b1000_0100_0010_0011;
sel =2'd3;
#10
rst = 1'b1;
d =16'b1000_0100_0010_0111;
sel =2'd3;
end
data_cal data_cal_inst
(
.clk(clk),
.rst(rst),
.d(d),
.sel(sel),
.out(out),
.valid_out(valid_out)
);
//end
initial begin
$dumpfile("out.vcd");
// This will dump all signal, which may not be useful
//$dumpvars;
// dumping only this module
//$dumpvars(1, testbench);
// dumping only these variable
// the first number (level) is actually useless
$dumpvars(0, testbench);
end
endmodule
注意:initial模块中只能是reg型变量,含有clk的要单独写一个always块中,通过
repeat(100)
#5 clk = ~clk;
这样波形会更加好看