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 |