HDLBits_Fadd

这篇博客介绍了如何使用VHDL编程语言创建一个具有两层层次的加法器电路。在最高层(top_module)中,实例化了两个add16模块,每个add16模块又包含16个add1模块。add1模块实现了基本的全加器功能,而add16模块则组合这些基本全加器以实现16位加法。博客提供了正确的VHDL代码示例,避免了重复声明module“add16”的错误。

In this exercise, you will create a circuit with two levels of hierarchy. Your top_module will instantiate two copies of add16
(provided), each of which will instantiate 16 copies of add1 (which
you must write). Thus, you must write two modules: top_module and
add1.
**

在这里插入图片描述

其实只要你写出,顶层调用add16,和add1的实现就行了,无需写add16的实现,如果自己实现了add16,会报错 module “add16” cannot be declared more than once File

正确代码如下

module top_module (
    input [31:0] a,
    input [31:0] b,
    output [31:0] sum
    
    
    
);//
    wire jin[31:0];
    wire jinwei;
    add16 uu1(a[15:0],b[15:0],1'b0,sum[15:0],jinwei);
    add16 uu2(a[31:16],b[31:16],jinwei,sum[31:16]);

endmodule

module add1 ( input a, input b, input cin,   output sum, output cout );

// Full adder module here
    assign sum = a^b^cin;
    assign cout = a&b | a&cin | b&cin;

endmodule

当时自己按照图实现的add16

module add16(input [15:0] a,input [15:0] b,input cin,output[15:0] sum,output cout);
    wire [15:0]jin;
    add1 u0(a[0],b[0],chu,sum[0],jin[0]);
    add1 u1(a[1],b[1],jin[0],sum[1],jin[1]);
    add1 u2(a[2],b[2],jin[1],sum[2],jin[2]);
    add1 u3(a[3],b[3],jin[2],sum[3],jin[3]);
    add1 u4(a[4],b[4],jin[3],sum[4],jin[4]);
    add1 u5(a[5],b[5],jin[4],sum[5],jin[5]);
    add1 u6(a[6],b[6],jin[5],sum[6],jin[6]);
    add1 u7(a[7],b[7],jin[6],sum[7],jin[7]);
    add1 u8(a[8],b[8],jin[7],sum[8],jin[8]);
    add1 u9(a[9],b[9],jin[8],sum[9],jin[9]);
    add1 u10(a[10],b[10],jin[9],sum[10],jin[10]);
    add1 u11(a[11],b[11],jin[10],sum[11],jin[11]);
    add1 u12(a[12],b[12],jin[11],sum[12],jin[12]);
    add1 u13(a[13],b[13],jin[12],sum[13],jin[13]);
    add1 u14(a[14],b[14],jin[13],sum[14],jin[14]);
    add1 u15(a[15],b[15],jin[14],sum[15],cout);
endmodule
module key_filter( input clk, input rst_n, input key_fadd, input key_fsub, input key_range, input key_sel, output reg fadd_flag, output reg fsub_flag, output reg range_flag, output reg sel_flag ); parameter DELAY_MAX = 19'd999_999; reg [1:0] key_fadd_sync; reg [18:0] cnt_fadd; reg key_fadd_stable; reg key_fadd_prev; always @(posedge clk or negedge rst_n) begin if(!rst_n) key_fadd_sync <= 2'b11; else begin key_fadd_sync[0] <= key_fadd; key_fadd_sync[1] <= key_fadd_sync[0]; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) cnt_fadd <= 19'd0; else begin if(key_fadd_sync[1] != key_fadd_stable) cnt_fadd <= 19'd0; else if(cnt_fadd < DELAY_MAX) cnt_fadd <= cnt_fadd + 1'b1; else cnt_fadd <= DELAY_MAX; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) key_fadd_stable <= 1'b1; else if(cnt_fadd == DELAY_MAX) key_fadd_stable <= key_fadd_sync[1]; end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin key_fadd_prev <= 1'b1; fadd_flag <= 1'b0; end else begin key_fadd_prev <= key_fadd_stable; fadd_flag <= (!key_fadd_stable) & key_fadd_prev; end end reg [1:0] key_fsub_sync; reg [18:0] cnt_fsub; reg key_fsub_stable; reg key_fsub_prev; always @(posedge clk or negedge rst_n) begin if(!rst_n) key_fsub_sync <= 2'b11; else begin key_fsub_sync[0] <= key_fsub; key_fsub_sync[1] <= key_fsub_sync[0]; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) cnt_fsub <= 19'd0; else begin if(key_fsub_sync[1] != key_fsub_stable) cnt_fsub <= 19'd0; else if(cnt_fsub < DELAY_MAX) cnt_fsub <= cnt_fsub + 1'b1; else cnt_fsub <= DELAY_MAX; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) key_fsub_stable <= 1'b1; else if(cnt_fsub == DELAY_MAX) key_fsub_stable <= key_fsub_sync[1]; end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin key_fsub_prev <= 1'b1; fsub_flag <= 1'b0; end else begin key_fsub_prev <= key_fsub_stable; fsub_flag <= (!key_fsub_stable) & key_fsub_prev; end end reg [1:0] key_range_sync; reg [18:0] cnt_range; reg key_range_stable; reg key_range_prev; always @(posedge clk or negedge rst_n) begin if(!rst_n) key_range_sync <= 2'b11; else begin key_range_sync[0] <= key_range; key_range_sync[1] <= key_range_sync[0]; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) cnt_range <= 19'd0; else begin if(key_range_sync[1] != key_range_stable) cnt_range <= 19'd0; else if(cnt_range < DELAY_MAX) cnt_range <= cnt_range + 1'b1; else cnt_range <= DELAY_MAX; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) key_range_stable <= 1'b1; else if(cnt_range == DELAY_MAX) key_range_stable <= key_range_sync[1]; end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin key_range_prev <= 1'b1; range_flag <= 1'b0; end else begin key_range_prev <= key_range_stable; range_flag <= (!key_range_stable) & key_range_prev; end end reg [1:0] key_sel_sync; reg [18:0] cnt_sel; reg key_sel_stable; reg key_sel_prev; always @(posedge clk or negedge rst_n) begin if(!rst_n) key_sel_sync <= 2'b11; else begin key_sel_sync[0] <= key_sel; key_sel_sync[1] <= key_sel_sync[0]; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) cnt_sel <= 19'd0; else begin if(key_sel_sync[1] != key_sel_stable) cnt_sel <= 19'd0; else if(cnt_sel < DELAY_MAX) cnt_sel <= cnt_sel + 1'b1; else cnt_sel <= DELAY_MAX; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) key_sel_stable <= 1'b1; else if(cnt_sel == DELAY_MAX) key_sel_stable <= key_sel_sync[1]; end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin key_sel_prev <= 1'b1; sel_flag <= 1'b0; end else begin key_sel_prev <= key_sel_stable; sel_flag <= (!key_sel_stable) & key_sel_prev; end end endmodule 生成tb代码
最新发布
07-05
### 生成 Verilog 模块 `key_filter` 的测试平台代码 在数字电路设计中,测试平台(testbench)用于验证设计的功能是否符合预期。针对用户提供的模块 `key_filter`,其输入信号包括 `clk`, `rst_n`, `key_fadd`, `key_fsub`, `key_range`, `key_sel`,输出为若干标志位(flags)。以下是一个完整的 Testbench 示例。 #### 测试平台结构 Testbench 包含以下部分: - **信号声明**:定义与被测模块接口匹配的输入/输出信号。 - **模块实例化**:将 `key_filter` 实例化到测试平台中。 - **激励生成**:使用 `initial` 块模拟时钟、复位及按键操作。 - **结果监控**:使用 `$monitor` 打印关键信号的变化。 #### 完整的 Testbench 示例 ```verilog module key_filter_testbench; // 声明信号 reg clk; reg rst_n; reg key_fadd; reg key_fsub; reg key_range; reg key_sel; // 输出标志 wire flag_fadd; wire flag_fsub; wire flag_range; wire flag_sel; // 实例化被测模块 key_filter uut ( .clk(clk), .rst_n(rst_n), .key_fadd(key_fadd), .key_fsub(key_fsub), .key_range(key_range), .key_sel(key_sel), .flag_fadd(flag_fadd), .flag_fsub(flag_fsub), .flag_range(flag_range), .flag_sel(flag_sel) ); // 生成时钟信号 always #5 clk = ~clk; // 10ns周期,50MHz频率 // 初始激励 initial begin // 初始化所有输入 clk = 0; rst_n = 0; key_fadd = 0; key_fsub = 0; key_range = 0; key_sel = 0; // 复位释放 #20 rst_n = 1; // 模拟按键按下 #10 key_fadd = 1; #10 key_fadd = 0; #10 key_fsub = 1; #10 key_fsub = 0; #10 key_range = 1; #10 key_range = 0; #10 key_sel = 1; #10 key_sel = 0; #20 $finish; end // 监控输出变化 initial begin $monitor("Time=%0t: fadd=%b, fsub=%b, range=%b, sel=%b", $time, flag_fadd, flag_fsub, flag_range, flag_sel); end endmodule ``` #### 注意事项 - **不可综合代码**:Testbench 中可以使用行为级语句,如 `#delay` 和 `$monitor`,这些不会影响仿真但不能用于综合。 - **结构清晰**:将时钟、复位和激励分开编写,便于调试和扩展。 - **自动化测试**:可在 `initial` 块中加入更多复杂序列以覆盖边界情况,例如连续按键或异步复位[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值