码迷,mamicode.com
首页 > 其他好文 > 详细

Verilog - ABS代码重构

时间:2018-10-18 22:09:56      阅读:268      评论:0      收藏:0      [点我收藏+]

标签:round   方式   项目   idt   多次   https   代码   去掉   tar   

 https://mp.weixin.qq.com/s/-KUviTzO3Hdir_mI57L24g

从形式和语义两个层面,来扣一下ABS这段代码。
目的在于:在不降低通用性、不增加复杂度的情况下,提升可读性。
 
module ABS
#(
    parameter    DATA_WIDTH = 8
)
(
    input        [DATA_WIDTH-1:0]            din,
    output reg   [DATA_WIDTH-1:0]            dout
);

always @(*) begin
    if (din[DATA_WIDTH-1] == 1b1) begin // negative data
          if (din[DATA_WIDTH-2:0] == {(DATA_WIDTH-1){1b0}}) begin // Max
                dout = {1b0,{(DATA_WIDTH-1){1b1}}};
          end
          else begin
               dout  = {1b0,((~din[DATA_WIDTH-2:0])+1b1)};
          end
    end
    else begin
          dout = din;
    end
end

endmodule

 

 
 
1. 从形式上,DATA_WIDTH这个命名太长,作为module parameter提供详细语义无可厚非。但在module实现中使用这么长的名字,并且多次出现,则代码稍显冗长。可以使用localparam来缩短长度。
 
module ABS
#( 
    parameter    DATA_WIDTH = 8
)
(
    input        [DATA_WIDTH-1:0]            din,
    output reg   [DATA_WIDTH-1:0]            dout
);

localparam W   = DATA_WIDTH; 
localparam MSB = DATA_WIDTH - 1;

always @(*) begin
    if (din[MSB] == 1b1) begin // negative data
            if (din[W-2:0] == { (W-1){1b0} }) begin // Max 
                dout = {1b0,{(W-1){1b1}}};
            end
            else begin
                dout  = {1b0,((~din[W-2:0])+1b1)};
            end
    end
    else begin
            dout = din;
    end
end

endmodule

 

 
2. 形式上,实现中2次用到了W-1做bit-replicate与din对比,2次用到了W-2对din做part-select,1次使用W-1对din做bit-select(已经替换为MSB)。能否对这些重复出现的代码,增加一个别名?
 
module ABS
#( 
    parameter    DATA_WIDTH = 8
)
(
    input        [DATA_WIDTH-1:0]            din,
    output reg   [DATA_WIDTH-1:0]            dout
);

localparam W   = DATA_WIDTH; 
localparam MSB = DATA_WIDTH - 1;

wire         din_sign  = din[MSB];
wire [W-2:0] din_data  = din[W-2:0];
wire [W-2:0] pad0      = { (W-1){1b0} };
wire [W-2:0] pad1      = { (W-1){1b1} };

always @(*) begin
    if (din_sign == 1b1) begin // negative data
            if (din_data == pad0) begin // Max 
                dout = {1b0, pad1};
            end
            else begin
                dout  = {1b0,((~din_data)+1b1)};
            end
    end
    else begin
            dout = din;
    end
end

endmodule

 

 
3. 从语义上,把din_data与pad0比较,等价于直接与0比较,则可以简化:
 
module ABS
#( 
    parameter    DATA_WIDTH = 8
)
(
    input        [DATA_WIDTH-1:0]            din,
    output reg   [DATA_WIDTH-1:0]            dout
);

localparam W   = DATA_WIDTH; 
localparam MSB = DATA_WIDTH - 1;

wire         din_sign  = din[MSB];
wire [W-2:0] din_data  = din[W-2:0];
wire [W-2:0] pad1      = { (W-1){1b1} };

always @(*) begin
    if (din_sign == 1b1) begin // negative data
            if (din_data == 0) begin // Max 
                dout = {1b0, pad1};
            end
            else begin
                dout  = {1b0,((~din_data)+1b1)};
            end
    end
    else begin
            dout = din;
    end
end

endmodule

 

 
 
4. 语义上,如果-128的绝对值取127,则直接对din取反即可。
 
module ABS
#( 
    parameter    DATA_WIDTH = 8
)
(
    input        [DATA_WIDTH-1:0]            din,
    output reg   [DATA_WIDTH-1:0]            dout
);

localparam W   = DATA_WIDTH; 
localparam MSB = DATA_WIDTH - 1;

wire         din_sign  = din[MSB];
wire [W-2:0] din_data  = din[W-2:0];
wire [W-2:0] pad1      = { (W-1){1b1} };

always @(*) begin
    if (din_sign == 1b1) begin // negative data
            if (din_data == 0) begin // Max 
                dout = ~din;
            end
            else begin
                dout  = {1b0,((~din_data)+1b1)};
            end
    end
    else begin
            dout = din;
    end
end

endmodule

 

 
 
5. 语义上,对非-128的负数取反,直接把din全部参与运算即可,无需使用concat操作。同时可以省略pad1。
 
module ABS
#( 
    parameter    DATA_WIDTH = 8
)
(
    input        [DATA_WIDTH-1:0]            din,
    output reg   [DATA_WIDTH-1:0]            dout
);

localparam W   = DATA_WIDTH; 
localparam MSB = DATA_WIDTH - 1;

wire         din_sign  = din[MSB];
wire [W-2:0] din_data  = din[W-2:0];

always @(*) begin
    if (din_sign == 1b1) begin // negative data
            if (din_data == 0) begin // Max 
                dout = ~din;
            end
            else begin
                dout  = ~din + 1;
            end
    end
    else begin
            dout = din;
    end
end

endmodule

 

 
 
6. 形式上,module的实现中已经没有对parameter的使用。localparam MSB只被使用了一次。可以取消,直接使用W即可。甚至W也可以去掉,但保留也没有大碍,毕竟多次使用。
 
module ABS
#( 
    parameter    DATA_WIDTH = 8
)
(
    input        [DATA_WIDTH-1:0]            din,
    output reg   [DATA_WIDTH-1:0]            dout
);

localparam W   = DATA_WIDTH; 

wire         din_sign  = din[W-1];
wire [W-2:0] din_data  = din[W-2:0];

always @(*) begin
    if (din_sign == 1b1) begin // negative data
            if (din_data == 0) begin // Max 
                dout = ~din;
            end
            else begin
                dout  = ~din + 1;
            end
    end
    else begin
            dout = din;
    end
end

endmodule

 

 
 
7. ABS模块实现上,这里对-128的处理,只是一种方式。可以看到这种方式增加复杂度的同时,降低了模块的通用性。
 
这个策略需要在具体项目中做选择。这里不做过多讨论。

Verilog - ABS代码重构

标签:round   方式   项目   idt   多次   https   代码   去掉   tar   

原文地址:https://www.cnblogs.com/wjcdx/p/9813097.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!