Verilog 加法器和減法器 5

2021-09-07 20:40:55 字數 4335 閱讀 6240

前面二進位制加法運算,我們並沒有提運算元是有符號數,還是無符號數。其實前面的二進位制加法對於有符號數和無符號數都成立。比如前面的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]);

endcout = c[n];

overflow = (x[n-1]&y[n-1]&~s[n-1])|(~x[n-1]&~y[n-1]&s[n-1]);

endendmodule

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 = x + y ;

assign overflow = (x[n-1]&y[n-1]&~s[n-1])|(~x[n-1]&~y[n-1]&s[n-1]);

endmodule

修改後的testbenc**件為:

`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;

endinitial begin

y = 0;

repeat(20)

#(`clock_period) y = $random;

endinitial begin

#(`clock_period*20)

$stop;

endendmodule

功能驗證的波形圖如下:

對於有符號數的減法,我們也可以用加法來做,但是對於減數,我們要做以下變化,如果減數為正數,則變其為補碼表示的負數,如果其為補碼表示的負數,則把它轉化為正數。

assign y1 = y[n-1]?(~+1'b1):(~+1'b1);

module subn_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;

wire [n-1:0] y1;

reg [n:0] c;

integer k;

//y commplement, if y=0, to negative with commplement,if y=1, to positive number.

assign y1 = y[n-1]?(~+1'b1):(~+1'b1);

always @(x,y1) begin

c[0] = 1'b0;

for(k = 0; k < n; k = k + 1) begin

s[k] = x[k]^y1[k]^c[k];

c[k+1] = (x[k]&y1[k])|(x[k]&c[k])|(y1[k]&c[k]);

endcout = c[n];

overflow = (x[n-1]&y1[n-1]&~s[n-1])|(~x[n-1]&~y1[n-1]&s[n-1]);

endendmodule

module subn_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;

wire [n-1:0] y1;

integer k;

//y commplement, if y=0, to negative with commplement,if y=1, to positive number.

assign y1 = y[n-1]?(~+1'b1):(~+1'b1);

assign = x + y1 ;

assign overflow = (x[n-1]&y1[n-1]&~s[n-1])|(~x[n-1]&~y1[n-1]&s[n-1]);

endmodule

testbench**為:

`timescale 1ns/1ns

`define clock_period 20

module subn_signed_tb;

reg [7:0] x,y;

wire cout;

wire overflow;

wire [7:0] s;

reg clk;

subn_signed #(.n(8)) subn_signed_0(

.x(x),

.y(y),

.s(s),

.cout(cout),

.overflow(overflow)

);initial clk = 0;

always #(`clock_period/2) clk = ~clk;

initial begin

x = 0;

repeat(20)

#(`clock_period) x = $random;

endinitial begin

y = 0;

repeat(20)

#(`clock_period) y = $random;

endinitial begin

#(`clock_period*20)

$stop;

endendmodule

從功能驗證的波形圖中,我們可以看到見過是正確的。

4 利用邏輯門實現加法器和減法器

首先給大家分享乙個巨牛巨牛的人工智慧教程,是我無意中發現的。教程不僅零基礎,通俗易懂,而且非常風趣幽默,還時不時有內涵段子,像看 一樣,哈哈 我正在學習中,覺得太牛了,所以分享給大家!點這裡可以跳轉到教程 了解了門,我們就可以做一些實際應用了,計算機的主要目的是計算,而門可以用於計算,所以可以說計算...

verilog學習記(加法器)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!程式語言,光看書其實作用不大的,關鍵還需要自己進行實踐。看書的時候,你覺得自己明白了 弄懂了,等到用modelsim實踐的時候還是會出現這樣那樣的問題。因此,還是希望自己能夠不斷地訓練和練習,這樣可以達到熟能生巧的程度。就今天的加法器來說,其實內容...

序列加法器 並行加法器 超前進製加法器

1.序列加法器 序列加法器即加法器執行位序列行操作,利用多個時鐘週期完成一次加法運算,即輸入運算元和輸出結果方式為隨時鐘序列輸入 輸出。位並行加法器速度高,但是占用資源多。在許多實際應用中並不需要這樣高的速度,而是希望減少硬體資源佔用率,這時就可以使用位序列加法器。在序列加法器中,只有乙個全加器,資...