OpenCores
URL https://opencores.org/ocsvn/steelcore/steelcore/trunk

Subversion Repositories steelcore

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/steelcore/trunk/bench/tb_alu.v
0,0 → 1,361
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 03.04.2020 18:35:35
// Module Name: tb_alu
// Project Name: Steel Core
// Description: RISC-V Steel Core 32-bit ALU testbench
//
// Dependencies: alu.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
module tb_alu();
 
reg [31:0] OP_1;
reg [31:0] OP_2;
reg [3:0] OPCODE;
wire [31:0] RESULT;
alu dut(
 
.OP_1( OP_1),
.OP_2( OP_2),
.OPCODE( OPCODE),
.RESULT( RESULT)
);
reg [31:0] expected_result;
integer i;
initial
begin
$display("Testing ALU...");
$display("Executing extreme values test for ADD and SUB operations...");
OP_1 = 32'h00000001; // decimal = 1
OP_2 = 32'h7FFFFFFF; // the biggest positive decimal
OPCODE = `ALU_ADD;
expected_result = 32'h80000000; // the lowest negative decimal
#10;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
OP_1 = 32'h80000000; // the lowest negative decimal
OP_2 = 32'h00000001; // decimal = 1
OPCODE = `ALU_SUB;
expected_result = 32'h7FFFFFFF; // the biggest positive decimal
#10;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
OP_1 = 32'h00000000; // decimal = 0
OP_2 = 32'h00000001; // decimal = 1
OPCODE = `ALU_SUB;
expected_result = 32'hFFFFFFFF; // decimal = -1
#10;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
OP_1 = 32'hFFFFFFFF; // decimal = -1
OP_2 = 32'h00000001; // decimal = 1
OPCODE = `ALU_ADD;
expected_result = 32'h00000000; // decimal = 0
#10;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
OP_1 = 32'h00000001; // decimal = 1
OP_2 = 32'hFFFFFFFF; // decimal = -1
OPCODE = `ALU_ADD;
expected_result = 32'h00000000; // decimal = 0
#10;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
OP_1 = 32'h00000001; // decimal = 1
OP_2 = 32'hFFFFFFFF; // decimal = -1
OPCODE = `ALU_SUB;
expected_result = 32'h00000002; // decimal = 2
#10;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
OP_1 = 32'hFFFFFFFF; // decimal = -1
OP_2 = 32'h00000001; // decimal = 1
OPCODE = `ALU_SUB;
expected_result = 32'hFFFFFFFE; // decimal = -2
#10;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Test successful.");
$display("Testing 10000 pseudorandom values for all operations...");
$display("Testing ADD operation...");
OPCODE = `ALU_ADD;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = OP_1 + OP_2;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("ADD operation successfully tested.");
$display("Testing SUB operation...");
OPCODE = `ALU_SUB;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = OP_1 - OP_2;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("SUB operation successfully tested.");
$display("Testing SLTU operation...");
OPCODE = `ALU_SLTU;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = {31'b0, OP_1 < OP_2};
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("SLTU operation successfully tested.");
$display("Testing SLT operation...");
OPCODE = `ALU_SLT;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = {31'b0, $signed(OP_1) < $signed(OP_2)};
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("SLT operation successfully tested.");
$display("Testing AND operation...");
OPCODE = `ALU_AND;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = OP_1 & OP_2;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("AND operation successfully tested.");
$display("Testing OR operation...");
OPCODE = `ALU_OR;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = OP_1 | OP_2;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("OR operation successfully tested.");
$display("Testing XOR operation...");
OPCODE = `ALU_XOR;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = OP_1 ^ OP_2;
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("XOR operation successfully tested.");
$display("Testing SLL operation...");
OPCODE = `ALU_SLL;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = OP_1 << OP_2[4:0];
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("SLL operation successfully tested.");
$display("Testing SRL operation...");
OPCODE = `ALU_SRL;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = OP_1 >> OP_2[4:0];
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("SRL operation successfully tested.");
$display("Testing SRA operation...");
OPCODE = `ALU_SRA;
for(i = 0; i < 10000; i=i+1)
begin
OP_1 = $random;
OP_2 = $random;
#10;
expected_result = $signed(OP_1) >>> OP_2[4:0];
if (RESULT != expected_result)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("SRA operation successfully tested.");
$display("All ALU operations successfully tested for pseudorandom values.");
$display("ALU successfully tested.");
end
 
endmodule
/steelcore/trunk/bench/tb_branch_unit.v
0,0 → 1,520
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 18:45:28
// Module Name: tb_branch_unit
// Project Name: Steel Core
// Description: RISC-V Steel Core Branch Decision Unit testbench
//
// Dependencies: branch_unit.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
module tb_branch_unit();
reg [6:2] OPCODE_6_TO_2;
reg [31:0] RS1;
reg [31:0] RS2;
reg [2:0] FUNCT3;
wire BRANCH_TAKEN;
integer i = 0;
reg signed [31:0] rs1s;
reg signed [31:0] rs2s;
branch_unit dut(
.OPCODE_6_TO_2(OPCODE_6_TO_2),
.RS1(RS1),
.RS2(RS2),
.FUNCT3(FUNCT3),
.BRANCH_TAKEN(BRANCH_TAKEN)
);
initial
begin
$display("Testing Branch Unit...");
$display("Testing branch comparator unit for BEQ.");
FUNCT3 = 3'b000;
OPCODE_6_TO_2 = `OPCODE_BRANCH;
for(i = 0; i < 10000; i=i+1)
begin
RS1 = $random;
RS2 = $random;
#10;
if(RS1 == RS2 && BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
if(RS1 != RS2 && BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
end
RS1 = $random;
RS2 = RS1;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
$display("Branch comparator works fine for BEQ.");
$display("Testing branch comparator unit for BNE.");
FUNCT3 = 3'b001;
OPCODE_6_TO_2 = `OPCODE_BRANCH;
for(i = 0; i < 10000; i=i+1)
begin
RS1 = $random;
RS2 = $random;
#10;
if(RS1 != RS2 && BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
if(RS1 == RS2 && BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
end
RS1 = $random;
RS2 = RS1;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
$display("Branch comparator works fine for BNE.");
$display("Testing branch comparator unit for BLT.");
FUNCT3 = 3'b100;
OPCODE_6_TO_2 = `OPCODE_BRANCH;
for(i = 0; i < 10000; i=i+1)
begin
RS1 = $random;
RS2 = $random;
rs1s = RS1;
rs2s = RS2;
#10;
if(rs1s < rs2s && BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
if(rs1s >= rs2s && BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b11111111_11111111_11111111_11111100;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b00000000_00000000_00000000_00001000;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
$display("Branch comparator works fine for BLT.");
$display("Testing branch comparator unit for BGE.");
FUNCT3 = 3'b101;
OPCODE_6_TO_2 = `OPCODE_BRANCH;
for(i = 0; i < 10000; i=i+1)
begin
RS1 = $random;
RS2 = $random;
rs1s = RS1;
rs2s = RS2;
#10;
if(rs1s >= rs2s && BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
if(rs1s < rs2s && BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b11111111_11111111_11111111_11111100;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b00000000_00000000_00000000_00001000;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
$display("Branch comparator works fine for BGE.");
$display("Testing branch comparator unit for BLTU.");
FUNCT3 = 3'b110;
OPCODE_6_TO_2 = `OPCODE_BRANCH;
for(i = 0; i < 10000; i=i+1)
begin
RS1 = $random;
RS2 = $random;
#10;
if(RS1 < RS2 && BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
if(RS1 >= RS2 && BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b11111111_11111111_11111111_11111100;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b00000000_00000000_00000000_00001000;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
$display("Branch comparator works fine for BLTU.");
$display("Testing branch comparator unit for BGEU.");
FUNCT3 = 3'b111;
OPCODE_6_TO_2 = `OPCODE_BRANCH;
for(i = 0; i < 10000; i=i+1)
begin
RS1 = $random;
RS2 = $random;
#10;
if(RS1 >= RS2 && BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
if(RS1 < RS2 && BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b11111111_11111111_11111111_11111100;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b00000000_00000000_00000000_00001000;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b11111111_11111111_11111111_11111000;
RS2 = 32'b00000000_00000000_00000000_00001100;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
RS1 = 32'b00000000_00000000_00000000_00001100;
RS2 = 32'b11111111_11111111_11111111_11111000;
#10;
if(BRANCH_TAKEN != 1'b0)
begin
$display("FAIL. Expected BRANCH_TAKEN = 0.");
$finish;
end
$display("Branch comparator works fine for BGEU.");
$display("Testing branch comparator unit for JAL.");
FUNCT3 = 3'bxxx;
OPCODE_6_TO_2 = `OPCODE_JAL;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
$display("Branch comparator works fine for JAL.");
$display("Testing branch comparator unit for JALR.");
FUNCT3 = 3'bxxx;
OPCODE_6_TO_2 = `OPCODE_JALR;
#10;
if(BRANCH_TAKEN != 1'b1)
begin
$display("FAIL. Expected BRANCH_TAKEN = 1.");
$finish;
end
$display("Branch comparator works fine for JALR.");
$display("Branch Unit successfully tested.");
end
endmodule
/steelcore/trunk/bench/tb_control_unit.v
0,0 → 1,1463
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 03.04.2020 18:35:35
// Module Name: tb_control_unit
// Project Name: Steel Core
// Description: RISC-V Steel Core Control Unit testbench
//
// Dependencies: control_unit.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
 
module tb_control_unit();
 
reg [6:0] OPCODE;
reg FUNCT7_5;
reg [2:0] FUNCT3;
reg [1:0] IADDER_OUT_1_TO_0;
wire [3:0] ALU_OPCODE;
wire MEM_WR_REQ;
wire [1:0] LOAD_SIZE;
wire LOAD_UNSIGNED;
wire ALU_SRC;
wire IADDER_SRC;
wire CSR_WR_EN;
wire RF_WR_EN;
wire [2:0] WB_MUX_SEL;
wire [2:0] IMM_TYPE;
wire [2:0] CSR_OP;
wire ILLEGAL_INSTR;
wire MISALIGNED_LOAD;
wire MISALIGNED_STORE;
control_unit dut(
.OPCODE(OPCODE),
.FUNCT7_5(FUNCT7_5),
.FUNCT3(FUNCT3),
.IADDER_OUT_1_TO_0(IADDER_OUT_1_TO_0),
.ALU_OPCODE(ALU_OPCODE),
.MEM_WR_REQ(MEM_WR_REQ),
.LOAD_SIZE(LOAD_SIZE),
.LOAD_UNSIGNED(LOAD_UNSIGNED),
.ALU_SRC(ALU_SRC),
.IADDER_SRC(IADDER_SRC),
.CSR_WR_EN(CSR_WR_EN),
.RF_WR_EN(RF_WR_EN),
.WB_MUX_SEL(WB_MUX_SEL),
.IMM_TYPE(IMM_TYPE),
.CSR_OP(CSR_OP),
.ILLEGAL_INSTR(ILLEGAL_INSTR),
.MISALIGNED_LOAD(MISALIGNED_LOAD),
.MISALIGNED_STORE(MISALIGNED_STORE)
);
reg [4:0] opcode_6_to_2;
reg [6:0] funct7;
initial
begin
$display("Testing Control Unit...");
$display("Testing OP opcode control signals...");
 
$display("Testing signals common to all instructions...");
opcode_6_to_2 = `OPCODE_OP;
OPCODE = {opcode_6_to_2, 2'b11};
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ALU_SRC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WB_MUX_SEL != `WB_ALU)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("OP control signals common to all instructions successfully tested.");
$display("Testing ALU_OPCODE signal generation for OP opcode...");
funct7 = `FUNCT7_ADD;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_ADD;
#10;
if(ALU_OPCODE != `ALU_ADD)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for ADD... OK.");
funct7 = `FUNCT7_SUB;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SUB;
#10;
if(ALU_OPCODE != `ALU_SUB)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SUB... OK.");
funct7 = `FUNCT7_SLT;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SLT;
#10;
if(ALU_OPCODE != `ALU_SLT)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SLT... OK.");
funct7 = `FUNCT7_SLTU;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SLTU;
#10;
if(ALU_OPCODE != `ALU_SLTU)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SLTU... OK.");
funct7 = `FUNCT7_AND;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_AND;
#10;
if(ALU_OPCODE != `ALU_AND)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for AND... OK.");
funct7 = `FUNCT7_OR;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_OR;
#10;
if(ALU_OPCODE != `ALU_OR)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for OR... OK.");
funct7 = `FUNCT7_XOR;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_XOR;
#10;
if(ALU_OPCODE != `ALU_XOR)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for XOR... OK.");
funct7 = `FUNCT7_SLL;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SLL;
#10;
if(ALU_OPCODE != `ALU_SLL)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SLL... OK.");
funct7 = `FUNCT7_SRL;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SRL;
#10;
if(ALU_OPCODE != `ALU_SRL)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SRL... OK.");
funct7 = `FUNCT7_SRA;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SRA;
#10;
if(ALU_OPCODE != `ALU_SRA)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SRA... OK.");
$display("ALU_OPCODE signal generation for OP opcode successfully tested.");
$display("OP control signals successfully tested.");
$display("Testing OP-IMM opcode control signals...");
$display("Testing signals common to all instructions...");
opcode_6_to_2 = `OPCODE_OP_IMM;
OPCODE = {opcode_6_to_2, 2'b11};
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ALU_SRC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WB_MUX_SEL != `WB_ALU)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `I_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("OP-IMM control signals common to all instructions successfully tested.");
$display("Testing ALU_OPCODE signal generation for OP-IMM opcode...");
FUNCT7_5 = 1'b0;
FUNCT3 = `FUNCT3_ADD;
#10;
if(ALU_OPCODE != `ALU_ADD)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT7_5 = 1'b1;
FUNCT3 = `FUNCT3_ADD;
#10;
if(ALU_OPCODE != `ALU_ADD)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for ADDI... OK.");
FUNCT7_5 = 1'b0;
FUNCT3 = `FUNCT3_SLT;
#10;
if(ALU_OPCODE != `ALU_SLT)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT7_5 = 1'b1;
FUNCT3 = `FUNCT3_SLT;
#10;
if(ALU_OPCODE != `ALU_SLT)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SLTI... OK.");
FUNCT7_5 = 1'b0;
FUNCT3 = `FUNCT3_SLTU;
#10;
if(ALU_OPCODE != `ALU_SLTU)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT7_5 = 1'b1;
FUNCT3 = `FUNCT3_SLTU;
#10;
if(ALU_OPCODE != `ALU_SLTU)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SLTIU... OK.");
FUNCT7_5 = 1'b0;
FUNCT3 = `FUNCT3_AND;
#10;
if(ALU_OPCODE != `ALU_AND)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT7_5 = 1'b1;
FUNCT3 = `FUNCT3_AND;
#10;
if(ALU_OPCODE != `ALU_AND)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for ANDI... OK.");
FUNCT7_5 = 1'b0;
FUNCT3 = `FUNCT3_OR;
#10;
if(ALU_OPCODE != `ALU_OR)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT7_5 = 1'b1;
FUNCT3 = `FUNCT3_OR;
#10;
if(ALU_OPCODE != `ALU_OR)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for ORI... OK.");
FUNCT7_5 = 1'b0;
FUNCT3 = `FUNCT3_XOR;
#10;
if(ALU_OPCODE != `ALU_XOR)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT7_5 = 1'b1;
FUNCT3 = `FUNCT3_XOR;
#10;
if(ALU_OPCODE != `ALU_XOR)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for XORI... OK.");
funct7 = `FUNCT7_SLL;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SLL;
#10;
if(ALU_OPCODE != `ALU_SLL)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SLLI... OK.");
funct7 = `FUNCT7_SRL;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SRL;
#10;
if(ALU_OPCODE != `ALU_SRL)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SRLI... OK.");
funct7 = `FUNCT7_SRA;
FUNCT7_5 = funct7[5];
FUNCT3 = `FUNCT3_SRA;
#10;
if(ALU_OPCODE != `ALU_SRA)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ALU_OPCODE for SRAI... OK.");
$display("ALU_OPCODE signal generation for OP-IMM opcode successfully tested.");
$display("OP-IMM control signals successfully tested.");
$display("Testing LOAD opcode control signals...");
$display("Testing signals common to all instructions...");
opcode_6_to_2 = `OPCODE_LOAD;
OPCODE = {opcode_6_to_2, 2'b11};
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WB_MUX_SEL != `WB_LU)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IADDER_SRC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `I_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("LOAD control signals common to all instructions successfully tested.");
$display("Testing load unit control signals generation...");
FUNCT3 = `FUNCT3_BYTE;
#10;
if(LOAD_SIZE != `LOAD_BYTE)
begin
$display("FAIL. Check the results.");
$finish;
end
if(LOAD_UNSIGNED != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Load unit signals for LB... OK.");
$display("Testing signal MISALIGNED_LOAD for LB...");
FUNCT3 = `FUNCT3_BYTE;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_LOAD generation for LB OK.");
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(LOAD_SIZE != `LOAD_HALF)
begin
$display("FAIL. Check the results.");
$finish;
end
if(LOAD_UNSIGNED != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Load unit signals for LH... OK.");
$display("Testing signal MISALIGNED_LOAD for LH...");
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_LOAD != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_LOAD != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_LOAD generation for LH OK.");
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(LOAD_SIZE != `LOAD_WORD)
begin
$display("FAIL. Check the results.");
$finish;
end
if(LOAD_UNSIGNED != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Load unit signals for LW... OK.");
$display("Testing signal MISALIGNED_LOAD for LW...");
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_LOAD != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_LOAD != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_LOAD != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_LOAD generation for LW OK.");
FUNCT3 = `FUNCT3_BYTE_U;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(LOAD_SIZE != `LOAD_BYTE)
begin
$display("FAIL. Check the results.");
$finish;
end
if(LOAD_UNSIGNED != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Load unit signals for LBU... OK.");
$display("Testing signal MISALIGNED_LOAD for LBU...");
FUNCT3 = `FUNCT3_BYTE_U;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE_U;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE_U;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_LOAD generation for LBU OK.");
FUNCT3 = `FUNCT3_HALF_U;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(LOAD_SIZE != `LOAD_HALF)
begin
$display("FAIL. Check the results.");
$finish;
end
if(LOAD_UNSIGNED != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Load unit signals for LHU... OK.");
$display("Testing signal MISALIGNED_LOAD for LHU...");
FUNCT3 = `FUNCT3_HALF_U;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_LOAD != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF_U;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF_U;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_LOAD != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_LOAD generation for LHU OK.");
$display("Signals for load unit successfuly tested.");
$display("LOAD opcode successfully tested.");
$display("Testing STORE opcode operation...");
$display("Testing signals common to all instructions...");
opcode_6_to_2 = `OPCODE_STORE;
OPCODE = {opcode_6_to_2, 2'b11};
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(MEM_WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_LOAD != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IADDER_SRC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `S_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("STORE control signals common to all instructions successfully tested.");
$display("Testing signal MISALIGNED_STORE for SB...");
FUNCT3 = `FUNCT3_BYTE;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_STORE generation for SB OK.");
$display("Testing signal MISALIGNED_STORE for SH...");
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_STORE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_STORE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_STORE generation for SH OK.");
$display("Testing signal MISALIGNED_STORE for SW...");
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(MISALIGNED_STORE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b01;
#10;
if(MISALIGNED_STORE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b10;
#10;
if(MISALIGNED_STORE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_WORD;
IADDER_OUT_1_TO_0 = 2'b11;
#10;
if(MISALIGNED_STORE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISALIGNED_STORE generation for SW OK.");
$display("STORE operation successfully tested.");
$display("Testing BRANCH opcode signals generation...");
opcode_6_to_2 = `OPCODE_BRANCH;
OPCODE = {opcode_6_to_2, 2'b11};
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IADDER_SRC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `B_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("BRANCH control signals successfully tested.");
$display("Testing JAL control signals generation...");
opcode_6_to_2 = `OPCODE_JAL;
OPCODE = {opcode_6_to_2, 2'b11};
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IADDER_SRC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WB_MUX_SEL != `WB_PC_PLUS)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `J_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("JAL control signals successfully tested.");
$display("Testing JALR control signals generation...");
opcode_6_to_2 = `OPCODE_JALR;
OPCODE = {opcode_6_to_2, 2'b11};
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WB_MUX_SEL != `WB_PC_PLUS)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IADDER_SRC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `I_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("JALR control signals successfully tested.");
$display("Testing LUI opcode operation...");
opcode_6_to_2 = `OPCODE_LUI;
OPCODE = {opcode_6_to_2, 2'b11};
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WB_MUX_SEL != `WB_IMM)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `U_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("LUI control signals successfully tested.");
$display("Testing AUIPC control signals generation...");
opcode_6_to_2 = `OPCODE_AUIPC;
OPCODE = {opcode_6_to_2, 2'b11};
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WB_MUX_SEL != `WB_IADDER_OUT)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IADDER_SRC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `U_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("AUIPC control signals successfully tested.");
$display("Testing MISC-MEM control signals generation...");
opcode_6_to_2 = `OPCODE_MISC_MEM;
OPCODE = {opcode_6_to_2, 2'b11};
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISM-MEM control signals successfully tested.");
$display("Testing SYSteel Core control signals operation...");
$display("Testing ECALL, EBREAK, MRET and WFI instructions...");
opcode_6_to_2 = `OPCODE_SYSTEM;
OPCODE = {opcode_6_to_2, 2'b11};
FUNCT3 = 3'b000;
#10;
if(MEM_WR_REQ != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("ECALL, EBREAK, MRET and WFI successfully tested.");
$display("Testing CSRRW...");
FUNCT3 = 3'b001;
#10;
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `CSR_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_OP != FUNCT3)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CSRRW successfully tested.");
$display("Testing CSRRS...");
FUNCT3 = 3'b010;
#10;
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `CSR_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_OP != FUNCT3)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CSRRS successfully tested.");
$display("Testing CSRRC...");
FUNCT3 = 3'b011;
#10;
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `CSR_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_OP != FUNCT3)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CSRRC successfully tested.");
$display("Testing CSRRWI...");
FUNCT3 = 3'b101;
#10;
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `CSR_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_OP != FUNCT3)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CSRRWI successfully tested.");
$display("Testing CSRRSI...");
FUNCT3 = 3'b110;
#10;
if(ILLEGAL_INSTR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RF_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_WR_EN != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(IMM_TYPE != `CSR_TYPE)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_OP != FUNCT3)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CSRRSI successfully tested.");
$display("Steel Core control signals successfully tested.");
$display("Testing illegal instructions...");
OPCODE = {`OPCODE_OP,2'b10};
#10;
if(ILLEGAL_INSTR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
OPCODE = {`OPCODE_OP,2'b01};
#10;
if(ILLEGAL_INSTR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
OPCODE = {5'b11111,2'b11};
#10;
if(ILLEGAL_INSTR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Illegal instructions successfully tested.");
$display("Control Unit successfully tested.");
end
 
endmodule
/steelcore/trunk/bench/tb_csr_file.v
0,0 → 1,1971
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 30.04.2020 21:30:47
// Module Name: tb_csr_file
// Project Name: Steel Core
// Description: RISC-V Steel Core CSR File testbench
//
// Dependencies: csr_file.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
module tb_csr_file();
 
reg CLK;
reg RESET;
reg WR_EN;
reg [11:0] CSR_ADDR;
reg [2:0] CSR_OP;
reg [4:0] CSR_UIMM;
reg [31:0] CSR_DATA_IN;
wire [31:0] CSR_DATA_OUT;
reg [31:0] PC;
reg E_IRQ;
reg T_IRQ;
reg S_IRQ;
reg I_OR_E;
reg SET_CAUSE;
reg [3:0] CAUSE_IN;
reg SET_EPC;
reg INSTRET_INC;
reg MIE_CLEAR;
reg MIE_SET;
wire MIE;
wire MEIE_OUT;
wire MTIE_OUT;
wire MSIE_OUT;
wire MEIP_OUT;
wire MTIP_OUT;
wire MSIP_OUT;
reg [63:0] REAL_TIME;
wire [31:0] EPC_OUT;
wire [31:0] TRAP_ADDRESS;
csr_file dut(
 
.CLK(CLK),
.RESET(RESET),
.WR_EN(WR_EN),
.CSR_ADDR(CSR_ADDR),
.CSR_OP(CSR_OP),
.CSR_UIMM(CSR_UIMM),
.CSR_DATA_IN(CSR_DATA_IN),
.CSR_DATA_OUT(CSR_DATA_OUT),
.PC(PC),
.E_IRQ(E_IRQ),
.T_IRQ(T_IRQ),
.S_IRQ(S_IRQ),
.I_OR_E(I_OR_E),
.SET_CAUSE(SET_CAUSE),
.CAUSE_IN(CAUSE_IN),
.SET_EPC(SET_EPC),
.INSTRET_INC(INSTRET_INC),
.MIE_CLEAR(MIE_CLEAR),
.MIE_SET(MIE_SET),
.MIE(MIE),
.MEIE_OUT(MEIE_OUT),
.MTIE_OUT(MTIE_OUT),
.MSIE_OUT(MSIE_OUT),
.MEIP_OUT(MEIP_OUT),
.MTIP_OUT(MTIP_OUT),
.MSIP_OUT(MSIP_OUT),
.REAL_TIME(REAL_TIME),
.EPC_OUT(EPC_OUT),
.TRAP_ADDRESS(TRAP_ADDRESS)
 
);
reg [31:0] base_offset;
always
begin
#10 CLK = !CLK;
end
initial
begin
$display("Testing CSR Register File...");
CLK = 1'b0;
RESET = 1'b0;
WR_EN = 1'b0;
CSR_ADDR = 5'b00000;
CSR_OP = `CSR_NOP;
CSR_UIMM = 5'b00000;
CSR_DATA_IN = 32'h00000000;
PC = 32'h00000000;
E_IRQ = 1'b0;
T_IRQ = 1'b0;
S_IRQ = 1'b0;
I_OR_E = 1'b0;
SET_CAUSE = 1'b0;
CAUSE_IN = 4'b0000;
SET_EPC = 1'b0;
INSTRET_INC = 1'b0;
MIE_CLEAR = 1'b0;
MIE_SET = 1'b0;
REAL_TIME = 64'h0000000000000000;
//----------------------------------------------------------------------
// RESET VALUES TEST
//----------------------------------------------------------------------
$display("Testing values after reset...");
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `CYCLE;
#5;
if(CSR_DATA_OUT != `MCYCLE_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CYCLE reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `CYCLEH;
#5;
if(CSR_DATA_OUT != `MCYCLEH_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CYCLEH reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `TIME;
#5;
if(CSR_DATA_OUT != `TIME_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("TIME reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `TIMEH;
#5;
if(CSR_DATA_OUT != `TIMEH_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("TIMEH reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `INSTRET;
#5;
if(CSR_DATA_OUT != `MINSTRET_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("INSTRET reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `INSTRETH;
#5;
if(CSR_DATA_OUT != `MINSTRETH_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("INSTRETH reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MSTATUS;
#5;
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b0, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MSTATUS reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MISA;
#5;
if(CSR_DATA_OUT != 32'b01000000000000000000000100000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MISA reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MIE;
#5;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MIE reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MTVEC;
#5;
if(CSR_DATA_OUT != {`MTVEC_BASE_RESET, `MTVEC_MODE_RESET})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MTVEC reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MSCRATCH;
#5;
if(CSR_DATA_OUT != `MSCRATCH_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MSCRATCH reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MEPC;
#5;
if(CSR_DATA_OUT != `MEPC_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MEPC reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MTVAL;
#5;
if(CSR_DATA_OUT != 32'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MTVAL reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MIP;
#5;
if(CSR_DATA_OUT != 32'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MIP reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MCYCLE;
#5;
if(CSR_DATA_OUT != `MCYCLE_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CYCLE reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MCYCLEH;
#5;
if(CSR_DATA_OUT != `MCYCLEH_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CYCLEH reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MINSTRET;
#5;
if(CSR_DATA_OUT != `MINSTRET_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("INSTRET reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MINSTRETH;
#5;
if(CSR_DATA_OUT != `MINSTRETH_RESET)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("INSTRETH reset value OK.");
#20;
RESET = 1'b1;
#15;
RESET = 1'b0;
CSR_ADDR = `MCOUNTINHIBIT;
#5;
if(CSR_DATA_OUT != {29'b0, `MCOUNTINHIBIT_IR_RESET, 1'b0, `MCOUNTINHIBIT_CY_RESET})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MCOUNTINHIBIT reset value OK.");
$display("Reset values successfully tested.");
#35;
//----------------------------------------------------------------------
// WRITE OPERATION TEST
//----------------------------------------------------------------------
$display("Testing write operation for each CSR...");
WR_EN = 1'b1;
CSR_OP = {1'b0, `CSR_RW};
CSR_UIMM = 5'b11111;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_ADDR = `CYCLE;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register CYCLE unsuccessful. Result OK.");
CSR_ADDR = `CYCLEH;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register CYCLEH unsuccessful. Result OK.");
CSR_ADDR = `TIME;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register TIME unsuccessful. Result OK.");
CSR_ADDR = `TIMEH;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register TIMEH unsuccessful. Result OK.");
CSR_ADDR = `INSTRET;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register INSTRET unsuccessful. Result OK.");
CSR_ADDR = `INSTRETH;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register INSTRETH unsuccessful. Result OK.");
CSR_ADDR = `MSTATUS;
#20;
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MSTATUS successful. Result OK.");
CSR_ADDR = `MISA;
#20;
if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MISA unsuccessful. Result OK.");
CSR_ADDR = `MIE;
#20;
if(CSR_DATA_OUT != {20'b0, 1'b1, 3'b0, 1'b1, 3'b0, 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MIE successful. Result OK.");
CSR_ADDR = `MTVEC;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MTVEC successful. Result OK.");
CSR_ADDR = `MSCRATCH;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MSCRATCH successful. Result OK.");
CSR_ADDR = `MEPC;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFC)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MEPC successful. Result OK.");
CSR_ADDR = `MCAUSE;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MCAUSE unsuccessful. Result OK.");
CSR_ADDR = `MTVAL;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MTVAL unsuccessful. Result OK.");
CSR_ADDR = `MIP;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MIP unsuccessful. Result OK.");
CSR_ADDR = `MCYCLE;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MCYCLE successful. Result OK.");
CSR_ADDR = `MCYCLEH;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MCYCLEH successful. Result OK.");
CSR_ADDR = `MINSTRET;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MINSTRET successful. Result OK.");
CSR_ADDR = `MINSTRETH;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MINSTRETH successful. Result OK.");
CSR_ADDR = `MCOUNTINHIBIT;
#20;
if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MCOUNTINHIBIT successful. Result OK.");
$display("Write operation successfully tested.");
//----------------------------------------------------------------------
// SET OPERATION TEST
//----------------------------------------------------------------------
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
$display("Testing set operation for each CSR...");
WR_EN = 1'b1;
CSR_OP = {1'b0, `CSR_RS};
CSR_UIMM = 5'b11111;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_ADDR = `CYCLE;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register CYCLE unsuccessful. Result OK.");
CSR_ADDR = `CYCLEH;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register CYCLEH unsuccessful. Result OK.");
CSR_ADDR = `TIME;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register TIME unsuccessful. Result OK.");
CSR_ADDR = `TIMEH;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register TIMEH unsuccessful. Result OK.");
CSR_ADDR = `INSTRET;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register INSTRET unsuccessful. Result OK.");
CSR_ADDR = `INSTRETH;
#20;
if(CSR_DATA_OUT == 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register INSTRETH unsuccessful. Result OK.");
CSR_ADDR = `MSTATUS;
#20;
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MSTATUS successful. Result OK.");
CSR_ADDR = `MISA;
#20;
if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MISA unsuccessful. Result OK.");
CSR_ADDR = `MIE;
#20;
if(CSR_DATA_OUT != {20'b0, 1'b1, 3'b0, 1'b1, 3'b0, 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MIE successful. Result OK.");
CSR_ADDR = `MTVEC;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MTVEC successful. Result OK.");
CSR_ADDR = `MSCRATCH;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MSCRATCH successful. Result OK.");
CSR_ADDR = `MEPC;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFC)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MEPC successful. Result OK.");
CSR_ADDR = `MCAUSE;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MCAUSE unsuccessful. Result OK.");
CSR_ADDR = `MTVAL;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MTVAL unsuccessful. Result OK.");
CSR_ADDR = `MIP;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MIP unsuccessful. Result OK.");
CSR_ADDR = `MCYCLE;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MCYCLE successful. Result OK.");
CSR_ADDR = `MCYCLEH;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MCYCLEH successful. Result OK.");
CSR_ADDR = `MINSTRET;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MINSTRET successful. Result OK.");
CSR_ADDR = `MINSTRETH;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MINSTRETH successful. Result OK.");
CSR_ADDR = `MCOUNTINHIBIT;
#20;
if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MCOUNTINHIBIT successful. Result OK.");
$display("Set operation successfully tested.");
//----------------------------------------------------------------------
// CLEAR OPERATION TEST
//----------------------------------------------------------------------
$display("Testing clear operation for each CSR...");
WR_EN = 1'b1;
CSR_OP = {1'b0, `CSR_RC};
CSR_UIMM = 5'b11111;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_ADDR = `CYCLE;
#20;
if(CSR_DATA_OUT == 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register CYCLE unsuccessful. Result OK.");
CSR_ADDR = `CYCLEH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register CYCLEH unsuccessful. Result OK.");
CSR_ADDR = `TIME;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register TIME unsuccessful. Result OK.");
CSR_ADDR = `TIMEH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register TIMEH unsuccessful. Result OK.");
CSR_ADDR = `INSTRET;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register INSTRET unsuccessful. Result OK.");
CSR_ADDR = `INSTRETH;
#20;
if(CSR_DATA_OUT != 32'hFFFFFFFF)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register INSTRETH unsuccessful. Result OK.");
CSR_ADDR = `MSTATUS;
#20;
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b0, 3'b0 , 1'b0, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MSTATUS successful. Result OK.");
CSR_ADDR = `MISA;
#20;
if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MISA unsuccessful. Result OK.");
CSR_ADDR = `MIE;
#20;
if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b0, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MIE successful. Result OK.");
CSR_ADDR = `MTVEC;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MTVEC successful. Result OK.");
CSR_ADDR = `MSCRATCH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MSCRATCH successful. Result OK.");
CSR_ADDR = `MEPC;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MEPC successful. Result OK.");
CSR_ADDR = `MCAUSE;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MCAUSE unsuccessful. Result OK.");
CSR_ADDR = `MTVAL;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MTVAL unsuccessful. Result OK.");
CSR_ADDR = `MIP;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MIP unsuccessful. Result OK.");
CSR_ADDR = `MCYCLE;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MCYCLE successful. Result OK.");
CSR_ADDR = `MCYCLEH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MCYCLEH successful. Result OK.");
CSR_ADDR = `MINSTRET;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MINSTRET successful. Result OK.");
CSR_ADDR = `MINSTRETH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MINSTRETH successful. Result OK.");
CSR_ADDR = `MCOUNTINHIBIT;
#20;
if(CSR_DATA_OUT != {29'b0, 1'b0, 1'b0, 1'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MCOUNTINHIBIT successful. Result OK.");
$display("Clear operation successfully tested.");
//----------------------------------------------------------------------
// WRITE IMMEDIATE OPERATION TEST
//----------------------------------------------------------------------
$display("Testing write immediate operation for each CSR...");
WR_EN = 1'b1;
CSR_OP = {1'b1, `CSR_RW};
CSR_UIMM = 5'b11111;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_ADDR = `CYCLE;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register CYCLE unsuccessful. Result OK.");
CSR_ADDR = `CYCLEH;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register CYCLEH unsuccessful. Result OK.");
CSR_ADDR = `TIME;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register TIME unsuccessful. Result OK.");
CSR_ADDR = `TIMEH;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register TIMEH unsuccessful. Result OK.");
CSR_ADDR = `INSTRET;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register INSTRET unsuccessful. Result OK.");
CSR_ADDR = `INSTRETH;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register INSTRETH unsuccessful. Result OK.");
CSR_ADDR = `MSTATUS;
#20;
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b0, 3'b0 , 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MSTATUS successful. Result OK.");
CSR_ADDR = `MISA;
#20;
if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MISA unsuccessful. Result OK.");
CSR_ADDR = `MIE;
#20;
if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MIE successful. Result OK.");
CSR_ADDR = `MTVEC;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MTVEC successful. Result OK.");
CSR_ADDR = `MSCRATCH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MSCRATCH successful. Result OK.");
CSR_ADDR = `MEPC;
#20;
if(CSR_DATA_OUT != 32'h0000001C)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MEPC successful. Result OK.");
CSR_ADDR = `MCAUSE;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MCAUSE unsuccessful. Result OK.");
CSR_ADDR = `MTVAL;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MTVAL unsuccessful. Result OK.");
CSR_ADDR = `MIP;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-only register MIP unsuccessful. Result OK.");
CSR_ADDR = `MCYCLE;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MCYCLE successful. Result OK.");
CSR_ADDR = `MCYCLEH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MCYCLEH successful. Result OK.");
CSR_ADDR = `MINSTRET;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MINSTRET successful. Result OK.");
CSR_ADDR = `MINSTRETH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MINSTRETH successful. Result OK.");
CSR_ADDR = `MCOUNTINHIBIT;
#20;
if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to write the read-write register MCOUNTINHIBIT successful. Result OK.");
$display("Write operation successfully tested.");
//----------------------------------------------------------------------
// SET IMMEDIATE OPERATION TEST
//----------------------------------------------------------------------
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
$display("Testing set immediate operation for each CSR...");
WR_EN = 1'b1;
CSR_OP = {1'b1, `CSR_RS};
CSR_UIMM = 5'b11111;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_ADDR = `CYCLE;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register CYCLE unsuccessful. Result OK.");
CSR_ADDR = `CYCLEH;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register CYCLEH unsuccessful. Result OK.");
CSR_ADDR = `TIME;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register TIME unsuccessful. Result OK.");
CSR_ADDR = `TIMEH;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register TIMEH unsuccessful. Result OK.");
CSR_ADDR = `INSTRET;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register INSTRET unsuccessful. Result OK.");
CSR_ADDR = `INSTRETH;
#20;
if(CSR_DATA_OUT == 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register INSTRETH unsuccessful. Result OK.");
CSR_ADDR = `MSTATUS;
#20;
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MSTATUS successful. Result OK.");
CSR_ADDR = `MISA;
#20;
if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MISA unsuccessful. Result OK.");
CSR_ADDR = `MIE;
#20;
if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MIE successful. Result OK.");
CSR_ADDR = `MTVEC;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MTVEC successful. Result OK.");
CSR_ADDR = `MSCRATCH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MSCRATCH successful. Result OK.");
CSR_ADDR = `MEPC;
#20;
if(CSR_DATA_OUT != 32'h0000001C)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MEPC successful. Result OK.");
CSR_ADDR = `MCAUSE;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MCAUSE unsuccessful. Result OK.");
CSR_ADDR = `MTVAL;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MTVAL unsuccessful. Result OK.");
CSR_ADDR = `MIP;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-only register MIP unsuccessful. Result OK.");
CSR_ADDR = `MCYCLE;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MCYCLE successful. Result OK.");
CSR_ADDR = `MCYCLEH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MCYCLEH successful. Result OK.");
CSR_ADDR = `MINSTRET;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MINSTRET successful. Result OK.");
CSR_ADDR = `MINSTRETH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MINSTRETH successful. Result OK.");
CSR_ADDR = `MCOUNTINHIBIT;
#20;
if(CSR_DATA_OUT != {29'b0, 1'b1, 1'b0, 1'b1})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to set the read-write register MCOUNTINHIBIT successful. Result OK.");
$display("Set operation successfully tested.");
//----------------------------------------------------------------------
// CLEAR IMMEDIATE OPERATION TEST
//----------------------------------------------------------------------
$display("Testing clear immediate operation for each CSR...");
WR_EN = 1'b1;
CSR_OP = {1'b1, `CSR_RC};
CSR_UIMM = 5'b11111;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_ADDR = `CYCLE;
#20;
if(CSR_DATA_OUT == 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register CYCLE unsuccessful. Result OK.");
CSR_ADDR = `CYCLEH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register CYCLEH unsuccessful. Result OK.");
CSR_ADDR = `TIME;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register TIME unsuccessful. Result OK.");
CSR_ADDR = `TIMEH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register TIMEH unsuccessful. Result OK.");
CSR_ADDR = `INSTRET;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register INSTRET unsuccessful. Result OK.");
CSR_ADDR = `INSTRETH;
#20;
if(CSR_DATA_OUT != 32'h0000001F)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register INSTRETH unsuccessful. Result OK.");
CSR_ADDR = `MSTATUS;
#20;
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b0, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MSTATUS successful. Result OK.");
CSR_ADDR = `MISA;
#20;
if(CSR_DATA_OUT != {2'b01, 4'b0, 26'b00000000000000000100000000})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MISA unsuccessful. Result OK.");
CSR_ADDR = `MIE;
#20;
if(CSR_DATA_OUT != {20'b0, 1'b0, 3'b0, 1'b0, 3'b0, 1'b0, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MIE successful. Result OK.");
CSR_ADDR = `MTVEC;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MTVEC successful. Result OK.");
CSR_ADDR = `MSCRATCH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MSCRATCH successful. Result OK.");
CSR_ADDR = `MEPC;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MEPC successful. Result OK.");
CSR_ADDR = `MCAUSE;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MCAUSE unsuccessful. Result OK.");
CSR_ADDR = `MTVAL;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MTVAL unsuccessful. Result OK.");
CSR_ADDR = `MIP;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-only register MIP unsuccessful. Result OK.");
CSR_ADDR = `MCYCLE;
#20;
if(CSR_DATA_OUT != 32'h00000020)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MCYCLE successful. Result OK.");
CSR_ADDR = `MCYCLEH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MCYCLEH successful. Result OK.");
CSR_ADDR = `MINSTRET;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MINSTRET successful. Result OK.");
CSR_ADDR = `MINSTRETH;
#20;
if(CSR_DATA_OUT != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MINSTRETH successful. Result OK.");
CSR_ADDR = `MCOUNTINHIBIT;
#20;
if(CSR_DATA_OUT != {29'b0, 1'b0, 1'b0, 1'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Attempt to clear the read-write register MCOUNTINHIBIT successful. Result OK.");
$display("Clear operation successfully tested.");
//----------------------------------------------------------------------
// INTERRUPT PENDING BITS TEST
//----------------------------------------------------------------------
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
$display("Testing interrupt pending bits setup...");
E_IRQ = 1'b1;
T_IRQ = 1'b1;
S_IRQ = 1'b1;
#20;
if(MEIP_OUT != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MTIP_OUT != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MSIP_OUT != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Interrupt pending bits successfully tested.");
//----------------------------------------------------------------------
// INTERRUPT ENABLE BITS TEST
//----------------------------------------------------------------------
$display("Testing interrupt enable bits setup...");
WR_EN = 1'b1;
CSR_ADDR = `MSTATUS;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_OP = {1'b0, `CSR_RW};
#20;
WR_EN = 1'b1;
CSR_ADDR = `MIE;
CSR_DATA_IN = 32'hFFFFFFFF;
CSR_OP = {1'b0, `CSR_RW};
#20;
if(MIE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MEIE_OUT != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MTIE_OUT != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MSIE_OUT != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Interrupt enable bits successfully tested.");
//----------------------------------------------------------------------
// EPC SET TEST
//----------------------------------------------------------------------
$display("Testing EPC setup...");
SET_EPC = 1'b1;
PC = $random;
CSR_ADDR = `MEPC;
#20;
SET_EPC = 1'b0;
if(CSR_DATA_OUT != PC)
begin
$display("FAIL. Check the results.");
$finish;
end
if(EPC_OUT != PC)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("EPC setup successfully tested.");
 
//----------------------------------------------------------------------
// MCAUSE SET TEST
//----------------------------------------------------------------------
$display("Testing MCAUSE setup...");
SET_CAUSE = 1'b1;
CAUSE_IN = $random;
I_OR_E = 1'b1;
CSR_ADDR = `MCAUSE;
#20;
if(CSR_DATA_OUT != {I_OR_E, 27'b0, CAUSE_IN})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MCAUSE setup successfully tested.");
//----------------------------------------------------------------------
// TRAP ADDRESS GENERATION TEST
//----------------------------------------------------------------------
$display("Testing TRAP ADDRESS generation...");
$display("Testing exceptions in Direct Mode...");
WR_EN =1'b1;
CSR_ADDR = `MTVEC;
CSR_OP = {1'b0, `CSR_RW};
CSR_DATA_IN = $random;
CSR_DATA_IN[1:0] = 2'b00;
SET_CAUSE = 1'b1;
CAUSE_IN = $random;
I_OR_E = 1'b0;
#20;
if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b00})
begin
$display("FAIL. Check the results.");
$finish;
end
if(TRAP_ADDRESS != {CSR_DATA_IN[31:2], 2'b00})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Exceptions in Direct Mode OK.");
$display("Testing interrupts in Direct Mode...");
WR_EN =1'b1;
CSR_ADDR = `MTVEC;
CSR_OP = {1'b0, `CSR_RW};
CSR_DATA_IN = $random;
CSR_DATA_IN[1:0] = 2'b00;
SET_CAUSE = 1'b1;
CAUSE_IN = $random;
I_OR_E = 1'b1;
#20;
if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b00})
begin
$display("FAIL. Check the results.");
$finish;
end
if(TRAP_ADDRESS != {CSR_DATA_IN[31:2], 2'b00})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Interrupts in Direct Mode OK.");
$display("Testing exceptions in Vectored Mode...");
WR_EN =1'b1;
CSR_ADDR = `MTVEC;
CSR_OP = {1'b0, `CSR_RW};
CSR_DATA_IN = $random;
CSR_DATA_IN[1:0] = 2'b01;
SET_CAUSE = 1'b1;
CAUSE_IN = $random;
I_OR_E = 1'b0;
#20;
if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b01})
begin
$display("FAIL. Check the results.");
$finish;
end
if(TRAP_ADDRESS != {CSR_DATA_IN[31:2], 2'b00})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Exceptions in Vectored Mode OK.");
$display("Testing interrupts in Vectored Mode...");
WR_EN =1'b1;
CSR_ADDR = `MTVEC;
CSR_OP = {1'b0, `CSR_RW};
CSR_DATA_IN = $random;
CSR_DATA_IN[1:0] = 2'b01;
SET_CAUSE = 1'b1;
CAUSE_IN = $random;
I_OR_E = 1'b1;
#20;
if(CSR_DATA_OUT != {CSR_DATA_IN[31:2], 2'b01})
begin
$display("FAIL. Check the results.");
$finish;
end
base_offset = CAUSE_IN << 2;
if(TRAP_ADDRESS != ({CSR_DATA_IN[31:2],2'b00} + base_offset))
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Interrupts in Vectored Mode OK.");
$display("TRAP ADDRESS generation successfully tested.");
//----------------------------------------------------------------------
// MIE CLEAR & SET TEST
//----------------------------------------------------------------------
WR_EN =1'b0;
$display("Testing MIE clear operation...");
MIE_CLEAR = 1'b1;
CSR_ADDR = `MSTATUS;
#20;
MIE_CLEAR = 1'b0;
if(MIE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b0, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
MIE_SET = 1'b1;
CSR_ADDR = `MSTATUS;
#20;
MIE_SET = 1'b0;
if(MIE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CSR_DATA_OUT != {19'b0, 2'b11, 3'b0, 1'b1, 3'b0 , 1'b1, 3'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
$display("MIE CLEAR & SET operation successfully tested.");
//----------------------------------------------------------------------
// CYCLE & INSTRET COUNTING TEST
//----------------------------------------------------------------------
WR_EN =1'b0;
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
$display("Testing CYCLE and INSTRET counting...");
INSTRET_INC = 1'b1;
CSR_ADDR = `CYCLE;
#15;
if(CSR_DATA_OUT != `MCYCLE_RESET + 1)
begin
$display("FAIL. Check the results.");
$finish;
end
CSR_ADDR = `INSTRET;
#5;
if(CSR_DATA_OUT != `MINSTRET_RESET + 1)
begin
$display("FAIL. Check the results.");
$finish;
end
INSTRET_INC = 1'b0;
CSR_ADDR = `CYCLE;
#15;
if(CSR_DATA_OUT != `MCYCLE_RESET + 2)
begin
$display("FAIL. Check the results.");
$finish;
end
CSR_ADDR = `INSTRET;
#5;
if(CSR_DATA_OUT != `MINSTRET_RESET + 1)
begin
$display("FAIL. Check the results.");
$finish;
end
WR_EN = 1'b1;
INSTRET_INC = 1'b1;
CSR_OP = {1'b0, CSR_OP};
CSR_ADDR = `MCOUNTINHIBIT;
CSR_DATA_IN = {29'b0, 3'b101};
#20;
WR_EN = 1'b0;
CSR_ADDR = `CYCLE;
#15;
if(CSR_DATA_OUT != `MCYCLE_RESET + 3)
begin
$display("FAIL. Check the results.");
$finish;
end
CSR_ADDR = `INSTRET;
#5;
if(CSR_DATA_OUT != `MINSTRET_RESET + 2)
begin
$display("FAIL. Check the results.");
$finish;
end
WR_EN = 1'b1;
CSR_OP = {1'b0, CSR_OP};
CSR_ADDR = `MCOUNTINHIBIT;
CSR_DATA_IN = {29'b0, 3'b000};
#20;
WR_EN = 1'b0;
CSR_ADDR = `CYCLE;
#15;
if(CSR_DATA_OUT != `MCYCLE_RESET + 4)
begin
$display("FAIL. Check the results.");
$finish;
end
CSR_ADDR = `INSTRET;
#5;
if(CSR_DATA_OUT != `MINSTRET_RESET + 3)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("CYCLE & INSTRET counting successfully tested.");
$display("CSR Register File successfully tested.");
end
 
endmodule
 
/steelcore/trunk/bench/tb_imm_generator.v
0,0 → 1,298
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 22:58:58
// Module Name: tb_imm_generator
// Project Name: Steel Core
// Description: RISC-V Steel Core Immediate Generator testbench
//
// Dependencies: imm_generator.v, control_unit.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
module tb_imm_generator();
 
reg [31:0] INSTR;
reg [2:0] FUNCT3;
wire [2:0] IMM_TYPE;
wire [31:0] IMM;
imm_generator dut(
.INSTR(INSTR[31:7]),
.IMM_TYPE(IMM_TYPE),
.IMM(IMM)
);
control_unit ctrlunit(
.OPCODE(INSTR[6:0]),
.FUNCT7_5(1'b0),
.FUNCT3(FUNCT3),
.IMM_TYPE(IMM_TYPE)
);
 
integer i;
initial
begin
$display("Testing Immediate Generator...");
INSTR = {30'b0, 2'b11};
FUNCT3 = 3'b0;
$display("Testing immediate generator for OP-IMM opcode");
INSTR[6:2] = `OPCODE_OP_IMM;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { {20{INSTR[31]}}, INSTR[31:20] })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("OP-IMM opcode successfully tested.");
$display("Testing immediate generator for LOAD opcode");
INSTR[6:2] = `OPCODE_LOAD;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { {20{INSTR[31]}}, INSTR[31:20] })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("LOAD opcode successfully tested.");
$display("Testing immediate generator for STORE opcode");
INSTR[6:2] = `OPCODE_STORE;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { {20{INSTR[31]}}, INSTR[31:25], INSTR[11:7] })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("STORE opcode successfully tested.");
$display("Testing immediate generator for BRANCH opcode");
INSTR[6:2] = `OPCODE_BRANCH;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { {19{INSTR[31]}}, INSTR[31], INSTR[7], INSTR[30:25], INSTR[11:8], 1'b0 })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("BRANCH opcode successfully tested.");
$display("Testing immediate generator for JALR opcode");
INSTR[6:2] = `OPCODE_JALR;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { {20{INSTR[31]}}, INSTR[31:20] })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("JALR opcode successfully tested.");
$display("Testing immediate generator for JAL opcode");
INSTR[6:2] = `OPCODE_JAL;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { {11{INSTR[31]}}, INSTR[31], INSTR[19:12], INSTR[20], INSTR[30:21], 1'b0 })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("JAL opcode successfully tested.");
$display("Testing immediate generator for LUI opcode");
INSTR[6:2] = `OPCODE_LUI;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { INSTR[31:12], 12'h000 })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("LUI opcode successfully tested.");
$display("Testing immediate generator for AUIPC opcode");
INSTR[6:2] = `OPCODE_AUIPC;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
#10;
if(IMM != { INSTR[31:12], 12'h000 })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("AUIPC opcode successfully tested.");
$display("Testing immediate generator for SYSteel Core opcode");
INSTR[6:2] = `OPCODE_SYSTEM;
for(i = 0; i < 10000; i=i+1)
begin
INSTR[31:7] = $random;
FUNCT3 = $random;
#10;
if(FUNCT3 != 3'b000 && IMM != { 27'b0, INSTR[19:15] })
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("SYSteel Core opcode successfully tested.");
$display("Immediate Generator successfully tested.");
end
 
endmodule
/steelcore/trunk/bench/tb_integer_file.v
0,0 → 1,199
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 03.04.2020 18:35:35
// Module Name: tb_integer_file
// Project Name: Steel Core
// Description: RISC-V Steel Core 32-bit Integer Register File testbench
//
// Dependencies: register_file.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
module tb_integer_file();
 
reg CLK;
reg RESET;
reg [4:0] RS_1_ADDR;
reg [4:0] RS_2_ADDR;
wire [31:0] RS_1;
wire [31:0] RS_2;
reg [4:0] RD_ADDR;
reg WR_EN;
reg [31:0] RD;
integer_file dut(
.CLK( CLK),
.RESET( RESET),
.RS_1_ADDR( RS_1_ADDR),
.RS_2_ADDR( RS_2_ADDR),
.RD_ADDR( RD_ADDR),
.RS_1( RS_1),
.RS_2( RS_2),
.WR_EN( WR_EN),
.RD( RD)
);
integer i;
always
begin
#10 CLK = !CLK;
end
initial
begin
$display("Testing Integer Register File...");
CLK = 1'b0;
RESET = 1'b0;
RS_1_ADDR = 5'b00000;
RS_2_ADDR = 5'b00000;
RD_ADDR = 5'b00000;
WR_EN = 1'b0;
RD = 32'b0;
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
$display("Testing values after reset...");
for(i = 0; i < 32; i=i+1)
begin
RS_1_ADDR = i[4:0];
#20;
if(RS_1 != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("Reset values OK.");
$display("Testing write operation...");
for(i = 0; i < 32; i=i+1)
begin
RD_ADDR = i[4:0];
WR_EN = 1'b1;
RD = $random;
#20;
WR_EN = 1'b0;
RS_1_ADDR = RD_ADDR;
RS_2_ADDR = RD_ADDR;
#20;
if(RD_ADDR == 5'b00000)
begin
if(RS_1 != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RS_2 != 32'h00000000)
begin
$display("FAIL. Check the results.");
$finish;
end
end
if(RD_ADDR != 5'b00000)
begin
if(RS_1 != RD)
begin
$display("FAIL. Check the results.");
$finish;
end
if(RS_2 != RD)
begin
$display("FAIL. Check the results.");
$finish;
end
end
end
$display("Write operation seems to work.");
$display("Integer Register File successfully tested.");
end
 
endmodule
/steelcore/trunk/bench/tb_load_unit.v
0,0 → 1,252
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 20:52:25
// Module Name: tb_load_unit
// Project Name: Steel Core
// Description: RISC-V Steel Core Load Unit testbench
//
// Dependencies: load_unit.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
 
module tb_load_unit();
 
reg [1:0] LOAD_SIZE;
reg LOAD_UNSIGNED;
reg [31:0] DATA_IN;
reg [1:0] IADDER_OUT_1_TO_0;
wire [31:0] OUTPUT;
load_unit dut(
.LOAD_SIZE(LOAD_SIZE),
.LOAD_UNSIGNED(LOAD_UNSIGNED),
.DATA_IN(DATA_IN),
.IADDER_OUT_1_TO_0(IADDER_OUT_1_TO_0),
.OUTPUT(OUTPUT)
);
integer i;
initial
begin
$display("Testing Load Unit...");
$display("Testing Load Unit for LB operation.");
LOAD_SIZE = 2'b00;
LOAD_UNSIGNED = 1'b0;
for(i = 0; i < 10000; i=i+1)
begin
DATA_IN = $random;
IADDER_OUT_1_TO_0 = $random;
#10;
if(IADDER_OUT_1_TO_0 == 2'b00 & OUTPUT != { {24{DATA_IN[7]}} , DATA_IN[7:0]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0 == 2'b01 & OUTPUT != { {24{DATA_IN[15]}} , DATA_IN[15:8]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0 == 2'b10 & OUTPUT != { {24{DATA_IN[23]}} , DATA_IN[23:16]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0 == 2'b11 & OUTPUT != { {24{DATA_IN[31]}} , DATA_IN[31:24]})
begin
$display("FAIL. Wrong result.");
$finish;
end
end
$display("LB operation successfully tested.");
$display("Testing Load Unit for LH operation.");
LOAD_SIZE = 2'b01;
LOAD_UNSIGNED = 1'b0;
for(i = 0; i < 10000; i=i+1)
begin
DATA_IN = $random;
IADDER_OUT_1_TO_0 = $random;
IADDER_OUT_1_TO_0[0] = 1'b0;
#10;
if(IADDER_OUT_1_TO_0[1] == 1'b0 & OUTPUT != { {16{DATA_IN[15]}} , DATA_IN[15:0]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0[1] == 1'b1 & OUTPUT != { {16{DATA_IN[31]}} , DATA_IN[31:16]})
begin
$display("FAIL. Wrong result.");
$finish;
end
end
$display("LH operation successfully tested.");
$display("Testing Load Unit for LW operation.");
LOAD_SIZE = 2'b10;
LOAD_UNSIGNED = 1'b0;
for(i = 0; i < 10000; i=i+1)
begin
DATA_IN = $random;
IADDER_OUT_1_TO_0 = 2'b00;
#10;
if(OUTPUT != DATA_IN[31:0])
begin
$display("FAIL. Wrong result.");
$finish;
end
end
$display("LW operation successfully tested.");
$display("Testing Load Unit for LBU operation.");
LOAD_SIZE = 2'b00;
LOAD_UNSIGNED = 1'b1;
for(i = 0; i < 10000; i=i+1)
begin
DATA_IN = $random;
IADDER_OUT_1_TO_0 = $random;
#10;
if(IADDER_OUT_1_TO_0 == 2'b00 & OUTPUT != { 24'b0 , DATA_IN[7:0]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0 == 2'b01 & OUTPUT != { 24'b0 , DATA_IN[15:8]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0 == 2'b10 & OUTPUT != { 24'b0 , DATA_IN[23:16]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0 == 2'b11 & OUTPUT != { 24'b0 , DATA_IN[31:24]})
begin
$display("FAIL. Wrong result.");
$finish;
end
end
$display("LBU operation successfully tested.");
$display("Testing Load Unit for LHU operation.");
LOAD_SIZE = 2'b01;
LOAD_UNSIGNED = 1'b1;
for(i = 0; i < 10000; i=i+1)
begin
DATA_IN = $random;
IADDER_OUT_1_TO_0 = $random;
IADDER_OUT_1_TO_0[0] = 1'b0;
#10;
if(IADDER_OUT_1_TO_0[1] == 1'b0 & OUTPUT != { 16'b0 , DATA_IN[15:0]})
begin
$display("FAIL. Wrong result.");
$finish;
end
else if(IADDER_OUT_1_TO_0[1] == 1'b1 & OUTPUT != { 16'b0 , DATA_IN[31:16]})
begin
$display("FAIL. Wrong result.");
$finish;
end
end
$display("LHU operation successfully tested.");
$display("Load Unit successfully tested.");
end
endmodule
/steelcore/trunk/bench/tb_machine_mode.v
0,0 → 1,1275
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 02.05.2020 15:45:27
// Module Name: tb_machine_mode
// Project Name: Steel Core
// Description: RISC-V Steel Core Machine Mode testbench
//
// Dependencies: csr_file.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
module tb_machine_mode();
 
reg CLK;
reg RESET;
reg ILLEGAL_INSTR;
reg MISALIGNED_INSTR;
reg MISALIGNED_LOAD;
reg MISALIGNED_STORE;
reg [6:2] OPCODE_6_TO_2;
reg [2:0] FUNCT3;
reg [6:0] FUNCT7;
reg [4:0] RS1_ADDR;
reg [4:0] RS2_ADDR;
reg [4:0] RD_ADDR;
reg E_IRQ;
reg T_IRQ;
reg S_IRQ;
 
reg MIE;
reg MEIE;
reg MTIE;
reg MSIE;
reg MEIP;
reg MTIP;
reg MSIP;
wire I_OR_E;
wire SET_EPC;
wire SET_CAUSE;
wire [3:0] CAUSE;
wire INSTRET_INC;
wire MIE_CLEAR;
wire MIE_SET;
wire [1:0] PC_SRC;
wire FLUSH;
machine_control dut(
 
.CLK(CLK),
.RESET(RESET),
.ILLEGAL_INSTR(ILLEGAL_INSTR),
.MISALIGNED_INSTR(MISALIGNED_INSTR),
.MISALIGNED_LOAD(MISALIGNED_LOAD),
.MISALIGNED_STORE(MISALIGNED_STORE),
.OPCODE_6_TO_2(OPCODE_6_TO_2),
.FUNCT3(FUNCT3),
.FUNCT7(FUNCT7),
.RS1_ADDR(RS1_ADDR),
.RS2_ADDR(RS2_ADDR),
.RD_ADDR(RD_ADDR),
.E_IRQ(E_IRQ),
.T_IRQ(T_IRQ),
.S_IRQ(S_IRQ),
.I_OR_E(I_OR_E),
.SET_CAUSE(SET_CAUSE),
.CAUSE(CAUSE),
.SET_EPC(SET_EPC),
.INSTRET_INC(INSTRET_INC),
.MIE_CLEAR(MIE_CLEAR),
.MIE_SET(MIE_SET),
.MIE(MIE),
.MEIE(MEIE),
.MTIE(MTIE),
.MSIE(MSIE),
.MEIP(MEIP),
.MTIP(MTIP),
.MSIP(MSIP),
.PC_SRC(PC_SRC),
.FLUSH(FLUSH)
 
);
always
begin
#10 CLK = !CLK;
end
initial
begin
$display("Testing Machine Mode Control module...");
CLK = 1'b0;
RESET = 1'b0;
ILLEGAL_INSTR = 1'b0;
MISALIGNED_INSTR = 1'b0;
OPCODE_6_TO_2 = `OPCODE_OP;
FUNCT3 = `FUNCT3_ADD;
FUNCT7 = `FUNCT7_ADD;
RS1_ADDR = 5'b00000;
RS2_ADDR = 5'b00000;
RD_ADDR = 5'b00000;
E_IRQ = 1'b0;
T_IRQ = 1'b0;
S_IRQ = 1'b0;
MIE = 1'b0;
MEIE = 1'b0;
MTIE = 1'b0;
MSIE = 1'b0;
MEIP = 1'b0;
MTIP = 1'b0;
MSIP = 1'b0;
$display("Testing RESET state...");
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
if(PC_SRC != `PC_BOOT)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_SET != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("RESET state values OK.");
#20;
/************************************************************
*************************************************************
************************************************************/
$display("Testing OPERATING state...");
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_SET != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("OPERATING state values OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine keeps in operating state when MIE=0 for all kinds of interrupt...");
E_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
E_IRQ = 1'b0;
T_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
T_IRQ = 1'b0;
S_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
S_IRQ = 1'b0;
$display("Test OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine changes it state when MIE=0 for all kinds of exceptions.");
MIE = 1'b0;
ILLEGAL_INSTR = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0010)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
ILLEGAL_INSTR = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MISALIGNED_INSTR = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0000)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
MISALIGNED_INSTR = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MISALIGNED_LOAD = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0100)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
MISALIGNED_LOAD = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MISALIGNED_STORE = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0110)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
MISALIGNED_STORE = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
OPCODE_6_TO_2 = `OPCODE_SYSTEM;
FUNCT3 = `FUNCT3_ECALL;
FUNCT7 = `FUNCT7_ECALL;
RS1_ADDR = `RS1_ECALL;
RS2_ADDR = `RS2_ECALL;
RD_ADDR = `RD_ECALL;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b1011)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
OPCODE_6_TO_2 = `OPCODE_OP;
FUNCT3 = `FUNCT3_ADD;
FUNCT7 = `FUNCT7_ADD;
RS1_ADDR = 5'b00000;
RS2_ADDR = 5'b00000;
RD_ADDR = 5'b00000;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
OPCODE_6_TO_2 = `OPCODE_SYSTEM;
FUNCT3 = `FUNCT3_EBREAK;
FUNCT7 = `FUNCT7_EBREAK;
RS1_ADDR = `RS1_EBREAK;
RS2_ADDR = `RS2_EBREAK;
RD_ADDR = `RD_EBREAK;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0011)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
OPCODE_6_TO_2 = `OPCODE_OP;
FUNCT3 = `FUNCT3_ADD;
FUNCT7 = `FUNCT7_ADD;
RS1_ADDR = 5'b00000;
RS2_ADDR = 5'b00000;
RD_ADDR = 5'b00000;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Test OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine keeps in operating state when MIE=1 for all types of interrupt when MTIE=0, MSIE=0 and MEIE=0...");
MIE = 1'b1;
E_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
E_IRQ = 1'b0;
T_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
T_IRQ = 1'b0;
S_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
S_IRQ = 1'b0;
$display("Test OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine change its state only for external interrupts in operating state when MIE=1 and MTIE=0, MSIE=0 and MEIE=1...");
MIE = 1'b1;
MEIE = 1'b1;
E_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b1011)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
E_IRQ = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
T_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
T_IRQ = 1'b0;
S_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
S_IRQ = 1'b0;
MEIE = 1'b0;
$display("Test OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine change its state only for timer interrupts in operating state when MIE=1 and MTIE=1, MSIE=0 and MEIE=0...");
MIE = 1'b1;
MTIE = 1'b1;
T_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0111)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
T_IRQ = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
E_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
E_IRQ = 1'b0;
S_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
S_IRQ = 1'b0;
MTIE = 1'b0;
$display("Test OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine change its state only for software interrupts in operating state when MIE=1 and MTIE=0, MSIE=1 and MEIE=0...");
MIE = 1'b1;
MSIE = 1'b1;
S_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0011)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
S_IRQ = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
T_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
T_IRQ = 1'b0;
E_IRQ = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
E_IRQ = 1'b0;
MSIE = 1'b0;
$display("Test OK.");
 
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine change its state only for MEIP in operating state when MIE=1 and MTIE=0, MSIE=0 and MEIE=1...");
MIE = 1'b1;
MEIE = 1'b1;
MEIP = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b1011)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
MEIP = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MTIP = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MTIP = 1'b0;
MSIP = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MSIP = 1'b0;
MEIE = 1'b0;
$display("Test OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine change its state only for MTIP in operating state when MIE=1 and MTIE=1, MSIE=0 and MEIE=0...");
MIE = 1'b1;
MTIE = 1'b1;
MTIP = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0111)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
MTIP = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MEIP = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MEIP = 1'b0;
MSIP = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MSIP = 1'b0;
MTIE = 1'b0;
$display("Test OK.");
/************************************************************
*************************************************************
************************************************************/
$display("Testing if the machine change its state only for MSIP in operating state when MIE=1 and MTIE=0, MSIE=1 and MEIE=0...");
MIE = 1'b1;
MSIE = 1'b1;
MSIP = 1'b1;
#20;
if(PC_SRC != `PC_TRAP)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(CAUSE != 4'b0011)
begin
$display("FAIL. Check the results.");
$finish;
end
if(I_OR_E != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
MSIP = 1'b0;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MTIP = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MTIP = 1'b0;
MEIP = 1'b1;
#20;
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
MEIP = 1'b0;
MSIE = 1'b0;
$display("Test OK.");
 
/************************************************************
*************************************************************
************************************************************/
$display("Testing transition from OPERATING to TRAP RETURN...");
OPCODE_6_TO_2 = `OPCODE_SYSTEM;
FUNCT7 = `FUNCT7_MRET;
FUNCT3 = `FUNCT3_MRET;
RS1_ADDR = `RS1_MRET;
RS2_ADDR = `RS2_MRET;
RD_ADDR = `RD_MRET;
#20;
if(PC_SRC != `PC_EPC)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_SET != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Test OK.");
OPCODE_6_TO_2 = `OPCODE_OP;
FUNCT3 = `FUNCT3_ADD;
FUNCT7 = `FUNCT7_ADD;
RS1_ADDR = 5'b00000;
RS2_ADDR = 5'b00000;
RD_ADDR = 5'b00000;
#20;
/************************************************************
*************************************************************
************************************************************/
$display("Testing transition from TRAP RETURN to OPERATING...");
if(PC_SRC != `PC_NEXT)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_CAUSE != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(SET_EPC != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_CLEAR != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(MIE_SET != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(FLUSH != 1'b0)
begin
$display("FAIL. Check the results.");
$finish;
end
if(INSTRET_INC != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("Test OK.");
$display("Machine Mode Control module successfully tested.");
end
 
endmodule
 
/steelcore/trunk/bench/tb_steel_top.v
0,0 → 1,181
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 20:52:25
// Module Name: tb_steel_top
// Project Name: Steel Core
// Description: RISC-V Steel Core testbench
//
// Dependencies: load_unit.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "../globals.vh"
 
module tb_steel_top();
 
reg CLK;
reg RESET;
wire [31:0] I_ADDR;
reg [31:0] INSTR;
wire [31:0] D_ADDR;
wire [31:0] DATA_OUT;
wire WR_REQ;
wire [3:0] WR_MASK;
reg [31:0] DATA_IN;
reg E_IRQ;
reg T_IRQ;
reg S_IRQ;
 
steel_top dut(
 
.CLK(CLK),
.RESET(RESET),
.REAL_TIME(64'b0),
.I_ADDR(I_ADDR),
.INSTR(INSTR),
.D_ADDR(D_ADDR),
.DATA_OUT(DATA_OUT),
.WR_REQ(WR_REQ),
.WR_MASK(WR_MASK),
.DATA_IN(DATA_IN),
.E_IRQ(E_IRQ),
.T_IRQ(T_IRQ),
.S_IRQ(S_IRQ)
 
);
reg [7:0] ram [0:65535]; // 8KB RAM
integer i;
integer f;
wire [12:0] eff_i_addr;
wire [12:0] eff_d_addr;
assign eff_i_addr = I_ADDR[12:0];
assign eff_d_addr = D_ADDR[12:0];
always
begin
#10 CLK = !CLK;
end
initial
begin
f = $fopen("../../../../../mem/mret.txt","w");
// LOADS PROGRAM INTO MEMORY
for(i = 0; i < 65535; i=i+1) ram[i] = 8'b0;
$readmemh("mret.mem",ram);
// INITIAL VALUES
RESET = 1'b0;
CLK = 1'b0;
E_IRQ = 1'b0;
T_IRQ = 1'b0;
S_IRQ = 1'b0;
// RESET
#5;
RESET = 1'b1;
#15;
RESET = 1'b0;
#800;
$fwrite(f, "%d", ram[1024]);
$fclose(f);
$stop;
end
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
INSTR = {ram[eff_i_addr+3],ram[eff_i_addr+2],ram[eff_i_addr+1],ram[eff_i_addr]};
DATA_IN = {ram[eff_d_addr+3],ram[eff_d_addr+2],ram[eff_d_addr+1],ram[eff_d_addr]};
end
else
begin
INSTR = {ram[eff_i_addr+3],ram[eff_i_addr+2],ram[eff_i_addr+1],ram[eff_i_addr]};
DATA_IN = {ram[eff_d_addr+3],ram[eff_d_addr+2],ram[eff_d_addr+1],ram[eff_d_addr]};
if(WR_REQ)
begin
ram[eff_d_addr] <= DATA_OUT[7:0];
if(WR_MASK[1])
begin
ram[eff_d_addr+1] <= DATA_OUT[15:8];
end
if(WR_MASK[2])
begin
ram[eff_d_addr+2] <= DATA_OUT[23:16];
end
if(WR_MASK[3])
begin
ram[eff_d_addr+3] <= DATA_OUT[31:24];
end
end
else
begin
DATA_IN = {ram[eff_d_addr+3],ram[eff_d_addr+2],ram[eff_d_addr+1],ram[eff_d_addr]};
end
end
end
 
endmodule
/steelcore/trunk/bench/tb_store_unit.v
0,0 → 1,297
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 02.06.2020 16:03:55
// Module Name: tb_store_unit
// Project Name: Steel Core
// Description: RISC-V Steel Core Store Unit testbench
//
// Dependencies: store_unit.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
 
module tb_store_unit();
 
reg [2:0] FUNCT3;
reg [31:0] IADDER_OUT;
reg [31:0] RS2;
reg MEM_WR_REQ;
wire [31:0] DATA_OUT;
wire [31:0] D_ADDR;
wire [3:0] WR_MASK;
wire WR_REQ;
 
store_unit dut(
 
.FUNCT3(FUNCT3[1:0]),
.IADDER_OUT(IADDER_OUT),
.RS2(RS2),
.MEM_WR_REQ(MEM_WR_REQ),
.DATA_OUT(DATA_OUT),
.D_ADDR(D_ADDR),
.WR_MASK(WR_MASK),
.WR_REQ(WR_REQ)
);
integer i;
initial
begin
FUNCT3 = `FUNCT3_BYTE;
RS2 = $random;
MEM_WR_REQ = 1'b0;
$display("Testing D_ADDR generation...");
for(i = 0; i < 20; i=i+1)
begin
IADDER_OUT = $random;
#10;
if(D_ADDR != {IADDER_OUT[31:2], 2'b00})
begin
$display("FAIL. Check the results.");
$finish;
end
end
$display("D_ADDR generation OK.");
$display("Testing SB signals generation...");
FUNCT3 = `FUNCT3_BYTE;
RS2 = $random;
MEM_WR_REQ = 1'b1;
IADDER_OUT[1:0] = 2'b00;
#10;
if(DATA_OUT != {24'b0, RS2[7:0]})
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_MASK != 4'b0001)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
RS2 = $random;
MEM_WR_REQ = 1'b1;
IADDER_OUT[1:0] = 2'b01;
#10;
if(DATA_OUT != {16'b0, RS2[7:0], 8'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_MASK != 4'b0010)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
RS2 = $random;
MEM_WR_REQ = 1'b1;
IADDER_OUT[1:0] = 2'b10;
#10;
if(DATA_OUT != {8'b0, RS2[7:0], 16'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_MASK != 4'b0100)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_BYTE;
RS2 = $random;
MEM_WR_REQ = 1'b1;
IADDER_OUT[1:0] = 2'b11;
#10;
if(DATA_OUT != {RS2[7:0], 24'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_MASK != 4'b1000)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("SB signals generation successfully tested.");
$display("Testing SH signals generation...");
FUNCT3 = `FUNCT3_HALF;
RS2 = $random;
MEM_WR_REQ = 1'b1;
IADDER_OUT[1:0] = 2'b00;
#10;
if(DATA_OUT != {16'b0, RS2[15:0]})
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_MASK != 4'b0011)
begin
$display("FAIL. Check the results.");
$finish;
end
FUNCT3 = `FUNCT3_HALF;
RS2 = $random;
MEM_WR_REQ = 1'b1;
IADDER_OUT[1:0] = 2'b10;
#10;
if(DATA_OUT != {RS2[15:0], 16'b0})
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_MASK != 4'b1100)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("SH signals generation successfully tested.");
$display("Testing SW signals generation...");
FUNCT3 = `FUNCT3_WORD;
RS2 = $random;
MEM_WR_REQ = 1'b1;
IADDER_OUT[1:0] = 2'b00;
#10;
if(DATA_OUT != RS2)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_REQ != 1'b1)
begin
$display("FAIL. Check the results.");
$finish;
end
if(WR_MASK != 4'b1111)
begin
$display("FAIL. Check the results.");
$finish;
end
$display("SW signals generation successfully tested.");
end
 
endmodule
/steelcore/trunk/alu.v
0,0 → 1,116
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 30.03.2020 17:28:42
// Module Name: alu
// Project Name: Steel Core
// Description: 32-bit Arithmetic and Logic Unit
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module alu(
 
input wire [31:0] OP_1,
input wire [31:0] OP_2,
input wire [3:0] OPCODE,
output reg [31:0] RESULT
 
);
wire signed [31:0] signed_op1;
wire signed [31:0] adder_op2;
wire [31:0] minus_op2;
wire [31:0] sra_result;
wire [31:0] srl_result;
wire [31:0] shr_result;
wire slt_result;
wire sltu_result;
reg [31:0] pre_result;
assign signed_op1 = OP_1;
assign minus_op2 = -OP_2;
assign adder_op2 = OPCODE[3] == 1'b1 ? minus_op2 : OP_2;
assign sra_result = signed_op1 >>> OP_2[4:0];
assign srl_result = OP_1 >> OP_2[4:0];
assign shr_result = OPCODE[3] == 1'b1 ? sra_result : srl_result;
assign sltu_result = OP_1 < OP_2;
assign slt_result = OP_1[31] ^ OP_2[31] ? OP_1[31] : sltu_result;
 
always @*
begin
case(OPCODE[2:0])
`FUNCT3_ADD: RESULT = OP_1 + adder_op2;
`FUNCT3_SRL: RESULT = shr_result;
`FUNCT3_OR: RESULT = OP_1 | OP_2;
`FUNCT3_AND: RESULT = OP_1 & OP_2;
`FUNCT3_XOR: RESULT = OP_1 ^ OP_2;
`FUNCT3_SLT: RESULT = {31'b0, slt_result};
`FUNCT3_SLTU: RESULT = {31'b0, sltu_result};
`FUNCT3_SLL: RESULT = OP_1 << OP_2[4:0];
endcase
end
endmodule
/steelcore/trunk/branch_unit.v
0,0 → 1,120
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 18:29:52
// Module Name: branch_unit
// Project Name: Steel Core
// Description: RISC-V Steel Core Branch Decision Unit
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module branch_unit(
 
input wire [6:2] OPCODE_6_TO_2,
input wire [2:0] FUNCT3,
input wire [31:0] RS1,
input wire [31:0] RS2,
output wire BRANCH_TAKEN
);
wire pc_mux_sel;
wire pc_mux_sel_en;
wire is_branch;
wire is_jal;
wire is_jalr;
wire is_jump;
wire eq;
wire ne;
wire lt;
wire ge;
wire ltu;
wire geu;
reg take;
 
assign is_jal = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & ~OPCODE_6_TO_2[4] & OPCODE_6_TO_2[3] & OPCODE_6_TO_2[2];
assign is_jalr = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & ~OPCODE_6_TO_2[4] & ~OPCODE_6_TO_2[3] & OPCODE_6_TO_2[2];
assign is_jump = is_jal | is_jalr;
assign eq = (RS1 == RS2);
assign ne = !eq;
assign lt = RS1[31] ^ RS2[31] ? RS1[31] : ltu;
assign ge = !lt;
assign ltu = (RS1 < RS2);
assign geu = !ltu;
assign is_branch = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & ~OPCODE_6_TO_2[4] & ~OPCODE_6_TO_2[3] & ~OPCODE_6_TO_2[2];
assign pc_mux_sel_en = is_branch | is_jal | is_jalr;
assign pc_mux_sel = (is_jump == 1'b1) ? 1'b1 : take;
assign BRANCH_TAKEN = pc_mux_sel_en & pc_mux_sel;
always @(*)
begin
case (FUNCT3)
3'b000: take = eq;
3'b001: take = ne;
3'b100: take = lt;
3'b101: take = ge;
3'b110: take = ltu;
3'b111: take = geu;
default: take = 1'b0;
endcase
end
endmodule
/steelcore/trunk/control_unit.v
0,0 → 1,161
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 25.04.2020 14:49:16
// Module Name: control_unit
// Project Name: Steel Core
// Description: Decodes the instruction and generates control signals
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module control_unit(
 
input wire [6:0] OPCODE,
input wire FUNCT7_5,
input wire [2:0] FUNCT3,
input wire [1:0] IADDER_OUT_1_TO_0,
output wire [3:0] ALU_OPCODE,
output wire MEM_WR_REQ,
output wire [1:0] LOAD_SIZE,
output wire LOAD_UNSIGNED,
output wire ALU_SRC,
output wire IADDER_SRC,
output wire CSR_WR_EN,
output wire RF_WR_EN,
output wire [2:0] WB_MUX_SEL,
output wire [2:0] IMM_TYPE,
output wire [2:0] CSR_OP,
output wire ILLEGAL_INSTR,
output wire MISALIGNED_LOAD,
output wire MISALIGNED_STORE
 
);
wire is_branch;
wire is_jal;
wire is_jalr;
wire is_auipc;
wire is_lui;
wire is_load;
wire is_store;
wire is_system;
wire is_csr;
wire is_op;
wire is_op_imm;
wire is_misc_mem;
wire is_addi;
wire is_slti;
wire is_sltiu;
wire is_andi;
wire is_ori;
wire is_xori;
wire is_addiw;
wire is_implemented_instr;
wire mal_word;
wire mal_half;
wire misaligned;
assign LOAD_SIZE[0] = FUNCT3[0];
assign LOAD_SIZE[1] = FUNCT3[1];
assign LOAD_UNSIGNED = FUNCT3[2];
assign ALU_SRC = OPCODE[5];
assign is_branch = OPCODE[6] & OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & ~OPCODE[2];
assign is_jal = OPCODE[6] & OPCODE[5] & ~OPCODE[4] & OPCODE[3] & OPCODE[2];
assign is_jalr = OPCODE[6] & OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & OPCODE[2];
assign is_auipc = ~OPCODE[6] & ~OPCODE[5] & OPCODE[4] & ~OPCODE[3] & OPCODE[2];
assign is_lui = ~OPCODE[6] & OPCODE[5] & OPCODE[4] & ~OPCODE[3] & OPCODE[2];
assign is_op = ~OPCODE[6] & OPCODE[5] & OPCODE[4] & ~OPCODE[3] & ~OPCODE[2];
assign is_op_imm = ~OPCODE[6] & ~OPCODE[5] & OPCODE[4] & ~OPCODE[3] & ~OPCODE[2];
assign is_addi = is_op_imm & ~FUNCT3[2] & ~FUNCT3[1] & ~FUNCT3[0];
assign is_slti = is_op_imm & ~FUNCT3[2] & FUNCT3[1] & ~FUNCT3[0];
assign is_sltiu = is_op_imm & ~FUNCT3[2] & FUNCT3[1] & FUNCT3[0];
assign is_andi = is_op_imm & FUNCT3[2] & FUNCT3[1] & FUNCT3[0];
assign is_ori = is_op_imm & FUNCT3[2] & FUNCT3[1] & ~FUNCT3[0];
assign is_xori = is_op_imm & FUNCT3[2] & ~FUNCT3[1] & ~FUNCT3[0];
assign is_load = ~OPCODE[6] & ~OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & ~OPCODE[2];
assign is_store = ~OPCODE[6] & OPCODE[5] & ~OPCODE[4] & ~OPCODE[3] & ~OPCODE[2];
assign is_system = OPCODE[6] & OPCODE[5] & OPCODE[4] & ~OPCODE[3] & ~OPCODE[2];
assign is_misc_mem = ~OPCODE[6] & ~OPCODE[5] & ~OPCODE[4] & OPCODE[3] & OPCODE[2];
assign is_csr = is_system & (FUNCT3[2] | FUNCT3[1] | FUNCT3[0]);
assign IADDER_SRC = is_load | is_store | is_jalr;
assign RF_WR_EN = is_lui | is_auipc | is_jalr | is_jal | is_op | is_load | is_csr | is_op_imm;
assign CSR_WR_EN = is_csr;
assign ALU_OPCODE[2:0] = FUNCT3;
assign ALU_OPCODE[3] = FUNCT7_5 & ~(is_addi | is_slti | is_sltiu | is_andi | is_ori | is_xori);
assign WB_MUX_SEL[0] = is_load | is_auipc | is_jal | is_jalr;
assign WB_MUX_SEL[1] = is_lui | is_auipc;
assign WB_MUX_SEL[2] = is_csr | is_jal | is_jalr;
assign IMM_TYPE[0] = is_op_imm | is_load | is_jalr | is_branch | is_jal;
assign IMM_TYPE[1] = is_store | is_branch | is_csr;
assign IMM_TYPE[2] = is_lui | is_auipc | is_jal | is_csr;
assign CSR_OP = FUNCT3;
assign is_implemented_instr = is_op | is_op_imm | is_branch | is_jal | is_jalr | is_auipc | is_lui | is_system | is_misc_mem | is_load | is_store;
assign ILLEGAL_INSTR = ~OPCODE[1] | ~OPCODE[0] | ~is_implemented_instr;
assign mal_word = FUNCT3[1] & ~FUNCT3[0] & (IADDER_OUT_1_TO_0[1] | IADDER_OUT_1_TO_0[0]);
assign mal_half = ~FUNCT3[1] & FUNCT3[0] & IADDER_OUT_1_TO_0[0];
assign misaligned = mal_word | mal_half;
assign MISALIGNED_STORE = is_store & misaligned;
assign MISALIGNED_LOAD = is_load & misaligned;
assign MEM_WR_REQ = is_store & ~misaligned;
endmodule
/steelcore/trunk/csr_file.v
0,0 → 1,397
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 23:33:34
// Module Name: csr_file
// Project Name: Steel Core
// Description: RISC-V Steel Core CSR Register File
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module csr_file(
 
input wire CLK,
input wire RESET,
input wire WR_EN,
input wire [11:0] CSR_ADDR,
input wire [2:0] CSR_OP,
input wire [4:0] CSR_UIMM,
input wire [31:0] CSR_DATA_IN,
output reg [31:0] CSR_DATA_OUT,
// from pipeline stage 1
input wire [31:0] PC,
// interface with CLIC
input wire E_IRQ,
input wire T_IRQ,
input wire S_IRQ,
// interface with Machine Control Module
input wire I_OR_E,
input wire SET_CAUSE,
input wire [3:0] CAUSE_IN,
input wire SET_EPC,
input wire INSTRET_INC,
input wire MIE_CLEAR,
input wire MIE_SET,
output reg MIE,
output wire MEIE_OUT,
output wire MTIE_OUT,
output wire MSIE_OUT,
output wire MEIP_OUT,
output wire MTIP_OUT,
output wire MSIP_OUT,
// platform real time CLK value
input wire [63:0] REAL_TIME,
// these two outputs are connected to the PC MUX
output wire [31:0] EPC_OUT,
output wire [31:0] TRAP_ADDRESS
 
);
 
// Machine trap setup
wire [31:0] mstatus; // machine status register
wire [31:0] misa; // machine ISA register
wire [31:0] mie_reg; // machine interrupt enable register
wire [31:0] mtvec;
wire [1:0] mxl; // machine XLEN
wire [25:0] mextensions; // ISA extensions
reg [1:0] mtvec_mode; // machine trap mode
reg [29:0] mtvec_base; // machine trap base address
reg mpie; // mach. prior interrupt enable
reg meie; // mach. external interrupt enable
reg mtie; // mach. timer interrupt enable
reg msie; // mach. software interrupt enable
 
// Machine trap handling
reg [31:0] mscratch; // machine scratch register
reg [31:0] mepc; // machine exception program counter
reg [31:0] mtval; // machine trap value register
wire [31:0] mcause; // machine trap cause register
wire [31:0] mip_reg; // machine interrupt pending register
reg int_or_exc; // interrupt or exception signal
reg [3:0] cause; // interrupt cause
reg [26:0] cause_rem; // remaining bits of mcause register
reg meip; // mach. external interrupt pending
reg mtip; // mach. timer interrupt pending
reg msip; // mach. software interrupt pending
 
// Machine counters
reg [63:0] mcycle;
reg [63:0] mtime;
reg [63:0] minstret;
 
// Machine counters setup
wire [31:0] mcountinhibit;
reg mcountinhibit_cy;
reg mcountinhibit_ir;
 
// CSR operation control
// ----------------------------------------------------------------------------
 
reg [31:0] data_wr;
wire [31:0] pre_data;
 
assign pre_data = CSR_OP[2] == 1'b1 ? {27'b0, CSR_UIMM} : CSR_DATA_IN;
 
always @*
begin
case(CSR_OP[1:0])
`CSR_RW: data_wr <= pre_data;
`CSR_RS: data_wr <= CSR_DATA_OUT | pre_data;
`CSR_RC: data_wr <= CSR_DATA_OUT & ~pre_data;
`CSR_NOP: data_wr <= CSR_DATA_OUT;
endcase
end
 
always @*
begin
case(CSR_ADDR)
`CYCLE: CSR_DATA_OUT = mcycle[31:0];
`CYCLEH: CSR_DATA_OUT = mcycle[63:32];
`TIME: CSR_DATA_OUT = mtime[31:0];
`TIMEH: CSR_DATA_OUT = mtime[63:32];
`INSTRET: CSR_DATA_OUT = minstret[31:0];
`INSTRETH: CSR_DATA_OUT = minstret[63:32];
`MSTATUS: CSR_DATA_OUT = mstatus;
`MISA: CSR_DATA_OUT = misa;
`MIE: CSR_DATA_OUT = mie_reg;
`MTVEC: CSR_DATA_OUT = mtvec;
`MSCRATCH: CSR_DATA_OUT = mscratch;
`MEPC: CSR_DATA_OUT = mepc;
`MCAUSE: CSR_DATA_OUT = mcause;
`MTVAL: CSR_DATA_OUT = mtval;
`MIP: CSR_DATA_OUT = mip_reg;
`MCYCLE: CSR_DATA_OUT = mcycle[31:0];
`MCYCLEH: CSR_DATA_OUT = mcycle[63:32];
`MINSTRET: CSR_DATA_OUT = minstret[31:0];
`MINSTRETH: CSR_DATA_OUT = minstret[63:32];
`MCOUNTINHIBIT: CSR_DATA_OUT = mcountinhibit;
default: CSR_DATA_OUT = 32'b0;
endcase
end
 
// MSTATUS register
// MPP
assign mstatus = {19'b0, 2'b11, 3'b0, mpie, 3'b0 , MIE, 3'b0};
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
MIE <= 1'b0;
mpie <= 1'b1;
end
else if(CSR_ADDR == `MSTATUS && WR_EN)
begin
MIE <= data_wr[3];
mpie <= data_wr[7];
end
else if(MIE_CLEAR == 1'b1)
begin
mpie <= MIE;
MIE <= 1'b0;
end
else if(MIE_SET == 1'b1)
begin
MIE <= mpie;
mpie <= 1'b1;
end
end
 
// MISA register
assign mxl = 2'b01;
assign mextensions = 26'b00000000000000000100000000;
assign misa = {mxl, 4'b0, mextensions};
 
// MIE register
assign mie_reg = {20'b0, meie, 3'b0, mtie, 3'b0, msie, 3'b0};
assign MEIE_OUT = meie;
assign MTIE_OUT = mtie;
assign MSIE_OUT = msie;
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
meie <= 1'b0;
mtie <= 1'b0;
msie <= 1'b0;
end
else if(CSR_ADDR == `MIE && WR_EN)
begin
meie <= data_wr[11];
mtie <= data_wr[7];
msie <= data_wr[3];
end
end
// MTVEC register
assign mtvec = {mtvec_base, mtvec_mode};
wire [31:0] trap_mux_out;
wire [31:0] vec_mux_out;
wire [31:0] base_offset;
assign base_offset = cause << 2;
assign trap_mux_out = int_or_exc ? vec_mux_out : {mtvec_base, 2'b00};
assign vec_mux_out = mtvec[0] ? {mtvec_base, 2'b00} + base_offset : {mtvec_base, 2'b00};
assign TRAP_ADDRESS = trap_mux_out;
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
mtvec_mode <= `MTVEC_MODE_RESET;
mtvec_base <= `MTVEC_BASE_RESET;
end
else if(CSR_ADDR == `MTVEC && WR_EN)
begin
mtvec_mode <= data_wr[1:0];
mtvec_base <= data_wr[31:2];
end
end
// MSCRATCH register
always @(posedge CLK or posedge RESET)
begin
if(RESET) mscratch <= `MSCRATCH_RESET;
else if(CSR_ADDR == `MSCRATCH && WR_EN) mscratch <= data_wr;
end
// MEPC register
assign EPC_OUT = mepc;
always @(posedge CLK or posedge RESET)
begin
if(RESET) mepc <= `MEPC_RESET;
else if(SET_EPC) mepc <= PC;
else if(CSR_ADDR == `MEPC && WR_EN) mepc <= {data_wr[31:2], 2'b00};
end
 
// MCAUSE register
assign mcause = {int_or_exc, cause_rem, cause};
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
cause <= 4'b0000;
cause_rem <= 27'b0;
int_or_exc <= 1'b0;
end
else if(SET_CAUSE)
begin
cause <= CAUSE_IN;
cause_rem <= 27'b0;
int_or_exc <= I_OR_E;
end
else if(CSR_ADDR == `MCAUSE && WR_EN)
begin
cause <= data_wr[3:0];
cause_rem <= data_wr[30:4];
int_or_exc <= data_wr[31];
end
end
// MIP register
assign mip_reg = {20'b0, meip, 3'b0, mtip, 3'b0, msip, 3'b0};
assign MEIP_OUT = meip;
assign MTIP_OUT = mtip;
assign MSIP_OUT = msip;
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
meip <= 1'b0;
mtip <= 1'b0;
msip <= 1'b0;
end
else
begin
meip <= E_IRQ;
mtip <= T_IRQ;
msip <= S_IRQ;
end
end
// MTVAL register
always @(posedge CLK or posedge RESET)
begin
if(RESET) mtval <= 32'b0;
else if(SET_CAUSE) mtval <= 32'b0;
else if(CSR_ADDR == `MTVAL && WR_EN) mtval <= data_wr;
end
// MCOUNTINHIBIT register
assign mcountinhibit = {29'b0, mcountinhibit_ir, 1'b0, mcountinhibit_cy};
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
mcountinhibit_cy <= `MCOUNTINHIBIT_CY_RESET;
mcountinhibit_ir <= `MCOUNTINHIBIT_IR_RESET;
end
else if(CSR_ADDR == `MCOUNTINHIBIT && WR_EN)
begin
mcountinhibit_cy <= data_wr[2];
mcountinhibit_ir <= data_wr[0];
end
end
// Counters
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
mcycle <= {`MCYCLEH_RESET, `MCYCLE_RESET};
minstret <= {`MINSTRETH_RESET, `MINSTRET_RESET};
mtime <= {`TIMEH_RESET, `TIME_RESET};
end
else
begin
mtime <= REAL_TIME;
if(CSR_ADDR == `MCYCLE && WR_EN)
begin
mcycle[31:0] <= data_wr;
end
else if(CSR_ADDR == `MCYCLEH && WR_EN)
begin
mcycle[63:32] <= data_wr;
end
else
begin
if(mcountinhibit_cy == 1'b0) mcycle <= mcycle + 1;
end
if(CSR_ADDR == `MINSTRET && WR_EN)
begin
minstret[31:0] <= data_wr;
end
else if(CSR_ADDR == `MINSTRETH && WR_EN)
begin
minstret[63:32] <= data_wr;
end
else
begin
if(mcountinhibit_ir == 1'b0) minstret <= minstret + INSTRET_INC;
end
end
end
endmodule
/steelcore/trunk/globals.vh
0,0 → 1,281
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 30.03.2020 17:28:42
// Module Name: -
// Project Name: STEM
// Description: RISC-V STEM Global Definitions
//
// Dependencies: -
//
// Revision:
// Revision 5.01 - Refactoring #5
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`ifndef GLOBALS_H
`define GLOBALS_H
 
// -------------------------------------------------------------------------------
// SETUP
// -------------------------------------------------------------------------------
 
// Boot address
`define BOOT_ADDRESS 32'h00000000
 
// CSR registers reset values
`define MCYCLE_RESET 32'h00000000
`define TIME_RESET 32'h00000000
`define MINSTRET_RESET 32'h00000000
`define MCYCLEH_RESET 32'h00000000
`define TIMEH_RESET 32'h00000000
`define MINSTRETH_RESET 32'h00000000
`define MTVEC_BASE_RESET 30'b00000000_00000000_00000000_000000
`define MTVEC_MODE_RESET 2'b00
`define MSCRATCH_RESET 32'h00000000
`define MEPC_RESET 32'h00000000
`define MCOUNTINHIBIT_CY_RESET 1'b0
`define MCOUNTINHIBIT_IR_RESET 1'b0
 
 
// -------------------------------------------------------------------------------
// WARNING: THE VALUES BELOW MUST NOT BE MODIFIED
// -------------------------------------------------------------------------------
 
// Implemented instructions opcodes
 
`define NOP_INSTR 32'b000000000000_00000_000_00000_0010011
`define OPCODE_OP 5'b01100
`define OPCODE_OP_IMM 5'b00100
`define OPCODE_LOAD 5'b00000
`define OPCODE_STORE 5'b01000
`define OPCODE_BRANCH 5'b11000
`define OPCODE_JAL 5'b11011
`define OPCODE_JALR 5'b11001
`define OPCODE_LUI 5'b01101
`define OPCODE_AUIPC 5'b00101
`define OPCODE_MISC_MEM 5'b00011
`define OPCODE_SYSTEM 5'b11100
 
// funct7 and funct3 for logic and arithmetic instructions
 
`define FUNCT7_SUB 7'b0100000
`define FUNCT7_SRA 7'b0100000
`define FUNCT7_ADD 7'b0000000
`define FUNCT7_SLT 7'b0000000
`define FUNCT7_SLTU 7'b0000000
`define FUNCT7_AND 7'b0000000
`define FUNCT7_OR 7'b0000000
`define FUNCT7_XOR 7'b0000000
`define FUNCT7_SLL 7'b0000000
`define FUNCT7_SRL 7'b0000000
`define FUNCT7_SRAI 7'b0100000
`define FUNCT7_ADDI 7'bxxxxxxx
`define FUNCT7_SLTI 7'bxxxxxxx
`define FUNCT7_SLTIU 7'bxxxxxxx
`define FUNCT7_ANDI 7'bxxxxxxx
`define FUNCT7_ORI 7'bxxxxxxx
`define FUNCT7_XORI 7'bxxxxxxx
`define FUNCT7_SLLI 7'b0000000
`define FUNCT7_SRLI 7'b0000000
 
`define FUNCT3_ADD 3'b000
`define FUNCT3_SUB 3'b000
`define FUNCT3_SLT 3'b010
`define FUNCT3_SLTU 3'b011
`define FUNCT3_AND 3'b111
`define FUNCT3_OR 3'b110
`define FUNCT3_XOR 3'b100
`define FUNCT3_SLL 3'b001
`define FUNCT3_SRL 3'b101
`define FUNCT3_SRA 3'b101
 
// ALU operations encoding
 
`define ALU_ADD 4'b0000
`define ALU_SUB 4'b1000
`define ALU_SLT 4'b0010
`define ALU_SLTU 4'b0011
`define ALU_AND 4'b0111
`define ALU_OR 4'b0110
`define ALU_XOR 4'b0100
`define ALU_SLL 4'b0001
`define ALU_SRL 4'b0101
`define ALU_SRA 4'b1101
 
// funct7 and funct3 for other instructions
 
`define FUNCT7_ECALL 7'b0000000
`define FUNCT7_EBREAK 7'b0000000
`define FUNCT7_MRET 7'B0011000
 
`define FUNCT3_CSRRW 3'b001
`define FUNCT3_CSRRS 3'b010
`define FUNCT3_CSRRC 3'b011
`define FUNCT3_CSRRWI 3'b101
`define FUNCT3_CSRRSI 3'b110
`define FUNCT3_CSRRCI 3'b111
 
`define FUNCT3_BEQ 3'b000
`define FUNCT3_BNE 3'b001
`define FUNCT3_BLT 3'b100
`define FUNCT3_BGE 3'b101
`define FUNCT3_BLTU 3'b110
`define FUNCT3_BGEU 3'b111
 
`define FUNCT3_ECALL 3'b000
`define FUNCT3_EBREAK 3'b000
`define FUNCT3_MRET 3'b000
`define FUNCT3_WFI 3'b000
 
`define FUNCT3_BYTE 3'b000
`define FUNCT3_HALF 3'b001
`define FUNCT3_WORD 3'b010
`define FUNCT3_BYTE_U 3'b100
`define FUNCT3_HALF_U 3'b101
 
// rd, rs1 and rs2 values for SYSTEM instructions
 
`define RS1_ECALL 5'b00000
`define RS1_EBREAK 5'b00000
`define RS1_MRET 5'b00000
`define RS1_WFI 5'b00000
 
`define RS2_ECALL 5'b00000
`define RS2_EBREAK 5'b00001
`define RS2_MRET 5'b00010
`define RS2_WFI 5'b00101
 
`define RD_ECALL 5'b00000
`define RD_EBREAK 5'b00000
`define RD_MRET 5'b00000
`define RD_WFI 5'b00000
 
// writeback selection
`define WB_ALU 3'b000
`define WB_LU 3'b001
`define WB_IMM 3'b010
`define WB_IADDER_OUT 3'b011
`define WB_CSR 3'b100
`define WB_PC_PLUS 3'b101
 
// immediate format selection
 
`define R_TYPE 3'b000
`define I_TYPE 3'b001
`define S_TYPE 3'b010
`define B_TYPE 3'b011
`define U_TYPE 3'b100
`define J_TYPE 3'b101
`define CSR_TYPE 3'b110
 
// PC MUX selection
 
`define PC_BOOT 2'b00
`define PC_EPC 2'b01
`define PC_TRAP 2'b10
`define PC_NEXT 2'b11
 
// mask for byte-writes
 
`define WR_MASK_BYTE 4'b0001
`define WR_MASK_HALF 4'b0011
`define WR_MASK_WORD 4'b1111
 
// load unit control encoding
 
`define LOAD_BYTE 2'b00
`define LOAD_HALF 2'b01
`define LOAD_WORD 2'b10
 
// CSR File operation encoding
 
`define CSR_NOP 2'b00
`define CSR_RW 2'b01
`define CSR_RS 2'b10
`define CSR_RC 2'b11
 
// CSR ADDRESSES ----------------------------
 
// Performance Counters
`define CYCLE 12'hC00
`define TIME 12'hC01
`define INSTRET 12'hC02
`define CYCLEH 12'hC80
`define TIMEH 12'hC81
`define INSTRETH 12'hC82
 
// Machine Trap Setup
`define MSTATUS 12'h300
`define MISA 12'h301
`define MIE 12'h304
`define MTVEC 12'h305
 
// Machine Trap Handling
`define MSCRATCH 12'h340
`define MEPC 12'h341
`define MCAUSE 12'h342
`define MTVAL 12'h343
`define MIP 12'h344
 
// Machine Counter / Timers
`define MCYCLE 12'hB00
`define MINSTRET 12'hB02
`define MCYCLEH 12'hB80
`define MINSTRETH 12'hB82
 
// Machine Counter Setup
`define MCOUNTINHIBIT 12'h320
 
`endif
/steelcore/trunk/imm_generator.v
0,0 → 1,105
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 22:01:22
// Module Name: imm_generator
// Project Name: Steel Core
// Description: Generates the immediate according with the instruction
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module imm_generator(
input wire [31:7] INSTR,
input wire [2:0] IMM_TYPE,
output reg [31:0] IMM
);
wire [31:0] i_type;
wire [31:0] s_type;
wire [31:0] b_type;
wire [31:0] u_type;
wire [31:0] j_type;
wire [31:0] csr_type;
assign i_type = { {20{INSTR[31]}}, INSTR[31:20] };
assign s_type = { {20{INSTR[31]}}, INSTR[31:25], INSTR[11:7] };
assign b_type = { {19{INSTR[31]}}, INSTR[31], INSTR[7], INSTR[30:25], INSTR[11:8], 1'b0 };
assign u_type = { INSTR[31:12], 12'h000 };
assign j_type = { {11{INSTR[31]}}, INSTR[31], INSTR[19:12], INSTR[20], INSTR[30:21], 1'b0 };
assign csr_type = { 27'b0, INSTR[19:15] };
always @(*)
begin
case (IMM_TYPE)
3'b000: IMM = i_type;
`I_TYPE: IMM = i_type;
`S_TYPE: IMM = s_type;
`B_TYPE: IMM = b_type;
`U_TYPE: IMM = u_type;
`J_TYPE: IMM = j_type;
`CSR_TYPE: IMM = csr_type;
3'b111: IMM = i_type;
endcase
end
endmodule
/steelcore/trunk/integer_file.v
0,0 → 1,137
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 02.04.2020 23:23:16
// Module Name: register_file
// Project Name: Steel Core
// Description: RISC-V Steel Core 32-bit Integer Register File
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module integer_file(
input wire CLK,
input wire RESET,
// connections with pipeline stage 2
input wire [4:0] RS_1_ADDR,
input wire [4:0] RS_2_ADDR,
output wire [31:0] RS_1,
output wire [31:0] RS_2,
// connections with pipeline stage 3
input wire [4:0] RD_ADDR,
input wire WR_EN,
input wire [31:0] RD
 
);
wire [31:0] data_out [31:0];
wire [31:0] rs1_wire;
wire [31:0] rs2_wire;
wire [31:1] enable;
wire fwd_op1_enable;
wire fwd_op2_enable;
wire fwd_op1_zero;
wire fwd_op2_zero;
wire [31:0] reg_en;
reg [31:0] rs1_reg;
reg [31:0] rs2_reg;
wire rs1_addr_is_x0;
wire rs2_addr_is_x0;
reg [31:0] Q [31:1];
genvar i;
generate
for(i = 1; i < 32; i=i+1)
begin:regn
and and_en(enable[i], reg_en[i], WR_EN);
always @(posedge CLK or posedge RESET)
begin
if(RESET) Q[i] <= 32'h00000000;
else if(enable[i]) Q[i] <= RD;
end
assign data_out[i] = Q[i];
end
endgenerate
assign data_out[0] = 32'h00000000;
always @(*)
begin
rs1_reg = data_out[RS_1_ADDR];
rs2_reg = data_out[RS_2_ADDR];
end
assign reg_en = 32'h00000001 << RD_ADDR;
assign rs1_addr_is_x0 = RS_1_ADDR == 5'b00000;
assign rs2_addr_is_x0 = RS_2_ADDR == 5'b00000;
assign fwd_op1_enable = RS_1_ADDR == RD_ADDR ? 1'b1 : 1'b0;
assign fwd_op2_enable = RS_2_ADDR == RD_ADDR ? 1'b1 : 1'b0;
assign fwd_op1_zero = rs1_addr_is_x0 == 1'b1 ? 1'b1 : 1'b0;
assign fwd_op2_zero = rs2_addr_is_x0 == 1'b1 ? 1'b1 : 1'b0;
assign rs1_wire = fwd_op1_enable == 1'b1 ? RD : rs1_reg;
assign rs2_wire = fwd_op2_enable == 1'b1 ? RD : rs2_reg;
assign RS_1 = fwd_op1_zero == 1'b1 ? 32'h00000000 : rs1_wire;
assign RS_2 = fwd_op2_zero == 1'b1 ? 32'h00000000 : rs2_wire;
endmodule
/steelcore/trunk/load_unit.v
0,0 → 1,127
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 20:30:54
// Module Name: load_unit
// Project Name: Steel Core
// Description: Sign extends the data read from memory
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module load_unit(
 
input wire [1:0] LOAD_SIZE,
input wire LOAD_UNSIGNED,
input wire [31:0] DATA_IN,
input wire [1:0] IADDER_OUT_1_TO_0,
output reg [31:0] OUTPUT
);
reg [7:0] byte;
reg [15:0] half;
wire [23:0] byte_ext;
wire [15:0] half_ext;
always @*
begin
case(LOAD_SIZE)
2'b00: OUTPUT = {byte_ext, byte};
2'b01: OUTPUT = {half_ext, half};
2'b10: OUTPUT = DATA_IN;
2'b11: OUTPUT = DATA_IN;
endcase
end
always @*
begin
case(IADDER_OUT_1_TO_0)
2'b00: byte = DATA_IN[7:0];
2'b01: byte = DATA_IN[15:8];
2'b10: byte = DATA_IN[23:16];
2'b11: byte = DATA_IN[31:24];
endcase
end
always @*
begin
case(IADDER_OUT_1_TO_0[1])
1'b0: half = DATA_IN[15:0];
1'b1: half = DATA_IN[31:16];
endcase
end
assign byte_ext = LOAD_UNSIGNED == 1'b1 ? 24'b0 : {24{byte[7]}};
assign half_ext = LOAD_UNSIGNED == 1'b1 ? 16'b0 : {16{half[15]}};
endmodule
/steelcore/trunk/machine_control.v
0,0 → 1,320
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 26.04.2020 23:18:08
// Module Name: machine_control
// Project Name: Steel Core
// Description: Controls the M-mode operation
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module machine_control(
 
input wire CLK,
input wire RESET,
// from control unit
input wire ILLEGAL_INSTR,
input wire MISALIGNED_LOAD,
input wire MISALIGNED_STORE,
// from pipeline stage 1
input wire MISALIGNED_INSTR,
// from instruction
input wire [6:2] OPCODE_6_TO_2,
input wire [2:0] FUNCT3,
input wire [6:0] FUNCT7,
input wire [4:0] RS1_ADDR,
input wire [4:0] RS2_ADDR,
input wire [4:0] RD_ADDR,
// from interrupt controller
input wire E_IRQ,
input wire T_IRQ,
input wire S_IRQ,
 
// from CSR file
input wire MIE,
input wire MEIE,
input wire MTIE,
input wire MSIE,
input wire MEIP,
input wire MTIP,
input wire MSIP,
// to CSR file
output reg I_OR_E,
output reg SET_EPC,
output reg SET_CAUSE,
output reg [3:0] CAUSE,
output reg INSTRET_INC,
output reg MIE_CLEAR,
output reg MIE_SET,
// to PC MUX
output reg [1:0] PC_SRC,
// to pipeline stage 2 register
output reg FLUSH
 
);
// state registers
reg [3:0] curr_state;
reg [3:0] next_state;
// machine states
parameter STATE_RESET = 2'b00;
parameter STATE_OPERATING = 2'b01;
parameter STATE_TRAP_TAKEN = 2'b10;
parameter STATE_TRAP_RETURN = 2'b11;
// internal control signals
wire exception;
wire ip;
wire eip;
wire tip;
wire sip;
wire is_system;
wire RS1_ADDR_zero;
wire RS2_ADDR_zero;
wire rd_zero;
wire RS2_ADDR_wfi;
wire RS2_ADDR_mret;
wire RS2_ADDR_ebreak;
wire FUNCT3_zero;
wire FUNCT7_zero;
wire FUNCT7_wfi;
wire FUNCT7_mret;
wire wfi;
wire csr;
wire mret;
wire ecall;
wire ebreak;
reg pre_instret_inc;
// COMBINATIONAL LOGIC -------------------------------------------
assign is_system = OPCODE_6_TO_2[6] & OPCODE_6_TO_2[5] & OPCODE_6_TO_2[4] & ~OPCODE_6_TO_2[3] & ~OPCODE_6_TO_2[2];
assign FUNCT3_zero = ~(FUNCT3[2] | FUNCT3[1] | FUNCT3[0]);
assign FUNCT7_zero = ~(FUNCT7[6] | FUNCT7[5] | FUNCT7[4] | FUNCT7[3] | FUNCT7[2] | FUNCT7[1] | FUNCT7[0]);
assign FUNCT7_wfi = ~FUNCT7[6] & ~FUNCT7[5] & ~FUNCT7[4] & FUNCT7[3] & ~FUNCT7[2] & ~FUNCT7[1] & ~FUNCT7[0];
assign FUNCT7_mret = ~FUNCT7[6] & ~FUNCT7[5] & FUNCT7[4] & FUNCT7[3] & ~FUNCT7[2] & ~FUNCT7[1] & ~FUNCT7[0];
assign RS1_ADDR_zero = ~(RS1_ADDR[4] | RS1_ADDR[3] | RS1_ADDR[2] | RS1_ADDR[1] | RS1_ADDR[0]);
assign RS2_ADDR_zero = ~(RS2_ADDR[4] | RS2_ADDR[3] | RS2_ADDR[2] | RS2_ADDR[1] | RS2_ADDR[0]);
assign rd_zero = ~(RD_ADDR[4] | RD_ADDR[3] | RD_ADDR[2] | RD_ADDR[1] | RD_ADDR[0]);
assign RS2_ADDR_wfi = ~RS2_ADDR[4] & ~RS2_ADDR[3] & RS2_ADDR[2] & ~RS2_ADDR[1] & RS2_ADDR[0];
assign RS2_ADDR_mret = ~RS2_ADDR[4] & ~RS2_ADDR[3] & ~RS2_ADDR[2] & RS2_ADDR[1] & ~RS2_ADDR[0];
assign RS2_ADDR_ebreak = ~RS2_ADDR[4] & ~RS2_ADDR[3] & ~RS2_ADDR[2] & ~RS2_ADDR[1] & RS2_ADDR[0];
assign wfi = is_system & FUNCT7_wfi & RS2_ADDR_wfi & RS1_ADDR_zero & FUNCT3_zero & rd_zero;
assign mret = is_system & FUNCT7_mret & RS2_ADDR_mret & RS1_ADDR_zero & FUNCT3_zero & rd_zero;
assign ecall = is_system & FUNCT7_zero & RS2_ADDR_zero & RS1_ADDR_zero & FUNCT3_zero & rd_zero;
assign ebreak = is_system & FUNCT7_zero & RS2_ADDR_ebreak & RS1_ADDR_zero & FUNCT3_zero & rd_zero;
assign eip = MEIE & (E_IRQ | MEIP);
assign tip = MTIE & (T_IRQ | MTIP);
assign sip = MSIE & (S_IRQ | MSIP);
assign ip = eip | tip | sip;
assign exception = ILLEGAL_INSTR | MISALIGNED_INSTR | MISALIGNED_LOAD | MISALIGNED_STORE;
always @*
begin
case(curr_state)
STATE_RESET:
next_state = STATE_OPERATING;
STATE_OPERATING:
if((MIE & ip) | exception | ecall | ebreak) next_state = STATE_TRAP_TAKEN;
else if(mret) next_state = STATE_TRAP_RETURN;
else next_state = STATE_OPERATING;
STATE_TRAP_TAKEN:
next_state = STATE_OPERATING;
STATE_TRAP_RETURN:
next_state = STATE_OPERATING;
default:
next_state = STATE_OPERATING;
endcase
end
// output generation
always @*
begin
case(curr_state)
STATE_RESET:
begin
PC_SRC = `PC_BOOT;
FLUSH = 1'b1;
INSTRET_INC = 1'b0;
SET_EPC = 1'b0;
SET_CAUSE = 1'b0;
MIE_CLEAR = 1'b0;
MIE_SET = 1'b0;
end
STATE_OPERATING:
begin
PC_SRC = `PC_NEXT;
FLUSH = 1'b0;
INSTRET_INC = 1'b1;
SET_EPC = 1'b0;
SET_CAUSE = 1'b0;
MIE_CLEAR = 1'b0;
MIE_SET = 1'b0;
end
STATE_TRAP_TAKEN:
begin
PC_SRC = `PC_TRAP;
FLUSH = 1'b1;
INSTRET_INC = 1'b0;
SET_EPC = 1'b1;
SET_CAUSE = 1'b1;
MIE_CLEAR = 1'b1;
MIE_SET = 1'b0;
end
STATE_TRAP_RETURN:
begin
PC_SRC = `PC_EPC;
FLUSH = 1'b1;
INSTRET_INC = 1'b0;
SET_EPC = 1'b0;
SET_CAUSE = 1'b0;
MIE_CLEAR = 1'b0;
MIE_SET = 1'b1;
end
default:
begin
PC_SRC = `PC_NEXT;
FLUSH = 1'b0;
INSTRET_INC = 1'b1;
SET_EPC = 1'b0;
SET_CAUSE = 1'b0;
MIE_CLEAR = 1'b0;
MIE_SET = 1'b0;
end
endcase
end
// SEQUENTIAL LOGIC -------------------------------------------
always @(posedge CLK or posedge RESET)
begin
if(RESET) curr_state <= STATE_RESET;
else curr_state <= next_state;
end
always @(posedge CLK or posedge RESET)
begin
if(RESET)
begin
CAUSE <= 4'b0;
I_OR_E <= 1'b0;
end
else if(curr_state == STATE_OPERATING)
begin
if(MIE & eip)
begin
CAUSE <= 4'b1011; // M-mode external interrupt
I_OR_E <= 1'b1;
end
else if(MIE & sip)
begin
CAUSE <= 4'b0011; // M-mode software interrupt
I_OR_E <= 1'b1;
end
else if(MIE & tip)
begin
CAUSE <= 4'b0111; // M-mode timer interrupt
I_OR_E <= 1'b1;
end
else if(ILLEGAL_INSTR)
begin
CAUSE <= 4'b0010; // Illegal instruction
I_OR_E <= 1'b0;
end
else if(MISALIGNED_INSTR)
begin
CAUSE <= 4'b0000; // Instruction address misaligned
I_OR_E <= 1'b0;
end
else if(ecall)
begin
CAUSE <= 4'b1011; // Environment call from M-mode
I_OR_E <= 1'b0;
end
else if(ebreak)
begin
CAUSE <= 4'b0011; // Breakpoint
I_OR_E <= 1'b0;
end
else if(MISALIGNED_STORE)
begin
CAUSE <= 4'b0110; // Store address misaligned
I_OR_E <= 1'b0;
end
else if(MISALIGNED_LOAD)
begin
CAUSE <= 4'b0100; // Load address misaligned
I_OR_E <= 1'b0;
end
end
end
endmodule
/steelcore/trunk/steel_top.v
0,0 → 1,476
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 30.04.2020 02:39:50
// Module Name: steel_top
// Project Name: Steel Core
// Description: RISC-V Steel Core top module
//
// Dependencies: globals.vh
// machine_control.v
// alu.v
// integer_file.v
// branch_unit.v
// control_unit.v
// csr_file.v
// imm_generator.v
// load_unit.v
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module steel_top(
 
input wire CLK,
input wire RESET,
// connection with Real Time Counter
input wire [63:0] REAL_TIME,
// connections with Instruction Memory
output wire [31:0] I_ADDR,
input wire [31:0] INSTR,
// connections with Data Memory
output wire [31:0] D_ADDR,
output wire [31:0] DATA_OUT,
output wire WR_REQ,
output wire [3:0] WR_MASK,
input wire [31:0] DATA_IN,
//connections with Interrupt Controller
input wire E_IRQ,
input wire T_IRQ,
input wire S_IRQ
 
);
// ---------------------------------
// Internal wires and registers
// ---------------------------------
wire [4:0] RS1_ADDR;
wire [4:0] RS2_ADDR;
wire [4:0] RD_ADDR;
reg [4:0] RD_ADDR_reg;
wire [31:0] CSR_DATA;
wire [11:0] CSR_ADDR;
reg [11:0] CSR_ADDR_reg;
wire [31:0] RS1;
reg [31:0] RS1_reg;
wire [31:0] RS2;
reg [31:0] RS2_reg;
reg [31:0] PC;
wire [31:0] NEXT_PC;
wire [31:0] PC_PLUS_4;
reg [31:0] PC_PLUS_4_reg;
wire BRANCH_TAKEN;
wire [31:0] IADDER_OUT;
reg [31:0] IADDER_OUT_reg;
wire [31:0] EPC;
wire [31:0] TRAP_ADDRESS;
wire [1:0] PC_SRC;
wire [6:0] OPCODE;
wire [6:0] FUNCT7;
wire [2:0] FUNCT3;
wire [3:0] ALU_OPCODE;
reg [3:0] ALU_OPCODE_reg;
wire MEM_WR_REQ;
wire [3:0] MEM_WR_MASK;
wire [1:0] LOAD_SIZE;
reg [1:0] LOAD_SIZE_reg;
wire LOAD_UNSIGNED;
reg LOAD_UNSIGNED_reg;
wire ALU_SRC;
reg ALU_SRC_reg;
wire IADDER_SRC;
wire CSR_WR_EN;
reg CSR_WR_EN_reg;
wire RF_WR_EN;
reg RF_WR_EN_reg;
wire [2:0] WB_MUX_SEL;
reg [2:0] WB_MUX_SEL_reg;
wire [2:0] IMM_TYPE;
wire [2:0] CSR_OP;
reg [2:0] CSR_OP_reg;
wire ILLEGAL_INSTR;
wire MISALIGNED_LOAD;
wire MISALIGNED_STORE;
wire [31:0] IMM;
reg [31:0] IMM_reg;
wire I_OR_E;
wire SET_CAUSE;
wire [3:0] CAUSE_IN;
wire SET_EPC;
wire INSTRET_INC;
wire MIE_CLEAR;
wire MIE_SET;
wire MIE;
wire MEIE_OUT;
wire MTIE_OUT;
wire MSIE_OUT;
wire MEIP_OUT;
wire MTIP_OUT;
wire MSIP_OUT;
wire FLUSH;
wire [31:0] LU_OUTPUT;
wire [31:0] ALU_RESULT;
reg [31:0] WB_MUX_OUT;
wire RESET_OR_FLUSH;
wire [31:0] SU_DATA_OUT;
wire [31:0] SU_D_ADDR;
wire [3:0] SU_WR_MASK;
wire SU_WR_REQ;
// ---------------------------------
// PIPELINE STAGE 1
// ---------------------------------
// PC MUX
reg [31:0] PC_MUX_OUT;
always @*
begin
case (PC_SRC)
`PC_BOOT: PC_MUX_OUT = `BOOT_ADDRESS;
`PC_EPC: PC_MUX_OUT = EPC;
`PC_TRAP: PC_MUX_OUT = TRAP_ADDRESS;
`PC_NEXT: PC_MUX_OUT = NEXT_PC;
endcase
end
// PC Adder and Multiplexer
assign PC_PLUS_4 = PC + 32'h00000004;
assign NEXT_PC = BRANCH_TAKEN ? {IADDER_OUT[31:1], 1'b0} : PC_PLUS_4;
// Program Counter (PC) register
always @(posedge CLK or posedge RESET)
begin
if(RESET) PC <= `BOOT_ADDRESS;
else PC <= PC_MUX_OUT;
end
// ---------------------------------
// PIPELINE STAGE 2
// ---------------------------------
wire [31:0] INSTR_mux;
assign INSTR_mux = FLUSH == 1'b1 ? 32'h00000013 : INSTR;
assign OPCODE = INSTR_mux[6:0];
assign FUNCT3 = INSTR_mux[14:12];
assign FUNCT7 = INSTR_mux[31:25];
store_unit su(
 
.FUNCT3(FUNCT3[1:0]),
.IADDER_OUT(IADDER_OUT),
.RS2(RS2),
.MEM_WR_REQ(MEM_WR_REQ),
.DATA_OUT(SU_DATA_OUT),
.D_ADDR(SU_D_ADDR),
.WR_MASK(SU_WR_MASK),
.WR_REQ(SU_WR_REQ)
);
control_unit ctrlunit(
.OPCODE(OPCODE),
.FUNCT7_5(FUNCT7[5]),
.FUNCT3(FUNCT3),
.IADDER_OUT_1_TO_0(IADDER_OUT[1:0]),
.ALU_OPCODE(ALU_OPCODE),
.MEM_WR_REQ(MEM_WR_REQ),
.LOAD_SIZE(LOAD_SIZE),
.LOAD_UNSIGNED(LOAD_UNSIGNED),
.ALU_SRC(ALU_SRC),
.IADDER_SRC(IADDER_SRC),
.CSR_WR_EN(CSR_WR_EN),
.RF_WR_EN(RF_WR_EN),
.WB_MUX_SEL(WB_MUX_SEL),
.IMM_TYPE(IMM_TYPE),
.CSR_OP(CSR_OP),
.ILLEGAL_INSTR(ILLEGAL_INSTR),
.MISALIGNED_LOAD(MISALIGNED_LOAD),
.MISALIGNED_STORE(MISALIGNED_STORE)
);
imm_generator immgen(
.INSTR(INSTR_mux[31:7]),
.IMM_TYPE(IMM_TYPE),
.IMM(IMM)
);
// Immediate Adder
wire [31:0] iadder_mux_out;
assign iadder_mux_out = IADDER_SRC == 1'b1 ? RS1 : PC;
assign IADDER_OUT = iadder_mux_out + IMM;
branch_unit bunit(
 
.OPCODE_6_TO_2(OPCODE[6:2]),
.FUNCT3(FUNCT3),
.RS1(RS1),
.RS2(RS2),
.BRANCH_TAKEN(BRANCH_TAKEN)
);
assign RS1_ADDR = INSTR_mux[19:15];
assign RS2_ADDR = INSTR_mux[24:20];
assign RD_ADDR = INSTR_mux[11:7];
integer_file irf(
.CLK(CLK),
.RESET(RESET),
.RS_1_ADDR(RS1_ADDR),
.RS_2_ADDR(RS2_ADDR),
.RS_1(RS1),
.RS_2(RS2),
.RD_ADDR(RD_ADDR_reg),
.WR_EN(RF_WR_EN_reg),
.RD(WB_MUX_OUT)
 
);
assign CSR_ADDR = INSTR_mux[31:20];
csr_file csrf(
 
.CLK(CLK),
.RESET(RESET),
.WR_EN(CSR_WR_EN_reg),
.CSR_ADDR(CSR_ADDR_reg),
.CSR_OP(CSR_OP_reg),
.CSR_UIMM(IMM_reg[4:0]),
.CSR_DATA_IN(RS1_reg),
.CSR_DATA_OUT(CSR_DATA),
.PC(PC),
.E_IRQ(E_IRQ),
.T_IRQ(T_IRQ),
.S_IRQ(S_IRQ),
.I_OR_E(I_OR_E),
.SET_CAUSE(SET_CAUSE),
.CAUSE_IN(CAUSE_IN),
.SET_EPC(SET_EPC),
.INSTRET_INC(INSTRET_INC),
.MIE_CLEAR(MIE_CLEAR),
.MIE_SET(MIE_SET),
.MIE(MIE),
.MEIE_OUT(MEIE_OUT),
.MTIE_OUT(MTIE_OUT),
.MSIE_OUT(MSIE_OUT),
.MEIP_OUT(MEIP_OUT),
.MTIP_OUT(MTIP_OUT),
.MSIP_OUT(MSIP_OUT),
.REAL_TIME(REAL_TIME),
.EPC_OUT(EPC),
.TRAP_ADDRESS(TRAP_ADDRESS)
 
);
machine_control mc(
 
.CLK(CLK),
.RESET(RESET),
.ILLEGAL_INSTR(ILLEGAL_INSTR),
.MISALIGNED_INSTR(BRANCH_TAKEN & NEXT_PC[1]),
.MISALIGNED_LOAD(MISALIGNED_LOAD),
.MISALIGNED_STORE(MISALIGNED_STORE),
.OPCODE_6_TO_2(OPCODE[6:2]),
.FUNCT3(FUNCT3),
.FUNCT7(FUNCT7),
.RS1_ADDR(RS1_ADDR),
.RS2_ADDR(RS2_ADDR),
.RD_ADDR(RD_ADDR),
.E_IRQ(E_IRQ),
.T_IRQ(T_IRQ),
.S_IRQ(S_IRQ),
.I_OR_E(I_OR_E),
.SET_CAUSE(SET_CAUSE),
.CAUSE(CAUSE_IN),
.SET_EPC(SET_EPC),
.INSTRET_INC(INSTRET_INC),
.MIE_CLEAR(MIE_CLEAR),
.MIE_SET(MIE_SET),
.MIE(MIE),
.MEIE(MEIE_OUT),
.MTIE(MTIE_OUT),
.MSIE(MSIE_OUT),
.MEIP(MEIP_OUT),
.MTIP(MTIP_OUT),
.MSIP(MSIP_OUT),
.PC_SRC(PC_SRC),
.FLUSH(FLUSH)
 
);
assign RESET_OR_FLUSH = RESET | FLUSH;
// Stages 1/2 interface registers
always @(posedge CLK or posedge RESET_OR_FLUSH)
begin
if(RESET_OR_FLUSH)
begin
RD_ADDR_reg <= 5'b00000;
CSR_ADDR_reg <= 12'b000000000000;
RS1_reg <= 32'h00000000;
RS2_reg <= 32'h00000000;
PC_PLUS_4_reg <= 32'h00000000;
IADDER_OUT_reg <= 32'h00000000;
ALU_OPCODE_reg <= 4'b0000;
LOAD_SIZE_reg <= 2'b00;
LOAD_UNSIGNED_reg <= 1'b0;
ALU_SRC_reg <= 1'b0;
CSR_WR_EN_reg <= 1'b0;
RF_WR_EN_reg <= 1'b0;
WB_MUX_SEL_reg <= `WB_ALU;
CSR_OP_reg <= 3'b000;
IMM_reg <= 32'h00000000;
end
else
begin
RD_ADDR_reg <= RD_ADDR;
CSR_ADDR_reg <= CSR_ADDR;
RS1_reg <= RS1;
RS2_reg <= RS2;
PC_PLUS_4_reg <= PC_PLUS_4;
IADDER_OUT_reg <= IADDER_OUT;
ALU_OPCODE_reg <= ALU_OPCODE;
LOAD_SIZE_reg <= LOAD_SIZE;
LOAD_UNSIGNED_reg <= LOAD_UNSIGNED;
ALU_SRC_reg <= ALU_SRC;
CSR_WR_EN_reg <= CSR_WR_EN;
RF_WR_EN_reg <= RF_WR_EN;
WB_MUX_SEL_reg <= WB_MUX_SEL;
CSR_OP_reg <= CSR_OP;
IMM_reg <= IMM;
end
end
// ---------------------------------
// PIPELINE STAGE 3
// ---------------------------------
load_unit lu(
.LOAD_SIZE(LOAD_SIZE_reg),
.LOAD_UNSIGNED(LOAD_UNSIGNED_reg),
.DATA_IN(DATA_IN),
.IADDER_OUT_1_TO_0(IADDER_OUT_reg[1:0]),
.OUTPUT(LU_OUTPUT)
);
wire [31:0] alu_2nd_src_mux;
assign alu_2nd_src_mux = ALU_SRC_reg ? RS2_reg : IMM_reg;
alu alu(
.OP_1(RS1_reg),
.OP_2(alu_2nd_src_mux),
.OPCODE(ALU_OPCODE_reg),
.RESULT(ALU_RESULT)
 
);
always @*
begin
case (WB_MUX_SEL_reg)
`WB_ALU: WB_MUX_OUT = ALU_RESULT;
`WB_LU: WB_MUX_OUT = LU_OUTPUT;
`WB_IMM: WB_MUX_OUT = IMM_reg;
`WB_IADDER_OUT: WB_MUX_OUT = IADDER_OUT_reg;
`WB_CSR: WB_MUX_OUT = CSR_DATA;
`WB_PC_PLUS: WB_MUX_OUT = PC_PLUS_4_reg;
default: WB_MUX_OUT = ALU_RESULT;
endcase
end
// ---------------------------------
// OUTPUT ASSIGNMENTS
// ---------------------------------
assign I_ADDR = PC_MUX_OUT;
assign WR_REQ = SU_WR_REQ;
assign WR_MASK = SU_WR_MASK;
assign D_ADDR = SU_D_ADDR;
assign DATA_OUT = SU_DATA_OUT;
endmodule
/steelcore/trunk/store_unit.v
0,0 → 1,170
//////////////////////////////////////////////////////////////////////////////////
// Engineer: Rafael de Oliveira Calçada (rafaelcalcada@gmail.com)
//
// Create Date: 02.06.2020 01:28:57
// Module Name: store_unit
// Project Name: Steel Core
// Description: Controls the data memory interface
//
// Dependencies: -
//
// Version 0.01
//
//////////////////////////////////////////////////////////////////////////////////
 
/*********************************************************************************
 
MIT License
 
Copyright (c) 2020 Rafael de Oliveira Calçada
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
-----------------------------------------------------------------------------
 
Licença MIT
 
Copyright (c) 2019 Rafael de Oliveira Calçada
 
Permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma
cópia deste software e dos arquivos de documentação associados
(o "Software"), para negociar sobre o Software sem restrições, incluindo,
sem limitação, os direitos de uso, cópia, modificação, fusão, publicação,
distribuição, sublicenciamento e/ou venda de cópias do Software e o direito
de permitir que pessoas a quem o Software seja fornecido o façam, sob as
seguintes condições:
 
O aviso de direitos autorais acima e este aviso de permissão devem ser
incluídos em todas as cópias ou partes substanciais do Software.
 
O SOFTWARE É FORNECIDO "TAL COMO ESTÁ", SEM GARANTIA DE QUALQUER TIPO,
EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO A GARANTIAS DE
COMERCIALIZAÇÃO, ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA E NÃO INFRAÇÃO.
EM NENHUM CASO OS AUTORES OU TITULARES DE DIREITOS AUTORAIS SERÃO
RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANOS OU OUTRA RESPONSABILIDADE,
SEJA EM AÇÕES CIVIS, PENAIS OU OUTRAS, PROVENIENTE, FORA OU EM CONEXÃO
COM O SOFTWARE OU O USO RELACIONADO AO SOFTWARE.
 
********************************************************************************/
 
`timescale 1ns / 1ps
`include "globals.vh"
 
module store_unit(
 
input wire [1:0] FUNCT3,
input wire [31:0] IADDER_OUT,
input wire [31:0] RS2,
input wire MEM_WR_REQ,
output reg [31:0] DATA_OUT,
output wire [31:0] D_ADDR,
output reg [3:0] WR_MASK,
output wire WR_REQ
);
reg [3:0] half_wr_mask;
reg [3:0] byte_wr_mask;
reg [31:0] half_dout;
reg [31:0] byte_dout;
assign D_ADDR = {IADDER_OUT[31:2], 2'b0};
assign WR_REQ = MEM_WR_REQ;
always @*
begin
case(FUNCT3[1:0])
2'b00: WR_MASK = byte_wr_mask;
2'b01: WR_MASK = half_wr_mask;
2'b10: WR_MASK = {4{MEM_WR_REQ}};
2'b11: WR_MASK = {4{MEM_WR_REQ}};
endcase
end
always @*
begin
case(FUNCT3[1:0])
2'b00: DATA_OUT = byte_dout;
2'b01: DATA_OUT = half_dout;
2'b10: DATA_OUT = RS2;
2'b11: DATA_OUT = RS2;
endcase
end
always @*
begin
case(IADDER_OUT[1:0])
2'b00: byte_dout = {24'b0, RS2[7:0]};
2'b01: byte_dout = {16'b0, RS2[7:0], 8'b0};
2'b10: byte_dout = {8'b0, RS2[7:0], 16'b0};
2'b11: byte_dout = {RS2[7:0], 24'b0};
endcase
end
always @*
begin
case(IADDER_OUT[1:0])
2'b00: byte_wr_mask = {3'b0, MEM_WR_REQ};
2'b01: byte_wr_mask = {2'b0, MEM_WR_REQ, 1'b0};
2'b10: byte_wr_mask = {1'b0, MEM_WR_REQ, 2'b0};
2'b11: byte_wr_mask = {MEM_WR_REQ, 3'b0};
endcase
end
always @*
begin
case(IADDER_OUT[1])
1'b0: half_dout = {16'b0, RS2[15:0]};
1'b1: half_dout = {RS2[15:0], 16'b0};
endcase
end
always @*
begin
case(IADDER_OUT[1])
1'b0: half_wr_mask = {2'b0, {2{MEM_WR_REQ}}};
1'b1: half_wr_mask = {{2{MEM_WR_REQ}}, 2'b0};
endcase
end
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.