blob: 9df409a3f82dc9007bf38f7a50a43c29078a34a1 [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
`include "sabitler.vh"
`include "mikroislem.vh"
module getir_coz
(
input clk_g ,
input rst_g ,
// Buyruk bellegi <-> GetirCoz
input bb_buy_gecerli_g ,
input [`BUYRUK_BIT-1:0] bb_buy_g ,
input [`BB_ADRES_BIT-1:0] bb_buy_ps_g ,
output gc_hazir_c ,
// GetirCoz <-> YazmacOkuYurut
input gc_duraklat_g ,
input gc_bosalt_g ,
output [`UIS_BIT-1:0] gc_uis_c ,
// GetirCoz <-> DDY birimi
output gc_odd_c ,
output [`BB_ADRES_BIT-1:0] gc_odd_ps_c
);
// ===================================================================================================
// ========================================MODUL TANIMLAMASI==========================================
// ===================================================================================================
// Getirilen buyruk
wire [`BUYRUK_BIT-1:0] buyruk_w = bb_buy_g ;
// Buyruk cozmek icin gereken sinyaller
wire [`BUY_ISKODU_BIT-1:0] iskodu_w = buyruk_w[`BUY_ISKODU +: `BUY_ISKODU_BIT] ;
wire [`BUY_HY_BIT-1:0] hy_w = buyruk_w[`BUY_HY +: `BUY_HY_BIT] ;
wire [`BUY_KY1_BIT-1:0] ky1_w = buyruk_w[`BUY_KY1 +: `BUY_KY1_BIT] ;
wire [`BUY_KY2_BIT-1:0] ky2_w = buyruk_w[`BUY_KY2 +: `BUY_KY2_BIT] ;
wire [`BUY_F7_BIT-1:0] f7_w = buyruk_w[`BUY_F7 +: `BUY_F7_BIT] ;
wire [`BUY_F3_BIT-1:0] f3_w = buyruk_w[`BUY_F3 +: `BUY_F3_BIT] ;
// Mikroislem sinyalleri
reg gecerli_r ;
reg [`YURUT_KODU_BIT - 1: 0] yurut_kodu_r ;
reg [`ISLEV_KODU_BIT - 1: 0] islev_kodu_r ;
reg [`IS1_SEC_BIT - 1: 0] is1_sec_r ;
reg [`IS2_SEC_BIT - 1: 0] is2_sec_r ;
reg [`ANLIK_DEGER_BIT - 1: 0] anlik_deger_r ;
reg yukle_buyrugu_r ;
reg kaydet_buyrugu_r ;
reg fence_buyrugu_r ;
reg bellek_turu_w_r ;
reg bellek_turu_hw_r ;
reg bellek_isaretli_r ;
reg bellek_turu_b_r ;
reg [`PS_BIT - 1: 0] ps_r ;
reg [`UIS_BIT - 1: 0] gc_uis_r ;
reg [`UIS_BIT - 1: 0] yazmac_gc_uis_r ;
// Comb. devrede hesaplanan sinyaller
reg [31:0] i_anlik ;
reg [31:0] u_anlik ;
reg [31:0] j_anlik ;
reg [31:0] s_anlik ;
reg [31:0] b_anlik ;
reg yanlis_buyruk_r ;
// denetim sayilabilecek sinyaller
assign gc_hazir_c = !gc_duraklat_g;
assign gc_uis_c = yazmac_gc_uis_r ;
assign gc_odd_c = gecerli_r && yanlis_buyruk_r ;
assign gc_odd_ps_c = ps_r ;
// Cozmek icin kocaman bir if else/switch agaci koyacagiz.
// Ataberk: Raven-SoC'deki kod da bu (^) sekilde.
always @* begin
gc_uis_r = yazmac_gc_uis_r ;
// Tum reglerin degerlerini belirle, latch olusturmak istemiyoruz.
gecerli_r = 0 ;
yurut_kodu_r = 0 ;
islev_kodu_r = 0 ;
is1_sec_r = 0 ;
is2_sec_r = 0 ;
anlik_deger_r = 0 ;
yukle_buyrugu_r = 0 ;
kaydet_buyrugu_r = 0 ;
fence_buyrugu_r = 0 ;
bellek_turu_w_r = 0 ;
bellek_turu_hw_r = 0 ;
bellek_turu_b_r = 0 ;
bellek_isaretli_r = 0 ;
ps_r = bb_buy_ps_g ;
// -------------------------- anlik deger hesapla --------------------------
// TODO: asagidakileri kontrol et
i_anlik = buyruk_w[`I_ANLIK_ISARET] ? {{20{1'b1}},
buyruk_w[`I_ANLIK+:`I_ANLIK_BIT]}
:
{{20{1'b0}},
buyruk_w[`I_ANLIK+:`I_ANLIK_BIT]};
u_anlik = buyruk_w[`U_ANLIK+:`U_ANLIK_BIT];
// J, S ve B tipi anliklar icin tum indisleri `define'lamak kafa
// karistirici olabilir, o yuzden yoklar
// Asagidaki bit alanlari icin riscv tanimlamasina bakabilirsiniz.
j_anlik = { (buyruk_w[19] ? {11{1'b1}} : {11{1'b0}}),
buyruk_w[19],
buyruk_w[12+:8],
buyruk_w[20],
buyruk_w[21+:10],
1'b0
};
s_anlik = { (buyruk_w[31] ? {20{1'b1}} : {20{1'b0}}),
buyruk_w[25+:7],
buyruk_w[7+:5]
};
b_anlik = { (buyruk_w[31] ? {19{1'b1}} : {19{1'b0}}),
buyruk_w[31],
buyruk_w[7],
buyruk_w[25+:6],
buyruk_w[8+:4],
1'b0
};
// --------------------------- islec sec -----------------------------------
if (iskodu_w == 7'h3 || iskodu_w == 7'h67 || iskodu_w == 7'h13) begin
is1_sec_r = `IS1_SEC_KY1;
is2_sec_r = `IS2_SEC_AD;
anlik_deger_r = i_anlik;
end
if (iskodu_w == 7'h37) begin
is1_sec_r = `IS1_SEC_0;
is2_sec_r = `IS2_SEC_AD;
anlik_deger_r = u_anlik;
end
if (iskodu_w == 7'h17) begin
is1_sec_r = `IS1_SEC_PS;
is2_sec_r = `IS2_SEC_AD;
anlik_deger_r = u_anlik;
end
if (iskodu_w == 7'h6f) begin
is1_sec_r = `IS1_SEC_PS;
is2_sec_r = `IS2_SEC_AD;
anlik_deger_r = j_anlik;
end
if (iskodu_w == 7'h63) begin
is1_sec_r = `IS1_SEC_KY1;
is2_sec_r = `IS2_SEC_KY2;
anlik_deger_r = b_anlik;
end
if (iskodu_w == 7'h23) begin
is1_sec_r = `IS1_SEC_KY1;
is2_sec_r = `IS2_SEC_KY2;
anlik_deger_r = s_anlik;
end
if (iskodu_w == 7'h33) begin
is1_sec_r = `IS1_SEC_KY1;
is2_sec_r = `IS2_SEC_KY2;
end
if (iskodu_w == 7'h73) begin
is1_sec_r = `IS1_SEC_KY1;
is2_sec_r = `IS2_SEC_AD;
end
// -------------------- yurut ve islev kodu belirle ------------------------
// TODO: hint parallel case
case (iskodu_w)
7'h37: begin // LUI
yurut_kodu_r = `YURUT_KODU_AMB;
islev_kodu_r = `LUI;
end
7'h17: begin // AUIPC
yurut_kodu_r = `YURUT_KODU_AMB;
islev_kodu_r = `AUIPC;
end
7'h13: begin
yurut_kodu_r = `YURUT_KODU_AMB;
case (f3_w)
3'h0: islev_kodu_r = `ADD;
3'h1: islev_kodu_r = `SLL;
3'h2: islev_kodu_r = `SLT;
3'h3: islev_kodu_r = `SLTU;
3'h4: islev_kodu_r = `XOR;
3'h5: islev_kodu_r = f7_w[5] ? `SRA : `SRL;
3'h6: islev_kodu_r = `OR;
3'h7: islev_kodu_r = `AND;
endcase
end
7'h33: begin
if (f7_w[0]) begin
yurut_kodu_r = f3_w < 3'h4 ? `YURUT_KODU_TCB : `YURUT_KODU_TBB;
case (f3_w)
3'h0: islev_kodu_r = `MUL;
3'h1: islev_kodu_r = `MULH;
3'h2: islev_kodu_r = `MULHSU;
3'h3: islev_kodu_r = `MULHU;
3'h4: islev_kodu_r = `DIV;
3'h5: islev_kodu_r = `DIVU;
3'h6: islev_kodu_r = `REM;
3'h7: islev_kodu_r = `REMU;
endcase
end
else begin
yurut_kodu_r = `YURUT_KODU_AMB;
case (f3_w)
3'h0: islev_kodu_r = f7_w[5] ? `SUB : `ADD;
3'h1: islev_kodu_r = `SLL;
3'h2: islev_kodu_r = `SLT;
3'h3: islev_kodu_r = `SLTU;
3'h4: islev_kodu_r = `XOR;
3'h5: islev_kodu_r = f7_w[5] ? `SRA : `SRL;
3'h6: islev_kodu_r = `OR;
3'h7: islev_kodu_r = `AND;
endcase
end
end
7'h6f: begin
yurut_kodu_r = `YURUT_KODU_DB;
islev_kodu_r = `JAL;
end
7'h67: begin
yurut_kodu_r = `YURUT_KODU_DB;
islev_kodu_r = `JALR;
end
7'h63: begin
yurut_kodu_r = `YURUT_KODU_DB;
case (f3_w)
3'h0: islev_kodu_r = `BEQ;
3'h1: islev_kodu_r = `BNE;
3'h4: islev_kodu_r = `BLT;
3'h5: islev_kodu_r = `BGE;
3'h6: islev_kodu_r = `BLTU;
3'h7: islev_kodu_r = `BGEU;
endcase
end
7'h03: begin
yurut_kodu_r = `YURUT_KODU_BIB;
yukle_buyrugu_r = 1'b1;
case (f3_w)
3'h0: begin
islev_kodu_r = `LB;
bellek_turu_b_r = 1'b1;
bellek_isaretli_r = 1'b1;
end
3'h1: begin
islev_kodu_r = `LH;
bellek_turu_hw_r = 1'b1;
bellek_isaretli_r = 1'b1;
end
3'h2: begin
islev_kodu_r = `LW;
bellek_turu_w_r = 1'b1;
bellek_isaretli_r = 1'b1;
end
3'h4: begin
islev_kodu_r = `LBU;
bellek_turu_b_r = 1'b1;
end
3'h5: begin
islev_kodu_r = `LHU;
bellek_turu_hw_r = 1'b1;
end
endcase
end
7'h23: begin
yurut_kodu_r = `YURUT_KODU_BIB;
kaydet_buyrugu_r = 1'b1;
case (f3_w)
3'h0: begin
islev_kodu_r = `SB;
bellek_turu_b_r = 1'b1;
end
3'h1: begin
islev_kodu_r = `SH;
bellek_turu_hw_r = 1'b1;
end
3'h2: begin
islev_kodu_r = `SW;
bellek_turu_w_r = 1'b1;
end
endcase
end
7'h0f: begin
yurut_kodu_r = `YURUT_KODU_BIB;
fence_buyrugu_r = 1'b1;
if (f3_w == 0) islev_kodu_r = `FENCE;
end
7'h73: begin
// CSR
yurut_kodu_r = `YURUT_KODU_CSR;
if (f3_w == 0) begin
yurut_kodu_r = `YURUT_KODU_SISTEM;
if (ky2_w == 'h1) islev_kodu_r = `EBREAK;
if (ky2_w == 'h0) islev_kodu_r = `ECALL;
if (ky2_w == 'h2) begin
if (f7_w == 'h0) islev_kodu_r = `URET;
if (f7_w == 'h18) islev_kodu_r = `MRET;
end
end
if (f3_w == 'h1) islev_kodu_r = `CSRRW;
if (f3_w == 'h2) islev_kodu_r = `CSRRS;
if (f3_w == 'h3) islev_kodu_r = `CSRRC;
if (f3_w == 'h5) islev_kodu_r = `CSRRWI;
if (f3_w == 'h6) islev_kodu_r = `CSRRSI;
if (f3_w == 'h7) islev_kodu_r = `CSRRCI;
end
endcase
// ------------------------------ denetim ----------------------------------
// ancak ve ancak islev kodu belirlenmediyse
// yanlis buyruk oddsi olusur
yanlis_buyruk_r = islev_kodu_r == 0 ? 1'b1 : 1'b0;
gecerli_r = bb_buy_gecerli_g && ~gc_bosalt_g;
gc_uis_r[`GECERLI] = gecerli_r && ~yanlis_buyruk_r;
// TODO: if icinde olmasi davranisi degistiriyor mu?
if (gecerli_r) begin
// mikroislem sinyallerini bagla
// TODO: DDB alanlarini doldur
gc_uis_r[`YURUT_KODU+:`YURUT_KODU_BIT] = yurut_kodu_r;
gc_uis_r[`ISLEV_KODU+:`ISLEV_KODU_BIT] = islev_kodu_r;
gc_uis_r[`IS1_SEC+:`IS1_SEC_BIT] = is1_sec_r;
gc_uis_r[`IS2_SEC+:`IS2_SEC_BIT] = is2_sec_r;
gc_uis_r[`ANLIK_DEGER+:`ANLIK_DEGER_BIT] = anlik_deger_r;
gc_uis_r[`KY1+:`KY1_BIT] = ky1_w;
gc_uis_r[`KY2+:`KY2_BIT] = ky2_w;
gc_uis_r[`YUKLE_BUYRUGU] = yukle_buyrugu_r;
gc_uis_r[`KAYDET_BUYRUGU] = kaydet_buyrugu_r;
gc_uis_r[`FENCE_BUYRUGU] = fence_buyrugu_r;
gc_uis_r[`BELLEK_TURU_W] = bellek_turu_w_r;
gc_uis_r[`BELLEK_TURU_HW] = bellek_turu_hw_r;
gc_uis_r[`BELLEK_TURU_B] = bellek_turu_b_r;
gc_uis_r[`BELLEK_ISARETLI] = bellek_isaretli_r;
gc_uis_r[`HY+:`HY_BIT] = hy_w;
gc_uis_r[`PS+:`PS_BIT] = ps_r;
gc_uis_r[`DDY_ADRES+:`DDY_ADRES_BIT] = i_anlik;
gc_uis_r[`DDY_ANLIK+:`DDY_ANLIK_BIT] = ky1_w;
end
end
always @(posedge clk_g) begin
if (rst_g) begin
yazmac_gc_uis_r[`GECERLI] <= 1'b0;
end
else begin
if (gc_duraklat_g) begin
yazmac_gc_uis_r <= yazmac_gc_uis_r;
end
else begin
yazmac_gc_uis_r <= gc_uis_r;
end
end
end
endmodule