参考资料
【明德扬_verilog零基础入门语法HDL仿真快速掌握-手把手教你写FPGA/ASIC代码设计流程中的应用】
写法一:组合逻辑和异步逻辑组合分开来写
写法二:组合逻辑和异步逻辑合起来写
代码一:(数据宽度不易改变)
//模块设计
module mul_module(
mul_a,//输入
mul_b,//输入
clk,//输入——时钟
rst_n,//输入——复位
mul_result//输出
);
//输入
input[3:0] mul_a;//四位
input[2:0] mul_b;//三位
input clk;//一位
input rst_n;//一位
//输出,output需要定义reg还是wire
output[6:0] mul_result;//七位
reg[6:0] mul_result;//本模块。always产生,用reg
reg[6:0] mul_result_tmp;
//组合逻辑
always@(*)begin
mul_result_tmp = mul_a * mul_b;//组合逻辑的等号没有箭头
end
//异步时序逻辑
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
mul_result <= 0;
end
else begin
mul_result <= mul_result_tmp;//时序逻辑的等号有箭头
end
end
endmodule
代码二:(参数化数据位数)
//模块设计
module mul_module(
mul_a,//输入
mul_b,//输入
clk,//输入——时钟
rst_n,//输入——复位
mul_result//输出
);
//定义参数——位宽
parameter A_W = 4;
parameter B_W = 3;
parameter C_W = A_W + B_W;
//输入
input[A_W-1:0] mul_a;//四位
input[B_W-1:0] mul_b;//三位
input clk;//一位
input rst_n;//一位
//输出,output需要定义reg还是wire
output[C_W-1:0] mul_result;//七位
reg[C_W-1:0] mul_result;//本模块。always产生,用reg
reg[C_W-1:0] mul_result_tmp;
//组合逻辑
always@(*)begin
mul_result_tmp = mul_a * mul_b;//组合逻辑的等号没有箭头
end
//异步时序逻辑
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
mul_result <= 0;
end
else begin
mul_result <= mul_result_tmp;//时序逻辑的等号有箭头
end
end
endmodule
module mul2port(
din_a,//输入a
din_b,//输入b
din_c,//输入c
din_d,//输入d
sel_a,//输入选择信号a
sel_b,//输入选择信号b
clk,//时钟
rst_n,//复位
result_a,//输出a
result_b//输出b
);
//宏定义
parameter W_A = 3;//输入a位宽
parameter W_B = 2;//输入b位宽
parameter W_SWITCH = 4;//输入c位宽或输入d位宽
parameter W_RESULT_A = W_A + W_SWITCH;//输出a位宽
parameter W_RESULT_B = W_B + W_SWITCH;//输出b位宽
//输入
input[W_A-1:0] din_a;
input[W_B-1:0] din_b;
input[W_SWITCH-1:0] din_c;
input[W_SWITCH-1:0] din_d;
input sel_a;
input sel_b;
input clk;
input rst_n;
//输出
output [W_RESULT_A-1:0] result_a;
output [W_RESULT_B-1:0] result_b;
reg [W_RESULT_A-1:0] result_a;
reg [W_RESULT_B-1:0] result_b;
//中间变量
reg sel_tmp;//sel_a和sel_b的并
reg sel_switch_tmp;//sel_a和sel_b经过触发器
reg[W_SWITCH-1:0] switch_tmp;//选择器输出
reg [W_RESULT_A-1:0] result_a_tmp;
reg [W_RESULT_B-1:0] result_b_tmp;
always@(*) begin
sel_tmp = sel_a&&sel_b;
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sel_switch_tmp <= 0;
end
else begin
sel_switch_tmp <= sel_tmp;
end
end
always@(*)begin
if(sel_switch_tmp==0)begin
switch_tmp = din_c;
end
else begin
switch_tmp = din_d;
end
end
mul_module#(.B_W(W_B)) mul_4_2(//注意此处参数例化B_W变成2
.mul_a (din_b),
.mul_b (switch_tmp),
.clk (clk),
.rst_n (rst_n),
.mul_result (result_b_tmp)
);
mul_module mul_4_3(//注意此处参数例化B_W变成2
.mul_a (din_A),
.mul_b (switch_tmp),
.clk (clk),
.rst_n (rst_n),
.mul_result (result_a_tmp)
);
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
result_a <= 0;
end
else begin
result_a <= result_a_tmp;
end
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
result_b <= 0;
end
else begin
result_b <= result_b_tmp;
end
end
endmodule
设计思路:从结果倒推设计过程
module mul2port(
din_a,//输入a
din_b,//输入b
din_c,//输入c
din_d,//输入d
sel_a,//输入选择信号a
sel_b,//输入选择信号b
clk,//时钟
rst_n,//复位
result_a,//输出a
result_b//输出b
);
//宏定义
parameter W_A = 3;//输入a位宽
parameter W_B = 2;//输入b位宽
parameter W_SWITCH = 4;//输入c位宽或输入d位宽
parameter W_RESULT_A = W_A + W_SWITCH;//输出a位宽
parameter W_RESULT_B = W_B + W_SWITCH;//输出b位宽
//输入
input[W_A-1:0] din_a;
input[W_B-1:0] din_b;
input[W_SWITCH-1:0] din_c;
input[W_SWITCH-1:0] din_d;
input sel_a;
input sel_b;
input clk;
input rst_n;
//输出
output [W_RESULT_A-1:0] result_a;
output [W_RESULT_B-1:0] result_b;
reg [W_RESULT_A-1:0] result_a;
reg [W_RESULT_B-1:0] result_b;
//中间变量
reg sel_tmp;//sel_a和sel_b的并
reg sel;//sel_a和sel_b经过触发器
reg[W_SWITCH-1:0] sel_dout;//选择器输出
wire [W_RESULT_A-1:0] result_a_tmp;//例化模块得到,使用wire
wire [W_RESULT_B-1:0] result_b_tmp;//例化模块得到,使用wire
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
result_a <= 0;
end
else begin
result_a <= result_a_tmp;
end
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
result_b <= 0;
end
else begin
result_b <= result_b_tmp;
end
end
//例化两个模块
mul_module#(.A_W(W_B),.B_W(W_SWITCH)) mul_4_2(//注意此处参数例化,个人编码练习中参数例化错误
.mul_a (din_b),
.mul_b (sel_dout),
.clk (clk),
.rst_n (rst_n),
.mul_result (result_b_tmp)
);
mul_module#(.A_W(W_A),.B_W(W_SWITCH)) mul_4_3(//注意此处参数例化,个人编码练习中参数例化错误
.mul_a (din_A),
.mul_b (sel_dout),
.clk (clk),
.rst_n (rst_n),
.mul_result (result_a_tmp)
);
//选择器
always@(*)begin
if(sel==0)begin
sel_dout = din_c;
end
else begin
sel_dout = din_d;
end
end
always@(*) begin
sel_tmp = sel_a&sel_b;//
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sel <= 0;
end
else begin
sel <= sel_tmp;
end
end
endmodule
对照标准答案发现的错误
//2024.1.10:虽然什么都没干,今天还是累了,明天起码更新两篇!!
//2024.1.11:坏了,明天一定全力以赴,今天写好了复杂的电路,明天对答案吧
//2024.1.12:完成此篇博文