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的處理,只是一種方式。能夠看到這種方式增長複雜度的同時,下降了模塊的通用性。
 
這個策略須要在具體項目中作選擇。這裏不作過多討論。
相關文章
相關標籤/搜索