在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 438|回复: 5

[求助] 加法器的设计

[复制链接]
发表于 2024-4-2 09:06:58 | 显示全部楼层 |阅读模式
1000资产

设计一个位宽为4的加法器,其输出受到输入最低位与的结果的影响。如果最低位的与为0,则当前时钟周期直接输出结果(下一个时钟周期可以读取下一组输入);如果最低位的与为1,则当前时钟周期输出高阻,在下一个时钟周期输出全0(下一个时钟周期不能读取下一组输入)。
在testbench中,需要根据最低位的结果循环读入输入数据:如果最低位的与为0,则在下一个时钟周期读取下一组输入;如果最低位的与为1,则在下下一个时钟周期读取下一组输入。

我的代码有问题,请大神帮忙修改下,能够实现所需功能。谢谢。

module test #(parameter width_in = 4)
(
input  clk, rst,
input  [width_in - 1 : 0] x, y,
output  E,
output reg [width_in : 0] out
);
wire [width_in : 0] s;

reg flag;

assign s = x + y;
assign E = x[0] & y[0];

always @ (posedge clk or negedge rst)
begin
        if (!rst)
        begin
                out  <= 'd0;
                flag <= 'd0;
        end
        else if (!E) //E == 0 normal ouput
        begin
                out  <= s;
                flag <= 'd0;
        end
        else if (flag)
        begin
                out  <= 'd0;
                flag <= 'd0;
        end
        else
        begin
                out  <= 'dz;
                flag <= 1'b1;
        end
end

endmodule

`timescale 1ns / 1ps
module test_tb #(parameter width_in = 4, count = 10) ();

reg  clk, rst;
reg  [width_in - 1 : 0] x, y;
wire E;
wire [width_in : 0] out;

test #(4) dut (clk, rst, x, y, E, out);

reg [width_in - 1 : 0] inx [0 : count-1];
reg [width_in - 1 : 0] iny [0 : count-1];

integer i;

initial
begin
        clk = 1'b1;
end
always
begin
        #5 clk = ~clk;
end

initial
begin
        rst = 1'b0;
        #10
        rst = 1'b1;
        $readmemb("../../inx.txt", inx);
        $readmemb("../../iny.txt", iny);
        for (i = 0; i <= count-1; i = i + 1)
        begin
                x <= inx;
                y <= iny;
                if (~E)
                           #10;
                else
                        #20;
        end
        #20 $stop;
end

endmodule

最佳答案

查看完整内容

再修改了一下,输出 E 规范了一下波形 module test #(parameter width_in = 4) ( input clk, rst, input [width_in - 1 : 0] x, y, output E, output [width_in : 0] out ); wire E_0; wire [width_in : 0] s; reg flag; reg [width_in : 0] out_r; assign s = x + y; assign E = flag ? 1'b0 : (x[0] & y[0]); // input data reading c ...
发表于 2024-4-2 09:06:59 | 显示全部楼层
再修改了一下,输出 E 规范了一下波形
module test #(parameter width_in = 4)
   (
    input  clk, rst,
    input  [width_in - 1 : 0] x, y,
    output  E,
    output [width_in : 0] out
    );
   wire                   E_0;
   wire [width_in : 0]    s;
   reg                    flag;
   reg [width_in : 0]     out_r;
   assign s = x + y;
   assign E = flag ? 1'b0 : (x[0] & y[0]); // input data reading control
   assign #1 E_0 = x[0] & y[0]; // delay 1 for simulation, avoid hold problem
   assign out = flag ? 'dz : out_r; // high-z on wire
   always @ (posedge clk or negedge rst)
     begin
        if (!rst)
          begin
             out_r  <= 'd0;
             flag <= 'd0;
          end
        else if (flag)
          begin
             out_r  <= 'd0;
             flag <= 'd0;
          end
        else if (E_0)
          begin
             out_r  <= 'd0;
             flag <= 1'b1;
          end
        else //if (!E_0) //E_0 == 0 normal ouput
        begin
           out_r  <= s;      
           flag <= 'd0;
        end
     end
endmodule


module test_tb #(parameter width_in = 4, count = 10) ();
   reg  clk, rst;
   reg [width_in - 1 : 0] x, y;
   wire                   E;
   wire [width_in : 0]    out;
   test #(4) dut (.clk(clk), .rst(rst), .x(x), .y(y), .E(E), .out(out));
   reg [width_in - 1 : 0] inx [0 : count-1];
   reg [width_in - 1 : 0] iny [0 : count-1];
   integer                i;

   initial
     begin
        clk = 1'b1;
        @(posedge rst);
        forever
          begin
             #5 clk = ~clk;
          end
     end

   initial
     begin
        x = 'b0;
        y = 'b0;
        rst = 1'b0;
        $readmemb("./inx.txt", inx);
        $readmemb("./iny.txt", iny);
        x = inx[ 0 ] ;
        y = iny[ 0 ] ;
        #10;
        rst = 1'b1;
        for (i = 1; i <= count-1; i = i + 1)
          begin
             @(posedge clk);
             if (E) begin
                wait(~E);
                @(posedge clk);
             end
             x = inx[ i ] ;
             y = iny[ i ] ;
          end
        #20 $finish;
     end // initial begin

endmodule // test_tb
发表于 2024-4-3 13:15:35 | 显示全部楼层
本帖最后由 harry_hust 于 2024-4-3 13:18 编辑

RTL代码需要注意的是 high-z 只能在 wire 上输出,然后调整了always 里面的优先级;
testbench 的数据控制 需要用 clk 来trigger 保证采样时序正确

按照你的框架大致修改了一下,没有验证,你可以参考看看


module test #(parameter width_in = 4)
(
input  clk, rst,
input  [width_in - 1 : 0] x, y,
output  E,
output [width_in : 0] out
);
wire E_0;
wire [width_in : 0] s;
reg flag;
reg [width_in : 0] out_r;
assign s = x + y;
assign E = flag ? 1'b0 : (x[0] & y[0]); // input data reading control
assign E_0 = x[0] & y[0]; //
assign out = flag ? 'dz : out_r; // high-z on wire
always @ (posedge clk or negedge rst)
begin
        if (!rst)
        begin
                out_r  <= 'd0;
                flag <= 'd0;
        end
        else if (flag)
        begin
                out_r  <= 'd0;
                flag <= 'd0;
        end
        else if (E_0)
        begin
                out_r  <= 'd0;
                flag <= 1'b1;
        end
        else //if (!E_0) //E_0 == 0 normal ouput
        begin
                out_r  <= s;
                flag <= 'd0;
        end
end
endmodule

`timescale 1ns / 1ps
module test_tb #(parameter width_in = 4, count = 10) ();
reg  clk, rst;
reg  [width_in - 1 : 0] x, y;
wire E;
wire [width_in : 0] out;
test #(4) dut (.clk(clk), .rst(rst), .x(x), .y(y), .E(E), .out(out));
reg [width_in - 1 : 0] inx [0 : count-1];
reg [width_in - 1 : 0] iny [0 : count-1];
integer i;

initial
begin
        clk = 1'b1;
forever
begin
        #5 clk = ~clk;
end
end

initial
begin
                x = 'b0;
                y = 'b0;
        rst = 1'b0;
        #10;
        rst = 1'b1;
        $readmemb("../../inx.txt", inx);
        $readmemb("../../iny.txt", iny);
        for (i = 0; i <= count-1; i = i + 1)
        begin
                                @(posedge clk);
                wait(~E);
                                #1;
                                x = inx[ i ];
                                y = iny[ i ] ;
        end
        #20 $stop;
end
endmodule
 楼主| 发表于 2024-4-4 10:38:13 | 显示全部楼层


harry_hust 发表于 2024-4-3 13:15
RTL代码需要注意的是 high-z 只能在 wire 上输出,然后调整了always 里面的优先级;
testbench 的数据控制  ...


你好,

感谢帮助。我仿真了你的代码,E=1时,能够产生所需的输出。
但是,E=1后的下一组输入的输出被覆盖掉了,没有产生正确结果。这是因为flag=1时,E=0,wait(~E)没有起到作用。请查看附图。
我尝试修改了几个版本,但是会出现各种问题。还请你再帮忙修改下。谢谢。

仿真结果

仿真结果

发表于 2024-4-7 11:00:46 | 显示全部楼层
这个简单debug 一下就行了吧。。

wait(~E);
改成
if (E) begin
                wait(~E);
                @(posedge clk);
             end
 楼主| 发表于 2024-4-7 11:46:12 | 显示全部楼层


harry_hust 发表于 2024-4-7 11:19
再修改了一下,输出 E 规范了一下波形
module test #(parameter width_in = 4)
   (


我仿真了,没问题。谢谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /2 下一条

×

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-30 22:39 , Processed in 0.023193 second(s), 8 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表