Verilog 加法器和減法器(5)
阿新 • • 發佈:2018-12-08
前面二進位制加法運算,我們並沒有提運算元是有符號數,還是無符號數。其實前面的二進位制加法對於有符號數和無符號數都成立。比如前面的8位二進位制加法運算,第一張圖我們選radix是unsigned,表示無符號加法,第二張圖我們選radix是decimal,表示有符號數,從圖中可知結果都是正確的。對於有符號數來說,負數預設是補碼的形式存在。假設二進位制數是n位,則對於無符號數來說,表示範圍是0~(2^n) -1 ,對於有符號數,表示的範圍是-(2^(n-1))~2^(n-1) - 1
對於有符號數來說,通常還要知道加法結果資料是否溢位。有一種直觀的方法判斷結果是否溢位,就是如果兩個加數有相同的符號,但是它們的和與它們有不同的符號,則產生溢位。假設有n位有符號二進位制數x,y,它們的和為s,則它們和溢位判斷公式是 overflow = xn_1 &yn-1&~sn-1 + ~xn_1&~yn-1&sn-1
修改後的有符號數加法程式碼為:
module addern_signed(x, y, s, cout, overflow); parameter n=8; input [n-1:0] x; input [n-1:0] y; output reg[n-1:0] s; output reg cout; output reg overflow; reg [n:0] c; integer k; always @(x,y) begin c[0] = 1'b0; for(k = 0; k < n; k = k + 1) begin s[k] = x[k]^y[k]^c[k]; c[k+1] = (x[k]&y[k])|(x[k]&c[k])|(y[k]&c[k]); end cout = c[n]; overflow = (x[n-1]&y[n-1]&~s[n-1])|(~x[n-1]&~y[n-1]&s[n-1]); end endmodule
module addern_signed(x, y, s, cout, overflow); parameter n=8; input [n-1:0] x; input [n-1:0] y; output [n-1:0] s; output cout; output overflow; integer k; assign {cout, s} = x + y ; assign overflow = (x[n-1]&y[n-1]&~s[n-1])|(~x[n-1]&~y[n-1]&s[n-1]); endmodule
修改後的testbench檔案為:
`timescale 1ns/1ns `define clock_period 20 module addern_signed_tb; reg [7:0] x,y; wire cout; wire [7:0] s; reg clk; addern_signed #(.n(8)) addern_signed_0( .x(x), .y(y), .s(s), .cout(cout) ); initial clk = 0; always #(`clock_period/2) clk = ~clk; initial begin x = 0; repeat(20) #(`clock_period) x = $random; end initial begin y = 0; repeat(20) #(`clock_period) y = $random; end initial begin #(`clock_period*20) $stop; end endmodule
功能驗證的波形圖如下: