blob: 09ba0c44a90f12631001639bd4c9de8eaf517841 [file] [log] [blame]
// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 09/13/2021 3:05:18 PM
// Design Name:
// Module Name: iki_bit_adimli_bolucu
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module iki_bit_adimli_bolucu(
input [31:0] a_g,
input [31:0] b_g,
input istek,
input isaretli,
input overflow,
input divbyzero,
input clk,
output [31:0] bolum,
output [31:0] kalan,
output reg bitti=0
);
/*
İlk sayı sabit kalırken ikinci sayıyı 31 birim sola kaydırıyoruz kısaca 2^31 ile çarpmış oluyoruz.
Daha sonra ikinci sayıyı birinciden çıkarıyoruz. Çıkardığımızda negatif bir sayı çıkıyorsa o çarpım içinde yok demektir.
Var ise bölümü o basamaktaki değer bir oluyor ve ilk sayı yerine artık çıkarılmış halini kullanıyoruz.
Tek saat dönümü içinde iki bit iki bit ilerlemeli olduğu için bir kaydırılmış hali ile yine bir çıkarma ve kontrol işlemi yapıyoruz.
Negatif sayılar alınırken positif halleriyle alınıyor ve kalansızsa sadece sonucu negatife çeviriyoruz.
Kalan var ise sonuç negatifinin bir eksiği ve kalan ikinci sayıdan kalanın çıkarılması ile bulunuyor.
*/
localparam EVET = 1'b1;
localparam HAYIR = 1'b0;
// bölme işlemine 2^31 sayısıyla başlıyor
localparam BOLME_BASLANGIC = 32'b1000_0000_0000_0000_0000_0000_0000_0000;
reg [31:0] A, A_next;
reg [63:0] B, B_next;
reg [31:0] bolum, bolum_next;
reg [31:0] kalan, kalan_next;
// o anda hangi basamakta olduğu değeri, ikinci de ikinci çıkarma işlemi için
reg [31:0] bolme_basamagi, bolme_basamagi_next = BOLME_BASLANGIC;
wire [31:0] ikinci_bolme_basamagi = {1'b0, bolme_basamagi[31:1]};
reg hesaplaniyor = HAYIR, hesaplaniyor_next = HAYIR;
reg sonuc_ver = HAYIR, sonuc_ver_next = HAYIR;
reg bitti_next = 0;
wire A_negatif_mi = isaretli & a_g[31];
wire B_negatif_mi = isaretli & b_g[31];
wire sonuc_negatif_mi = A_negatif_mi ^ B_negatif_mi;
// sayının çıkarıldığı yer [32:0] olması bazı taşma durumları için
wire [32:0] ilk_cikarma_sonucu = A - B[31:0];
wire ilk_cikarma_sonucu_negatif_mi = ilk_cikarma_sonucu[32];
wire ilk_cikarma_b_de_tasma_var_mi = |B[63:32];
// eğer çıkarttığımızda pozitif bir sayı elde ediyorsak çıkarma işlemini yapmalıyız
wire ilk_cikarmayi_yap = ~ (ilk_cikarma_sonucu_negatif_mi | ilk_cikarma_b_de_tasma_var_mi);
// ilk çıkartmadan sonraki değer
wire [31:0] A_ilk_cikarma_sonrasi = ( ilk_cikarmayi_yap ? ilk_cikarma_sonucu[31:0] : A );
// ikinci çıkartmada ikinci sayının bir kaydırılmış hali ve ona göre taşma sonucuna bakıyoruz
wire [32:0] ikinci_cikarma_sonucu = A_ilk_cikarma_sonrasi - B[32:1];
wire ikinci_cikarma_sonucu_negatif_mi = ikinci_cikarma_sonucu[32];
wire ikinci_cikarma_b_de_tasma_var_mi = |B[63:33];
wire ikinci_cikarmayi_yap = ~ (ikinci_cikarma_sonucu_negatif_mi | ikinci_cikarma_b_de_tasma_var_mi);
// ikinci çıkartmanın durumuna göre A'nın yeni durumunu atıyoruz
wire [31:0] A_ikinci_cikarma_sonrasi = ( ikinci_cikarmayi_yap ? ikinci_cikarma_sonucu[31:0] : A_ilk_cikarma_sonrasi );
always@ (*) begin
bitti_next = HAYIR;
hesaplaniyor_next = hesaplaniyor;
A_next = A;
B_next = B;
bolme_basamagi_next = bolme_basamagi;
sonuc_ver_next = sonuc_ver;
kalan_next = kalan;
bolum_next = bolum;
if (hesaplaniyor) begin
hesaplaniyor_next = ~bolme_basamagi[1];
sonuc_ver_next = bolme_basamagi[1]; // iki kaydıra kaydıra bitmeden bir önceki adımda olan bir
bitti_next = HAYIR;
A_next = A_ikinci_cikarma_sonrasi; // ilki hesaplanan çıkarma sonucunu alıyor
B_next = B >> 2; // ikinci sayıyı iki birim sağa kaydırıyoruz
bolme_basamagi_next = bolme_basamagi >> 2; // bölme basamağı da beraber sola kayıyor
case ( {ilk_cikarmayi_yap, ikinci_cikarmayi_yap} ) // çıkarma işlemini yapıp yapmamamıza göre o basamakları bölüme ekliyoruz
2'b00:
bolum_next = bolum;
2'b01:
bolum_next = bolum ^ ikinci_bolme_basamagi;
2'b10:
bolum_next = bolum ^ bolme_basamagi;
2'b11:
bolum_next = bolum ^ bolme_basamagi ^ ikinci_bolme_basamagi;
endcase
end
else if(sonuc_ver) begin // çıkartma işlemlerinden sonraki negatif hesaplama kısmı
hesaplaniyor_next = HAYIR;
sonuc_ver_next = HAYIR;
bitti_next = EVET;
if (divbyzero) begin
bolum_next = 32'hffffffff;
kalan_next = a_g;
end else if (overflow && isaretli) begin
bolum_next = 32'h80000000;
kalan_next = 32'h0;
end
else begin
bolum_next = sonuc_negatif_mi? -bolum: bolum;
kalan_next = A_negatif_mi? -A: A;
end
end
else if (istek) begin // yeni istek
hesaplaniyor_next = EVET;
sonuc_ver_next = HAYIR;
bitti_next = HAYIR;
A_next = ( A_negatif_mi ? -a_g : a_g ); // A'yı pozitif olarak al
B_next = ( B_negatif_mi ? {1'd0, -b_g, 31'd0} : {1'd0, b_g, 31'd0} ); // B 2^31 ile çarpılmış hali ile başlat
bolme_basamagi_next = BOLME_BASLANGIC; // bölme basamağını başlangıca sıfırla
kalan_next = 32'd0;
bolum_next = 32'd0;
end
end
always@ (posedge clk) begin
A <= A_next;
B <= B_next;
kalan <= kalan_next;
bolum <= bolum_next;
bitti <= bitti_next;
hesaplaniyor <= hesaplaniyor_next;
sonuc_ver <= sonuc_ver_next;
bolme_basamagi <= bolme_basamagi_next;
end
endmodule