Add 5 stage pipeline test and move timescale to include
Some checks are pending
continuous-integration/drone/push Build is pending
Some checks are pending
continuous-integration/drone/push Build is pending
This commit is contained in:
parent
a9147414cf
commit
24a5622103
@ -44,7 +44,7 @@ function(rvscc_add_test)
|
||||
PREFIX verilator_${TEST_TOP}
|
||||
TOP_MODULE ${TEST_TOP}
|
||||
TRACE
|
||||
VERILATOR_ARGS --timing --assert
|
||||
VERILATOR_ARGS --timing --assert -I${PROJECT_SOURCE_DIR}/hwinc
|
||||
)
|
||||
target_compile_definitions(${TEST_TARGET_NAME} PRIVATE
|
||||
TEST_HEADER="verilator_${TEST_TOP}.h"
|
||||
|
2
hwinc/timescale.sv
Normal file
2
hwinc/timescale.sv
Normal file
@ -0,0 +1,2 @@
|
||||
// Project timescale
|
||||
`timescale 1ns / 1ps
|
@ -1,3 +1,5 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
module alu (
|
||||
|
@ -1,6 +1,6 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module alu_decoder(
|
||||
module alu_decoder (
|
||||
input logic opcode_5,
|
||||
input logic [2:0] funct_3,
|
||||
input logic funct_7_5,
|
||||
|
@ -1,6 +1,6 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module CacheController #(
|
||||
module cache_controller #(
|
||||
parameter int ADDR_SIZE = 32,
|
||||
parameter int NUM_SETS = 16,
|
||||
parameter int NUM_WAYS = 4,
|
||||
|
@ -1,4 +1,4 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module cache_memory #(
|
||||
parameter int ADDR_SIZE = 32,
|
||||
|
@ -1,4 +1,4 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
module data_memory #(
|
||||
|
@ -1,3 +1,5 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
interface data_memory_if #(
|
||||
parameter int ADDR_SIZE = 32,
|
||||
parameter int DATA_SIZE = 32
|
||||
@ -14,5 +16,22 @@ interface data_memory_if #(
|
||||
|
||||
modport datapath(input read_data, output addr, write_enable, write_data);
|
||||
modport ram(input clk, rst, addr, write_enable, write_data, output read_data);
|
||||
modport test(input read_data, write_enable, write_data);
|
||||
|
||||
/*
|
||||
* Test assertion that should be used against test-core.s firmware.
|
||||
* This function checks if the results in data memory are the expected.
|
||||
* Must be called each clock cycle.
|
||||
*/
|
||||
function static void check_fw_test_core_assertions();
|
||||
if (write_enable) begin
|
||||
if (addr == 'd100 && write_data == 'd25) begin
|
||||
$finish;
|
||||
end else
|
||||
assert (addr == 'd96)
|
||||
else $error("Unexpected write address in test-core program");
|
||||
$finish;
|
||||
end
|
||||
endfunction
|
||||
endinterface
|
||||
|
||||
|
267
rtl/five_stage_pipeline_datapath.sv
Normal file
267
rtl/five_stage_pipeline_datapath.sv
Normal file
@ -0,0 +1,267 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
module five_stage_pipeline_datapath (
|
||||
input logic clk,
|
||||
input logic rst,
|
||||
instr_memory_if.datapath instr_mem_if,
|
||||
data_memory_if.datapath data_mem_if
|
||||
);
|
||||
logic [31:0] fetch_pc, fetch_pc_next;
|
||||
|
||||
logic [31:0] fetch_pc_plus_4, execute_pc_target;
|
||||
logic execute_pc_src;
|
||||
always_comb begin
|
||||
fetch_pc_plus_4 = fetch_pc + 'd4;
|
||||
case (execute_pc_src)
|
||||
'd0: fetch_pc_next = fetch_pc_plus_4;
|
||||
'd1: fetch_pc_next = execute_pc_target;
|
||||
default: fetch_pc_next = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic fetch_stall;
|
||||
always_ff @(posedge clk) begin
|
||||
if (rst) fetch_pc <= 'b0;
|
||||
else if (!fetch_stall) fetch_pc <= fetch_pc_next;
|
||||
end
|
||||
|
||||
logic [31:0] fetch_instr;
|
||||
assign instr_mem_if.addr = instr_mem_if.AddrSize'(fetch_pc);
|
||||
assign fetch_instr = instr_mem_if.instr;
|
||||
|
||||
logic decode_stall, decode_flush;
|
||||
logic [31:0] decode_instr, decode_pc, decode_pc_plus_4;
|
||||
always_ff @(posedge clk) begin
|
||||
if (decode_flush) begin
|
||||
decode_instr <= 'd0;
|
||||
decode_pc <= 'd0;
|
||||
decode_pc_plus_4 <= 'd0;
|
||||
end else if (!decode_stall) begin
|
||||
decode_instr <= fetch_instr;
|
||||
decode_pc <= fetch_pc;
|
||||
decode_pc_plus_4 <= fetch_pc_plus_4;
|
||||
end
|
||||
end
|
||||
|
||||
logic [4:0] decode_rs_1, decode_rs_2, decode_rd;
|
||||
assign decode_rs_1 = decode_instr[19:15];
|
||||
assign decode_rs_2 = decode_instr[24:20];
|
||||
assign decode_rd = decode_instr[11:7];
|
||||
|
||||
logic writeback_reg_write;
|
||||
logic [31:0] decode_read_data_1, decode_read_data_2;
|
||||
logic [31:0] result, writeback_result;
|
||||
register_file register_file (
|
||||
.clk(!clk),
|
||||
.rst(rst),
|
||||
.addr_1(decode_instr[19:15]),
|
||||
.addr_2(decode_instr[24:20]),
|
||||
.addr_3(writeback_rd),
|
||||
.write_enable_3(writeback_reg_write),
|
||||
.write_data_3(writeback_result),
|
||||
.read_data_1(decode_read_data_1),
|
||||
.read_data_2(decode_read_data_2)
|
||||
);
|
||||
|
||||
logic [1:0] decode_result_src;
|
||||
logic [1:0] decode_imm_src;
|
||||
logic [2:0] decode_alu_ctrl;
|
||||
logic decode_reg_write;
|
||||
logic decode_mem_write;
|
||||
logic decode_jump;
|
||||
logic decode_branch;
|
||||
logic decode_alu_src;
|
||||
logic decode_branch_alu_neg;
|
||||
control_unit control_unit (
|
||||
.opcode(decode_instr[6:0]),
|
||||
.funct_3(decode_instr[14:12]),
|
||||
.funct_7(decode_instr[31:25]),
|
||||
.reg_write(decode_reg_write),
|
||||
.result_src(decode_result_src),
|
||||
.mem_write(decode_mem_write),
|
||||
.jump(decode_jump),
|
||||
.branch(decode_branch),
|
||||
.alu_ctrl(decode_alu_ctrl),
|
||||
.alu_src(decode_alu_src),
|
||||
.imm_src(decode_imm_src),
|
||||
.branch_alu_neg(decode_branch_alu_neg)
|
||||
);
|
||||
|
||||
logic [31:0] decode_imm_ext;
|
||||
imm_extend imm_extend (
|
||||
.imm_src(decode_imm_src[1:0]),
|
||||
.instr (decode_instr[31:7]),
|
||||
.imm_ext(decode_imm_ext[31:0])
|
||||
);
|
||||
|
||||
logic execute_reg_write;
|
||||
logic execute_mem_write;
|
||||
logic execute_jump;
|
||||
logic execute_branch;
|
||||
logic execute_branch_alu_neg;
|
||||
logic execute_alu_src;
|
||||
logic execute_flush;
|
||||
logic [1:0] execute_result_src;
|
||||
logic [2:0] execute_alu_ctrl;
|
||||
logic [4:0] execute_rs_1, execute_rs_2, execute_rd;
|
||||
logic [31:0] execute_pc;
|
||||
logic [31:0] execute_pc_plus_4;
|
||||
logic [31:0] execute_read_data_1;
|
||||
logic [31:0] execute_read_data_2;
|
||||
logic [31:0] execute_imm_ext;
|
||||
always_ff @(posedge clk) begin
|
||||
if (execute_flush) begin
|
||||
execute_reg_write <= 'd0;
|
||||
execute_result_src <= 'd0;
|
||||
execute_mem_write <= 'd0;
|
||||
execute_jump <= 'd0;
|
||||
execute_branch <= 'd0;
|
||||
execute_alu_ctrl <= 'd0;
|
||||
execute_alu_src <= 'd0;
|
||||
execute_read_data_1 <= 'd0;
|
||||
execute_read_data_2 <= 'd0;
|
||||
execute_pc <= 'd0;
|
||||
execute_rs_1 <= 'd0;
|
||||
execute_rs_2 <= 'd0;
|
||||
execute_rd <= 'd0;
|
||||
execute_imm_ext <= 'd0;
|
||||
execute_pc_plus_4 <= 'd0;
|
||||
end else if (!decode_stall) begin
|
||||
execute_reg_write <= decode_reg_write;
|
||||
execute_result_src <= decode_result_src;
|
||||
execute_mem_write <= decode_mem_write;
|
||||
execute_jump <= decode_jump;
|
||||
execute_branch <= decode_branch;
|
||||
execute_branch_alu_neg <= decode_branch_alu_neg;
|
||||
execute_alu_ctrl <= decode_alu_ctrl;
|
||||
execute_alu_src <= decode_alu_src;
|
||||
execute_read_data_1 <= decode_read_data_1;
|
||||
execute_read_data_2 <= decode_read_data_2;
|
||||
execute_pc <= decode_pc;
|
||||
execute_rs_1 <= decode_rs_1;
|
||||
execute_rs_2 <= decode_rs_2;
|
||||
execute_rd <= decode_rd;
|
||||
execute_imm_ext <= decode_imm_ext;
|
||||
execute_pc_plus_4 <= decode_pc_plus_4;
|
||||
end
|
||||
end
|
||||
|
||||
logic execute_zero;
|
||||
jump_control jump_control (
|
||||
.jump(execute_jump),
|
||||
.branch(execute_branch),
|
||||
.branch_alu_neg(execute_branch_alu_neg),
|
||||
.zero(execute_zero),
|
||||
.pc_src(execute_pc_src)
|
||||
);
|
||||
|
||||
logic [31:0] execute_src_a, memory_alu_result;
|
||||
logic [1:0] execute_forward_a;
|
||||
always_comb begin
|
||||
case (execute_forward_a)
|
||||
'b00: execute_src_a = execute_read_data_1;
|
||||
'b01: execute_src_a = writeback_result;
|
||||
'b10: execute_src_a = memory_alu_result;
|
||||
'b11: execute_src_a = 'dx;
|
||||
default: execute_src_a = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic [31:0] execute_write_data;
|
||||
logic [ 1:0] execute_forward_b;
|
||||
always_comb begin
|
||||
case (execute_forward_b)
|
||||
'b00: execute_write_data = execute_read_data_2;
|
||||
'b01: execute_write_data = writeback_result;
|
||||
'b10: execute_write_data = memory_alu_result;
|
||||
'b11: execute_write_data = 'dx;
|
||||
default: execute_write_data = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic [31:0] execute_src_b;
|
||||
always_comb begin
|
||||
case (execute_alu_src)
|
||||
'd0: execute_src_b = execute_write_data;
|
||||
'd1: execute_src_b = execute_imm_ext;
|
||||
default: execute_src_b = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic [31:0] execute_alu_result;
|
||||
logic [ 3:0] execute_alu_status;
|
||||
assign execute_zero = execute_alu_status[2];
|
||||
alu alu (
|
||||
.a(execute_src_a),
|
||||
.b(execute_src_b),
|
||||
.operation(execute_alu_ctrl),
|
||||
.result(execute_alu_result),
|
||||
.status(execute_alu_status)
|
||||
);
|
||||
|
||||
assign execute_pc_target = execute_pc + execute_imm_ext;
|
||||
|
||||
logic memory_reg_write, memory_mem_write;
|
||||
logic [1:0] memory_result_src;
|
||||
logic [4:0] memory_rd;
|
||||
logic [31:0] memory_pc_plus_4, memory_write_data;
|
||||
always_ff @(posedge clk) begin
|
||||
memory_reg_write <= execute_reg_write;
|
||||
memory_result_src <= execute_result_src;
|
||||
memory_mem_write <= execute_mem_write;
|
||||
memory_alu_result <= execute_alu_result;
|
||||
memory_write_data <= execute_write_data;
|
||||
memory_rd <= execute_rd;
|
||||
memory_pc_plus_4 <= execute_pc_plus_4;
|
||||
end
|
||||
|
||||
logic [31:0] memory_read_data;
|
||||
always_comb begin
|
||||
data_mem_if.addr = memory_alu_result;
|
||||
data_mem_if.write_enable = memory_mem_write;
|
||||
data_mem_if.write_data = memory_write_data;
|
||||
memory_read_data = data_mem_if.read_data;
|
||||
end
|
||||
|
||||
logic [1:0] writeback_result_src;
|
||||
logic [4:0] writeback_rd;
|
||||
logic [31:0] writeback_pc_plus_4, writeback_alu_result, writeback_read_data;
|
||||
always_ff @(posedge clk) begin
|
||||
writeback_reg_write <= memory_reg_write;
|
||||
writeback_result_src <= memory_result_src;
|
||||
writeback_alu_result <= memory_alu_result;
|
||||
writeback_read_data <= memory_read_data;
|
||||
writeback_rd <= memory_rd;
|
||||
writeback_pc_plus_4 <= memory_pc_plus_4;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
case (writeback_result_src)
|
||||
'b00: writeback_result = writeback_alu_result;
|
||||
'b01: writeback_result = writeback_read_data;
|
||||
'b10: writeback_result = writeback_pc_plus_4;
|
||||
default: writeback_result = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
hazard_unit hazard_unit (
|
||||
.rst(rst),
|
||||
.execute_pc_src(execute_pc_src),
|
||||
.execute_result_src_0(execute_result_src[0]),
|
||||
.memory_reg_write(memory_reg_write),
|
||||
.writeback_reg_write(writeback_reg_write),
|
||||
.decode_rs_1(decode_rs_1),
|
||||
.decode_rs_2(decode_rs_2),
|
||||
.execute_rs_1(execute_rs_1),
|
||||
.execute_rs_2(execute_rs_2),
|
||||
.execute_rd(execute_rd),
|
||||
.memory_rd(memory_rd),
|
||||
.writeback_rd(writeback_rd),
|
||||
.fetch_stall(fetch_stall),
|
||||
.decode_stall(decode_stall),
|
||||
.decode_flush(decode_flush),
|
||||
.execute_flush(execute_flush),
|
||||
.execute_forward_a(execute_forward_a),
|
||||
.execute_forward_b(execute_forward_b)
|
||||
);
|
||||
endmodule
|
@ -1,24 +1,24 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module HazardUnit (
|
||||
module hazard_unit (
|
||||
input logic rst,
|
||||
execute_pc_src,
|
||||
execute_result_src_0,
|
||||
memory_reg_write,
|
||||
writeback_reg_write,
|
||||
input logic execute_pc_src,
|
||||
input logic execute_result_src_0,
|
||||
input logic memory_reg_write,
|
||||
input logic writeback_reg_write,
|
||||
input logic [4:0] decode_rs_1,
|
||||
decode_rs_2,
|
||||
execute_rs_1,
|
||||
execute_rs_2,
|
||||
execute_rd,
|
||||
memory_rd,
|
||||
writeback_rd,
|
||||
input logic [4:0] decode_rs_2,
|
||||
input logic [4:0] execute_rs_1,
|
||||
input logic [4:0] execute_rs_2,
|
||||
input logic [4:0] execute_rd,
|
||||
input logic [4:0] memory_rd,
|
||||
input logic [4:0] writeback_rd,
|
||||
output logic fetch_stall,
|
||||
decode_stall,
|
||||
decode_flush,
|
||||
execute_flush,
|
||||
output logic decode_stall,
|
||||
output logic decode_flush,
|
||||
output logic execute_flush,
|
||||
output logic [1:0] execute_forward_a,
|
||||
execute_forward_b
|
||||
output logic [1:0] execute_forward_b
|
||||
);
|
||||
logic lw_stall;
|
||||
always_comb begin
|
||||
@ -27,15 +27,18 @@ module HazardUnit (
|
||||
decode_stall = 0;
|
||||
decode_flush = 1;
|
||||
execute_flush = 1;
|
||||
execute_forward_a = 0;
|
||||
execute_forward_b = 0;
|
||||
execute_forward_a = 2'd0;
|
||||
execute_forward_b = 2'd0;
|
||||
lw_stall = 1'dx;
|
||||
end else begin
|
||||
// set execute_forward_a
|
||||
if (((execute_rs_1 == memory_rd) & memory_reg_write) & (execute_rs_1 != 0))
|
||||
execute_forward_a = 'b10;
|
||||
else if (((execute_rs_1 == writeback_rd) & writeback_reg_write) & (execute_rs_1 != 0))
|
||||
execute_forward_a = 'b01;
|
||||
else execute_forward_a = 'b00;
|
||||
|
||||
// set execute_forward_b
|
||||
if (((execute_rs_2 == memory_rd) & memory_reg_write) & (execute_rs_2 != 0))
|
||||
execute_forward_b = 'b10;
|
||||
else if (((execute_rs_2 == writeback_rd) & writeback_reg_write) & (execute_rs_2 != 0))
|
||||
|
@ -1,4 +1,4 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module imm_extend (
|
||||
input logic [ 1:0] imm_src,
|
||||
|
@ -1,3 +1,5 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
module instr_memory #(
|
||||
|
@ -1,3 +1,5 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
interface instr_memory_if #(
|
||||
|
@ -1,4 +1,4 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module jump_control (
|
||||
input logic jump,
|
||||
|
@ -1,4 +1,4 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
@ -13,7 +13,6 @@ module main_decoder (
|
||||
output logic reg_write,
|
||||
output logic [1:0] alu_op
|
||||
);
|
||||
|
||||
opcode_fmt_t opcode_enum;
|
||||
assign opcode_enum = opcode_fmt_t'(opcode);
|
||||
always_comb begin
|
||||
|
@ -1,6 +1,6 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module PipelinedControlUnit (
|
||||
module pipelined_control_unit (
|
||||
input logic [6:0] opcode,
|
||||
input logic [2:0] funct_3,
|
||||
input logic [6:0] funct_7,
|
||||
@ -12,35 +12,25 @@ module PipelinedControlUnit (
|
||||
output logic alu_src,
|
||||
output logic [1:0] imm_src
|
||||
);
|
||||
//logic branch, branch_result, branch_neg, jump;
|
||||
//assign pc_src = (branch & branch_result) | jump;
|
||||
/*
|
||||
always_comb begin
|
||||
case(branch_neg)
|
||||
'd0: branch_result = !zero;
|
||||
'd1: branch_result = zero;
|
||||
endcase
|
||||
end*/
|
||||
|
||||
logic [1:0] alu_op;
|
||||
MainDecoder main_decoder (
|
||||
opcode,
|
||||
branch,
|
||||
jump,
|
||||
result_src,
|
||||
mem_write,
|
||||
alu_src,
|
||||
imm_src,
|
||||
reg_write,
|
||||
alu_op
|
||||
main_decoder main_decoder (
|
||||
.opcode(opcode),
|
||||
.branch(branch),
|
||||
.jump(jump),
|
||||
.result_src(result_src),
|
||||
.mem_write(mem_write),
|
||||
.alu_src(alu_src),
|
||||
.imm_src(imm_src),
|
||||
.reg_write(reg_write),
|
||||
.alu_op(alu_op)
|
||||
);
|
||||
|
||||
ALUDecoder alu_decoder (
|
||||
opcode[5],
|
||||
funct_3,
|
||||
funct_7[5],
|
||||
alu_op,
|
||||
alu_ctrl,
|
||||
branch_neg
|
||||
alu_decoder alu_decoder (
|
||||
.opcode(opcode[5]),
|
||||
.funct_3(funct_3),
|
||||
.funct_7_5(funct_7[5]),
|
||||
.alu_op(alu_op),
|
||||
.alu_ctrl(alu_ctrl),
|
||||
.branch_neg(branch_neg)
|
||||
);
|
||||
endmodule
|
||||
|
@ -1,237 +0,0 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module PipelinedCPU(
|
||||
input logic clk, reset
|
||||
);
|
||||
logic[31:0] fetch_pc, fetch_pc_next;
|
||||
|
||||
logic[31:0] fetch_pc_plus_4, execute_pc_target;
|
||||
always_comb begin
|
||||
fetch_pc_plus_4 = fetch_pc + 'd4;
|
||||
case(execute_pc_src)
|
||||
'd0: fetch_pc_next = fetch_pc_plus_4;
|
||||
'd1: fetch_pc_next = execute_pc_target;
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if(reset)
|
||||
fetch_pc <= 'b0;
|
||||
else if(!fetch_stall)
|
||||
fetch_pc <= fetch_pc_next;
|
||||
end
|
||||
|
||||
logic[31:0] fetch_instr;
|
||||
InstructionMemory #(.N(32)) instruction_memory(fetch_pc, fetch_instr);
|
||||
|
||||
logic decode_stall, decode_flush;
|
||||
logic[31:0] decode_instr, decode_pc, decode_pc_plus_4;
|
||||
always_ff @(posedge clk) begin
|
||||
if(decode_flush) begin
|
||||
decode_instr <= 'd0;
|
||||
decode_pc <= 'd0;
|
||||
decode_pc_plus_4 <= 'd0;
|
||||
end else if(!decode_stall) begin
|
||||
decode_instr <= fetch_instr;
|
||||
decode_pc <= fetch_pc;
|
||||
decode_pc_plus_4 <= fetch_pc_plus_4;
|
||||
end
|
||||
end
|
||||
|
||||
logic[4:0] decode_rs_1, decode_rs_2, decode_rd;
|
||||
assign decode_rs_1 = decode_instr[19:15];
|
||||
assign decode_rs_2 = decode_instr[24:20];
|
||||
assign decode_rd = decode_instr[11:7];
|
||||
|
||||
logic writeback_reg_write;
|
||||
logic[31:0] decode_read_data_1, decode_read_data_2;
|
||||
logic[31:0] result, writeback_result;
|
||||
RegisterFile #(.N_REG_ADDR(5), .N_DATA(32)) register_file(
|
||||
~clk,
|
||||
reset,
|
||||
decode_instr[19:15],
|
||||
decode_instr[24:20],
|
||||
writeback_rd,
|
||||
writeback_reg_write,
|
||||
writeback_result,
|
||||
decode_read_data_1,
|
||||
decode_read_data_2
|
||||
);
|
||||
|
||||
logic[1:0] decode_result_src;
|
||||
logic[1:0] decode_imm_src;
|
||||
logic[2:0] decode_alu_ctrl;
|
||||
logic decode_reg_write, decode_branch_alu_neg;
|
||||
ControlUnit control_unit(
|
||||
.opcode(decode_instr[6:0]),
|
||||
.funct_3(decode_instr[14:12]),
|
||||
.funct_7(decode_instr[31:25]),
|
||||
.reg_write(decode_reg_write),
|
||||
.result_src(decode_result_src),
|
||||
.mem_write(decode_mem_write),
|
||||
.jump(decode_jump),
|
||||
.branch(decode_branch),
|
||||
.alu_ctrl(decode_alu_ctrl),
|
||||
.alu_src(decode_alu_src),
|
||||
.imm_src(decode_imm_src),
|
||||
.branch_alu_neg(decode_branch_alu_neg)
|
||||
);
|
||||
|
||||
logic[31:0] decode_imm_ext;
|
||||
Extend imm_extend(
|
||||
decode_imm_src[1:0],
|
||||
decode_instr[31:7],
|
||||
decode_imm_ext[31:0]
|
||||
);
|
||||
|
||||
logic execute_reg_write, execute_mem_write, execute_jump, execute_branch, execute_branch_alu_neg, execute_alu_src;
|
||||
logic[1:0] execute_result_src;
|
||||
logic[2:0] execute_alu_ctrl;
|
||||
logic[4:0] execute_rs_1, execute_rs_2, execute_rd;
|
||||
logic[31:0] execute_pc, execute_pc_plus_4, execute_read_data_1, execute_read_data_2, execute_imm_ext;
|
||||
always_ff @(posedge clk) begin
|
||||
if(execute_flush) begin
|
||||
execute_reg_write <= 'd0;
|
||||
execute_result_src <= 'd0;
|
||||
execute_mem_write <= 'd0;
|
||||
execute_jump <= 'd0;
|
||||
execute_branch <= 'd0;
|
||||
execute_alu_ctrl <= 'd0;
|
||||
execute_alu_src <= 'd0;
|
||||
execute_read_data_1 <= 'd0;
|
||||
execute_read_data_2 <= 'd0;
|
||||
execute_pc <= 'd0;
|
||||
execute_rs_1 <= 'd0;
|
||||
execute_rs_2 <= 'd0;
|
||||
execute_rd <= 'd0;
|
||||
execute_imm_ext <= 'd0;
|
||||
execute_pc_plus_4 <= 'd0;
|
||||
end else if (!decode_stall) begin
|
||||
execute_reg_write <= decode_reg_write;
|
||||
execute_result_src <= decode_result_src;
|
||||
execute_mem_write <= decode_mem_write;
|
||||
execute_jump <= decode_jump;
|
||||
execute_branch <= decode_branch;
|
||||
execute_branch_alu_neg <= decode_branch_alu_neg;
|
||||
execute_alu_ctrl <= decode_alu_ctrl;
|
||||
execute_alu_src <= decode_alu_src;
|
||||
execute_read_data_1 <= decode_read_data_1;
|
||||
execute_read_data_2 <= decode_read_data_2;
|
||||
execute_pc <= decode_pc;
|
||||
execute_rs_1 <= decode_rs_1;
|
||||
execute_rs_2 <= decode_rs_2;
|
||||
execute_rd <= decode_rd;
|
||||
execute_imm_ext <= decode_imm_ext;
|
||||
execute_pc_plus_4 <= decode_pc_plus_4;
|
||||
end
|
||||
end
|
||||
|
||||
JumpControl jump_control(
|
||||
execute_jump,
|
||||
execute_branch,
|
||||
execute_branch_alu_neg,
|
||||
execute_zero,
|
||||
execute_pc_src
|
||||
);
|
||||
|
||||
logic[31:0] execute_src_a, memory_alu_result;
|
||||
logic[1:0] execute_forward_a;
|
||||
always_comb begin
|
||||
case(execute_forward_a)
|
||||
'b00: execute_src_a = execute_read_data_1;
|
||||
'b01: execute_src_a = writeback_result;
|
||||
'b10: execute_src_a = memory_alu_result;
|
||||
'b11: execute_src_a = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic[31:0] execute_write_data;
|
||||
logic[1:0] execute_forward_b;
|
||||
always_comb begin
|
||||
case(execute_forward_b)
|
||||
'b00: execute_write_data = execute_read_data_2;
|
||||
'b01: execute_write_data = writeback_result;
|
||||
'b10: execute_write_data = memory_alu_result;
|
||||
'b11: execute_write_data = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic[31:0] execute_src_b;
|
||||
always_comb begin
|
||||
case(execute_alu_src)
|
||||
'd0: execute_src_b = execute_write_data;
|
||||
'd1: execute_src_b = execute_imm_ext;
|
||||
endcase
|
||||
end
|
||||
|
||||
logic[31:0] execute_alu_result;
|
||||
logic[3:0] execute_alu_status;
|
||||
assign execute_zero = execute_alu_status[2];
|
||||
ALU alu(
|
||||
execute_src_a,
|
||||
execute_src_b,
|
||||
execute_alu_ctrl,
|
||||
execute_alu_result,
|
||||
execute_alu_status
|
||||
);
|
||||
|
||||
assign execute_pc_target = execute_pc + execute_imm_ext;
|
||||
|
||||
logic memory_reg_write, memory_mem_write;
|
||||
logic[1:0] memory_result_src;
|
||||
logic[4:0] memory_rd;
|
||||
logic[31:0] memory_pc_plus_4, memory_write_data;
|
||||
always_ff @(posedge clk) begin
|
||||
memory_reg_write <= execute_reg_write;
|
||||
memory_result_src <= execute_result_src;
|
||||
memory_mem_write <= execute_mem_write;
|
||||
memory_alu_result <= execute_alu_result;
|
||||
memory_write_data <= execute_write_data;
|
||||
memory_rd <= execute_rd;
|
||||
memory_pc_plus_4 <= execute_pc_plus_4;
|
||||
end
|
||||
|
||||
logic[31:0] memory_read_data;
|
||||
DataMemory data_memory(
|
||||
clk,
|
||||
reset,
|
||||
memory_alu_result,
|
||||
memory_mem_write,
|
||||
memory_write_data,
|
||||
memory_read_data
|
||||
);
|
||||
|
||||
logic[1:0] writeback_result_src;
|
||||
logic[4:0] writeback_rd;
|
||||
logic[31:0] writeback_pc_plus_4, writeback_alu_result, writeback_read_data;
|
||||
always_ff @(posedge clk) begin
|
||||
writeback_reg_write <= memory_reg_write;
|
||||
writeback_result_src <= memory_result_src;
|
||||
writeback_alu_result <= memory_alu_result;
|
||||
writeback_read_data <= memory_read_data;
|
||||
writeback_rd <= memory_rd;
|
||||
writeback_pc_plus_4 <= memory_pc_plus_4;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
case(writeback_result_src)
|
||||
'b00: writeback_result = writeback_alu_result;
|
||||
'b01: writeback_result = writeback_read_data;
|
||||
'b10: writeback_result = writeback_pc_plus_4;
|
||||
'b11: writeback_result = 'dx;
|
||||
endcase
|
||||
end
|
||||
|
||||
HazardUnit hazard_unit(
|
||||
reset,
|
||||
execute_pc_src, execute_result_src[0],
|
||||
memory_reg_write, writeback_reg_write,
|
||||
decode_rs_1, decode_rs_2,
|
||||
execute_rs_1, execute_rs_2,
|
||||
execute_rd, memory_rd, writeback_rd,
|
||||
fetch_stall, decode_stall,
|
||||
decode_flush, execute_flush,
|
||||
execute_forward_a, execute_forward_b
|
||||
);
|
||||
|
||||
endmodule
|
@ -1,4 +1,4 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
// 2**N to N Priority encoder
|
||||
module priority_encoder #(
|
||||
|
@ -1,3 +1,5 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
module register_file (
|
||||
|
@ -1,6 +1,6 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module RotateCRP #(
|
||||
module rotate_cru#(
|
||||
parameter ADDR_SIZE = 32,
|
||||
parameter NUM_SETS = 16,
|
||||
parameter NUM_WAYS = 4,
|
||||
|
@ -1,4 +1,4 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
package rv32i_defs;
|
||||
// Sizes in bits
|
||||
@ -27,5 +27,4 @@ package rv32i_defs;
|
||||
LUI = 'b0110111,
|
||||
AUIPC = 'b0010111
|
||||
} opcode_fmt_t;
|
||||
|
||||
endpackage
|
||||
|
@ -1,3 +1,5 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
module single_cycle_datapath (
|
||||
|
@ -1,6 +1,6 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module TwoWayLRUCache #(
|
||||
module two_way_lru_cache #(
|
||||
parameter ADDR_SIZE = 32,
|
||||
parameter NUM_SETS = 16,
|
||||
parameter BLOCK_SIZE = 32
|
||||
|
@ -1,6 +1,6 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module TwoWayLRUCRU #(
|
||||
module two_way_lru_cru #(
|
||||
parameter ADDR_SIZE = 32,
|
||||
parameter NUM_SETS = 16,
|
||||
parameter BLOCK_SIZE = 32
|
||||
|
@ -1,4 +1,4 @@
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/utils.cmake)
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/utils.cmake)
|
||||
|
||||
find_package(verilator HINTS $ENV{VERILATOR_ROOT})
|
||||
if (NOT verilator_FOUND)
|
||||
@ -13,66 +13,86 @@ find_package(SystemCLanguage QUIET)
|
||||
rvscc_add_test(
|
||||
NAME alu
|
||||
TOP test_alu
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/alu.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_alu.sv
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/rv32i_defs.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/alu.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_alu.sv
|
||||
)
|
||||
|
||||
rvscc_add_test(
|
||||
NAME priority-encoder
|
||||
TOP test_priority_encoder
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/priority_encoder.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_priority_encoder.sv
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/priority_encoder.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_priority_encoder.sv
|
||||
)
|
||||
|
||||
rvscc_add_test(
|
||||
NAME data-memory
|
||||
TOP test_data_memory
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory_if.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_data_memory.sv
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/rv32i_defs.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/data_memory_if.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/data_memory.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_data_memory.sv
|
||||
)
|
||||
|
||||
rvscc_add_test(
|
||||
NAME imm-extend
|
||||
TOP test_imm_extend
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/imm_extend.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_imm_extend.sv
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/imm_extend.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_imm_extend.sv
|
||||
)
|
||||
|
||||
rvscc_add_test(
|
||||
NAME register-file
|
||||
TOP test_register_file
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/register_file.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_register_file.sv
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/rv32i_defs.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/register_file.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_register_file.sv
|
||||
)
|
||||
|
||||
rvscc_add_test(
|
||||
NAME instruction_memory
|
||||
TOP test_instr_memory
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/instr_memory_if.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/instr_memory.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_instr_memory.sv
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/rv32i_defs.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/instr_memory_if.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/instr_memory.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_instr_memory.sv
|
||||
)
|
||||
|
||||
rvscc_add_test(
|
||||
NAME single-cycle-core
|
||||
TOP test_single_cycle_core
|
||||
SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../rtl/rv32i_defs.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/single_cycle_datapath.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory_if.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/data_memory.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/instr_memory_if.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/instr_memory.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/jump_control.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/control_unit.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/alu_decoder.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/main_decoder.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/register_file.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/imm_extend.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../rtl/alu.sv
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_single_cycle_core.sv
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/rv32i_defs.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/single_cycle_datapath.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/data_memory_if.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/data_memory.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/instr_memory_if.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/instr_memory.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/jump_control.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/control_unit.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/alu_decoder.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/main_decoder.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/register_file.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/imm_extend.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/alu.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_single_cycle_core.sv
|
||||
)
|
||||
|
||||
rvscc_add_test(
|
||||
NAME five-stage-pipeline-core
|
||||
TOP test_five_stage_pipeline_core
|
||||
SOURCES ${PROJECT_SOURCE_DIR}/rtl/rv32i_defs.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/five_stage_pipeline_datapath.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/data_memory_if.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/data_memory.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/instr_memory_if.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/instr_memory.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/jump_control.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/control_unit.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/alu_decoder.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/main_decoder.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/register_file.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/imm_extend.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/alu.sv
|
||||
${PROJECT_SOURCE_DIR}/rtl/hazard_unit.sv
|
||||
${PROJECT_SOURCE_DIR}/test/test_five_stage_pipeline_core.sv
|
||||
)
|
||||
|
@ -1,3 +1,5 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
import rv32i_defs::*;
|
||||
|
||||
module test_alu ();
|
||||
|
37
test/test_five_stage_pipeline_core.sv
Normal file
37
test/test_five_stage_pipeline_core.sv
Normal file
@ -0,0 +1,37 @@
|
||||
`include "timescale.sv"
|
||||
|
||||
module test_five_stage_pipeline_core ();
|
||||
logic clk, rst;
|
||||
always #1 clk = ~clk;
|
||||
|
||||
instr_memory_if instr_mem_if ();
|
||||
instr_memory #(
|
||||
.FILE_PATH("../fw/test/test-core.mem")
|
||||
) instr_mem (
|
||||
.instr_mem_if(instr_mem_if.mem)
|
||||
);
|
||||
|
||||
data_memory_if data_mem_if (
|
||||
.clk(clk),
|
||||
.rst(rst)
|
||||
);
|
||||
data_memory #(.NUM_BLOCKS(128)) data_mem (.data_mem_if(data_mem_if.ram));
|
||||
|
||||
five_stage_pipeline_datapath dut (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.instr_mem_if(instr_mem_if.datapath),
|
||||
.data_mem_if(data_mem_if.datapath)
|
||||
);
|
||||
|
||||
always @(posedge clk) data_mem_if.check_fw_test_core_assertions();
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
rst = 1;
|
||||
#4;
|
||||
rst = 0;
|
||||
#1000;
|
||||
$error("Program execution timeout");
|
||||
end
|
||||
endmodule
|
@ -1,11 +1,15 @@
|
||||
`timescale 1ns / 1ps
|
||||
`include "timescale.sv"
|
||||
|
||||
module test_single_cycle_core ();
|
||||
logic clk, rst;
|
||||
always #1 clk = ~clk;
|
||||
|
||||
instr_memory_if instr_mem_if();
|
||||
instr_memory #(.FILE_PATH("test-core.mem")) instr_mem (.instr_mem_if(instr_mem_if.mem));
|
||||
instr_memory_if instr_mem_if ();
|
||||
instr_memory #(
|
||||
.FILE_PATH("../fw/test/test-core.mem")
|
||||
) instr_mem (
|
||||
.instr_mem_if(instr_mem_if.mem)
|
||||
);
|
||||
|
||||
data_memory_if data_mem_if (
|
||||
.clk(clk),
|
||||
@ -19,25 +23,15 @@ module test_single_cycle_core ();
|
||||
.instr_mem_if(instr_mem_if.datapath),
|
||||
.data_mem_if(data_mem_if.datapath)
|
||||
);
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (data_mem_if.write_enable) begin
|
||||
if(data_mem_if.addr == 'd100 && data_mem_if.write_data == 'd25) begin
|
||||
$finish;
|
||||
end else if (data_mem_if.addr != 'd96) // assert
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) data_mem_if.check_fw_test_core_assertions();
|
||||
|
||||
initial begin
|
||||
$dumpfile("single_cycle.vcd");
|
||||
$dumpvars(1, dut);
|
||||
clk = 0;
|
||||
rst = 1;
|
||||
#4;
|
||||
rst = 0;
|
||||
#1000;
|
||||
$display("Hello world");
|
||||
$finish;
|
||||
$error("Program execution timeout");
|
||||
end
|
||||
endmodule
|
||||
|
Loading…
Reference in New Issue
Block a user