Verilog - ABS代码重构

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

从形式和语义两个层面,来扣一下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] == 1'b1) begin // negative data
          if (din[DATA_WIDTH-2:0] == {(DATA_WIDTH-1){1'b0}}) begin // Max
                dout = {1'b0,{(DATA_WIDTH-1){1'b1}}}; end
          else begin dout = {1'b0,((~din[DATA_WIDTH-2:0])+1'b1)}; 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] == 1'b1) begin // negative data
            if (din[W-2:0] == { (W-1){1'b0} }) begin // Max 
                dout = {1'b0,{(W-1){1'b1}}}; end
            else begin dout = {1'b0,((~din[W-2:0])+1'b1)}; 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){1'b0} };
wire [W-2:0] pad1      = { (W-1){1'b1} };

always @(*) begin
    if (din_sign == 1'b1) begin // negative data
            if (din_data == pad0) begin // Max 
                dout = {1'b0, pad1};
            end
            else begin dout = {1'b0,((~din_data)+1'b1)}; 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){1'b1} };

always @(*) begin
    if (din_sign == 1'b1) begin // negative data
            if (din_data == 0) begin // Max 
                dout = {1'b0, pad1};
            end
            else begin dout = {1'b0,((~din_data)+1'b1)}; 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){1'b1} };

always @(*) begin
    if (din_sign == 1'b1) begin // negative data
            if (din_data == 0) begin // Max 
                dout = ~din; end
            else begin dout = {1'b0,((~din_data)+1'b1)}; 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 == 1'b1) 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 == 1'b1) 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的处理,只是一种方式。能够看到这种方式增长复杂度的同时,下降了模块的通用性。
 
这个策略须要在具体项目中作选择。这里不作过多讨论。
相关文章
相关标签/搜索