Uploaded 10_19_2019
This commit is contained in:
parent
e56189c12b
commit
90a5a79a45
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// File Name : DPROM_8Kx128.v
|
||||
// Used on :
|
||||
// Author : Ted Fried, MicroCore Labs
|
||||
// Creation : 8/57/2017
|
||||
// Code Type : Behavioral
|
||||
//
|
||||
// Description:
|
||||
// ============
|
||||
// Xilinx ROM behavioral model.
|
||||
//
|
||||
//
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
`timescale 1ns/100ps
|
||||
|
||||
|
||||
|
||||
module DPROM_8Kx128
|
||||
(
|
||||
input clka,
|
||||
input[12:0] addra,
|
||||
output reg[127:0] douta,
|
||||
|
||||
input clkb,
|
||||
input[12:0] addrb,
|
||||
output reg[127:0] doutb
|
||||
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
integer file, k, l;
|
||||
reg [127:0] ram_array[0:8191];
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
initial
|
||||
begin
|
||||
|
||||
// Zero out the RAM so there are no X's
|
||||
for (k = 0; k < 8192 ; k = k + 1)
|
||||
begin
|
||||
ram_array[k] = 'h0;
|
||||
end
|
||||
|
||||
|
||||
// Load the instructions into the array using ASCII byte file
|
||||
$readmemh("D:/MCL/MCLR5/Quad_Issue/usercode_rom.hex", ram_array);
|
||||
//$readmemb("C:/MCL/MCLR5/Quad_Issue/usercode_rom.hex", ram_array);
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
always @(posedge clka)
|
||||
begin
|
||||
|
||||
douta <= ram_array[addra];
|
||||
doutb <= ram_array[addrb];
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,491 @@
|
|||
//
|
||||
//
|
||||
// File Name : MCLR5.v
|
||||
// Author : Ted Fried, MicroCore Labs
|
||||
// Creation : 4/27/2018
|
||||
// Code Type : Synthesizable
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Description:
|
||||
// ============
|
||||
//
|
||||
// Quad-issue Superscalar Risc V Processor
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (C) 2018 by Ted Fried info@MicroCoreLabs.com
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software and its
|
||||
// documentation for any purpose and without fee is hereby granted, provided
|
||||
// that the above copyright notice appear in all copies and that both that
|
||||
// copyright notice and this permission notice appear in supporting documentation.
|
||||
// This software is provided "as is" without express or implied warranty.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Modification History:
|
||||
// =====================
|
||||
//
|
||||
// Revision 1 4/27/18
|
||||
// Initial revision
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
module MCLR5
|
||||
(
|
||||
input CORE_CLK,
|
||||
input RST_n,
|
||||
|
||||
output [31:0] LOAD_STORE_ADDRESS,
|
||||
output [31:0] STORE_DATA,
|
||||
input [31:0] LOAD_DATA,
|
||||
output LOAD_REQ,
|
||||
output STORE_REQ
|
||||
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
// Internal Signals
|
||||
|
||||
reg new_pc_stall = 'h0;
|
||||
reg alu0_load_req_d = 'h0;
|
||||
reg alu1_load_req_d = 'h0;
|
||||
reg alu2_load_req_d = 'h0;
|
||||
reg alu3_load_req_d = 'h0;
|
||||
reg [31:0] register_1 = 'h0;
|
||||
reg [31:0] register_2 = 'h0;
|
||||
reg [31:0] register_3 = 'h0;
|
||||
reg [31:0] register_4 = 'h0;
|
||||
reg [3:0] loadstore_stall = 'h0;
|
||||
reg [31:0] new_pc = 'h0;
|
||||
wire alu0_load_req;
|
||||
wire alu1_load_req;
|
||||
wire alu2_load_req;
|
||||
wire alu3_load_req;
|
||||
wire alu0_store_req;
|
||||
wire alu1_store_req;
|
||||
wire alu2_store_req;
|
||||
wire alu3_store_req;
|
||||
wire [31:0] i_immediate;
|
||||
wire [255:0] program_rom_data;
|
||||
wire [31:0] new_pc_plus1;
|
||||
wire [32:0] alu0_rd;
|
||||
wire [32:0] alu1_rd;
|
||||
wire [32:0] alu2_rd;
|
||||
wire [32:0] alu3_rd;
|
||||
wire [32:0] alu0_newpc;
|
||||
wire [32:0] alu1_newpc;
|
||||
wire [32:0] alu2_newpc;
|
||||
wire [32:0] alu3_newpc;
|
||||
wire [31:0] alu0_opcode;
|
||||
wire [31:0] alu1_opcode;
|
||||
wire [31:0] alu2_opcode;
|
||||
wire [31:0] alu3_opcode;
|
||||
wire [31:0] alu0_pc;
|
||||
wire [31:0] alu1_pc;
|
||||
wire [31:0] alu2_pc;
|
||||
wire [31:0] alu3_pc;
|
||||
wire [31:0] alu0_rs1;
|
||||
wire [31:0] alu1_rs1;
|
||||
wire [31:0] alu2_rs1;
|
||||
wire [31:0] alu3_rs1;
|
||||
wire [31:0] alu0_rs2;
|
||||
wire [31:0] alu1_rs2;
|
||||
wire [31:0] alu2_rs2;
|
||||
wire [31:0] alu3_rs2;
|
||||
wire [31:0] alu0_load_store_address;
|
||||
wire [31:0] alu0_store_data;
|
||||
wire [31:0] alu0_load_data;
|
||||
wire [4:0] alu0_opcode_rs1;
|
||||
wire [4:0] alu1_opcode_rs1;
|
||||
wire [4:0] alu2_opcode_rs1;
|
||||
wire [4:0] alu3_opcode_rs1;
|
||||
wire [4:0] alu0_opcode_rs2;
|
||||
wire [4:0] alu1_opcode_rs2;
|
||||
wire [4:0] alu2_opcode_rs2;
|
||||
wire [4:0] alu3_opcode_rs2;
|
||||
wire [4:0] alu0_opcode_rd;
|
||||
wire [4:0] alu1_opcode_rd;
|
||||
wire [4:0] alu2_opcode_rd;
|
||||
wire [4:0] alu3_opcode_rd;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// For Xilinx FPGAs
|
||||
DPROM_8Kx128 code_rom
|
||||
(
|
||||
.clka (CORE_CLK),
|
||||
.addra (new_pc[14:2]),
|
||||
.douta (program_rom_data[127:0]),
|
||||
|
||||
.clkb (CORE_CLK),
|
||||
.addrb (new_pc_plus1[14:2]),
|
||||
.doutb (program_rom_data[255:128])
|
||||
);
|
||||
|
||||
*/
|
||||
|
||||
DPROM_8Kx128 code_rom (
|
||||
.address_a (new_pc[14:2]), // input, width = 13, ram_input.address_a
|
||||
.address_b (new_pc_plus1[14:2]), // input, width = 13, .address_b
|
||||
.clock (CORE_CLK), // input, width = 1, .clock
|
||||
.q_a (program_rom_data[127:0]), // output, width = 128, ram_output.q_a
|
||||
.q_b (program_rom_data[255:128]) // output, width = 128, .q_b
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
assign new_pc_plus1 = new_pc + 3'h4;
|
||||
|
||||
|
||||
assign alu0_pc = new_pc;
|
||||
assign alu1_pc = new_pc + 1;
|
||||
assign alu2_pc = new_pc + 2;
|
||||
assign alu3_pc = new_pc + 3;
|
||||
|
||||
|
||||
|
||||
assign alu0_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[31:0] :
|
||||
(new_pc[1:0]==2'h1) ? program_rom_data[63:32] :
|
||||
(new_pc[1:0]==2'h2) ? program_rom_data[95:64] :
|
||||
program_rom_data[127:96] ;
|
||||
|
||||
|
||||
assign alu1_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[63:32] :
|
||||
(new_pc[1:0]==2'h1) ? program_rom_data[95:64] :
|
||||
(new_pc[1:0]==2'h2) ? program_rom_data[127:96] :
|
||||
program_rom_data[159:128] ;
|
||||
|
||||
assign alu2_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[95:64] :
|
||||
(new_pc[1:0]==2'h1) ? program_rom_data[127:96] :
|
||||
(new_pc[1:0]==2'h2) ? program_rom_data[159:128] :
|
||||
program_rom_data[191:160] ;
|
||||
|
||||
assign alu3_opcode = (new_pc[1:0]==2'h0) ? program_rom_data[127:96] :
|
||||
(new_pc[1:0]==2'h1) ? program_rom_data[159:128] :
|
||||
(new_pc[1:0]==2'h2) ? program_rom_data[191:160] :
|
||||
program_rom_data[223:192] ;
|
||||
|
||||
|
||||
|
||||
// Register decodes from the opcode
|
||||
//
|
||||
assign alu0_opcode_rs1 = alu0_opcode[19:15];
|
||||
assign alu0_opcode_rs2 = alu0_opcode[24:20];
|
||||
assign alu0_opcode_rd = alu0_opcode[11:7];
|
||||
|
||||
assign alu1_opcode_rs1 = alu1_opcode[19:15];
|
||||
assign alu1_opcode_rs2 = alu1_opcode[24:20];
|
||||
assign alu1_opcode_rd = alu1_opcode[11:7];
|
||||
|
||||
assign alu2_opcode_rs1 = alu2_opcode[19:15];
|
||||
assign alu2_opcode_rs2 = alu2_opcode[24:20];
|
||||
assign alu2_opcode_rd = alu2_opcode[11:7];
|
||||
|
||||
assign alu3_opcode_rs1 = alu3_opcode[19:15];
|
||||
assign alu3_opcode_rs2 = alu3_opcode[24:20];
|
||||
assign alu3_opcode_rd = alu3_opcode[11:7];
|
||||
|
||||
|
||||
assign LOAD_STORE_ADDRESS = alu0_load_store_address;
|
||||
assign STORE_DATA = alu0_store_data;
|
||||
assign alu0_load_data = LOAD_DATA;
|
||||
assign LOAD_REQ = alu0_load_req;
|
||||
assign STORE_REQ = alu0_store_req;
|
||||
|
||||
|
||||
|
||||
// Register read-port routing
|
||||
// If the previous alu has modified a register that this alu needs, then use this value,
|
||||
// otherwise take the register from the main register-file.
|
||||
//
|
||||
|
||||
assign alu0_rs1 = (alu0_opcode_rs1 == 5'h00) ? 32'h0 :
|
||||
(alu0_opcode_rs1 == 5'h01) ? register_1 :
|
||||
(alu0_opcode_rs1 == 5'h02) ? register_2 :
|
||||
(alu0_opcode_rs1 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
|
||||
|
||||
assign alu0_rs2 = (alu0_opcode_rs2 == 5'h00) ? 32'h0 :
|
||||
(alu0_opcode_rs2 == 5'h01) ? register_1 :
|
||||
(alu0_opcode_rs2 == 5'h02) ? register_2 :
|
||||
(alu0_opcode_rs2 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
assign alu1_rs1 = ( alu0_rd[32]==1'b1 && (alu1_opcode_rs1==alu0_opcode_rd) ) ? alu0_rd[31:0] :
|
||||
(alu1_opcode_rs1 == 5'h00) ? 32'h0 :
|
||||
(alu1_opcode_rs1 == 5'h01) ? register_1 :
|
||||
(alu1_opcode_rs1 == 5'h02) ? register_2 :
|
||||
(alu1_opcode_rs1 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
|
||||
|
||||
assign alu1_rs2 = ( alu0_rd[32]==1'b1 && (alu1_opcode_rs2==alu0_opcode_rd) ) ? alu0_rd[31:0] :
|
||||
(alu1_opcode_rs2 == 5'h00) ? 32'h0 :
|
||||
(alu1_opcode_rs2 == 5'h01) ? register_1 :
|
||||
(alu1_opcode_rs2 == 5'h02) ? register_2 :
|
||||
(alu1_opcode_rs2 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
assign alu2_rs1 = ( alu1_rd[32]==1'b1 && (alu2_opcode_rs1==alu1_opcode_rd) ) ? alu1_rd[31:0] :
|
||||
( alu0_rd[32]==1'b1 && (alu2_opcode_rs1==alu0_opcode_rd) ) ? alu0_rd[31:0] :
|
||||
(alu2_opcode_rs1 == 5'h00) ? 32'h0 :
|
||||
(alu2_opcode_rs1 == 5'h01) ? register_1 :
|
||||
(alu2_opcode_rs1 == 5'h02) ? register_2 :
|
||||
(alu2_opcode_rs1 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
|
||||
|
||||
|
||||
assign alu2_rs2 = ( alu1_rd[32]==1'b1 && (alu2_opcode_rs2==alu1_opcode_rd) ) ? alu1_rd[31:0] :
|
||||
( alu0_rd[32]==1'b1 && (alu2_opcode_rs2==alu0_opcode_rd) ) ? alu0_rd[31:0] :
|
||||
(alu2_opcode_rs2 == 5'h00) ? 32'h0 :
|
||||
(alu2_opcode_rs2 == 5'h01) ? register_1 :
|
||||
(alu2_opcode_rs2 == 5'h02) ? register_2 :
|
||||
(alu2_opcode_rs2 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
assign alu3_rs1 = ( alu2_rd[32]==1'b1 && (alu3_opcode_rs1==alu2_opcode_rd) ) ? alu2_rd[31:0] :
|
||||
( alu1_rd[32]==1'b1 && (alu3_opcode_rs1==alu1_opcode_rd) ) ? alu1_rd[31:0] :
|
||||
( alu0_rd[32]==1'b1 && (alu3_opcode_rs1==alu0_opcode_rd) ) ? alu0_rd[31:0] :
|
||||
(alu3_opcode_rs1 == 5'h00) ? 32'h0 :
|
||||
(alu3_opcode_rs1 == 5'h01) ? register_1 :
|
||||
(alu3_opcode_rs1 == 5'h02) ? register_2 :
|
||||
(alu3_opcode_rs1 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
|
||||
|
||||
|
||||
assign alu3_rs2 = ( alu2_rd[32]==1'b1 && (alu3_opcode_rs2==alu2_opcode_rd) ) ? alu2_rd[31:0] :
|
||||
( alu1_rd[32]==1'b1 && (alu3_opcode_rs2==alu1_opcode_rd) ) ? alu1_rd[31:0] :
|
||||
( alu0_rd[32]==1'b1 && (alu3_opcode_rs2==alu0_opcode_rd) ) ? alu0_rd[31:0] :
|
||||
(alu3_opcode_rs2 == 5'h00) ? 32'h0 :
|
||||
(alu3_opcode_rs2 == 5'h01) ? register_1 :
|
||||
(alu3_opcode_rs2 == 5'h02) ? register_2 :
|
||||
(alu3_opcode_rs2 == 5'h03) ? register_3 :
|
||||
register_4 ;
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Register writebacks
|
||||
//
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
always @(posedge CORE_CLK or negedge RST_n)
|
||||
begin : REGISTER_WRITEBACKS
|
||||
|
||||
if (RST_n==1'b0)
|
||||
begin
|
||||
alu0_load_req_d <= 'h0;
|
||||
new_pc <= 32'hFFFF_FFFC;
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
|
||||
if ( (loadstore_stall == 4'b0000 && (alu0_load_req==1'b1 || alu0_store_req==1'b1) ) ||
|
||||
(loadstore_stall == 4'b0000 && (alu1_load_req==1'b1 || alu1_store_req==1'b1) ) ||
|
||||
(loadstore_stall == 4'b0000 && (alu2_load_req==1'b1 || alu2_store_req==1'b1) ) ||
|
||||
(loadstore_stall == 4'b0000 && (alu3_load_req==1'b1 || alu3_store_req==1'b1) ) )
|
||||
begin
|
||||
loadstore_stall <= 4'b1111; // new_pc_stall for three cycles
|
||||
end
|
||||
else
|
||||
begin
|
||||
loadstore_stall <= { 1'b0 , loadstore_stall[3:1] };
|
||||
end
|
||||
|
||||
|
||||
|
||||
// Writeback register file
|
||||
// Only write back registers that have been updated.
|
||||
// Block register updates if a previous alu is taking a branch
|
||||
//
|
||||
if (new_pc_stall==1'b0 && ((loadstore_stall==4'b0001 || alu0_newpc[32]==1'b0) && alu1_newpc[32]==1'b0 && alu2_newpc[32]==1'b0) && alu3_rd[32]==1'b1)
|
||||
begin
|
||||
case (alu3_opcode_rd)
|
||||
5'h01 : register_1 <= alu3_rd[31:0];
|
||||
5'h02 : register_2 <= alu3_rd[31:0];
|
||||
5'h03 : register_3 <= alu3_rd[31:0];
|
||||
5'h04 : register_4 <= alu3_rd[31:0];
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
else if (new_pc_stall==1'b0 && ((loadstore_stall==4'b0001 || alu0_newpc[32]==1'b0) && alu1_newpc[32]==1'b0) && alu2_rd[32]==1'b1)
|
||||
begin
|
||||
case (alu2_opcode_rd)
|
||||
5'h01 : register_1 <= alu2_rd[31:0];
|
||||
5'h02 : register_2 <= alu2_rd[31:0];
|
||||
5'h03 : register_3 <= alu2_rd[31:0];
|
||||
5'h04 : register_4 <= alu2_rd[31:0];
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
else if (new_pc_stall==1'b0 && (loadstore_stall==4'b0001 || alu0_newpc[32]==1'b0) && alu1_rd[32]==1'b1)
|
||||
begin
|
||||
case (alu1_opcode_rd)
|
||||
5'h01 : register_1 <= alu1_rd[31:0];
|
||||
5'h02 : register_2 <= alu1_rd[31:0];
|
||||
5'h03 : register_3 <= alu1_rd[31:0];
|
||||
5'h04 : register_4 <= alu1_rd[31:0];
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
else if (new_pc_stall==1'b0 && alu0_rd[32]==1'b1)
|
||||
begin
|
||||
case (alu0_opcode_rd)
|
||||
5'h01 : register_1 <= alu0_rd[31:0];
|
||||
5'h02 : register_2 <= alu0_rd[31:0];
|
||||
5'h03 : register_3 <= alu0_rd[31:0];
|
||||
5'h04 : register_4 <= alu0_rd[31:0];
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Update the PC for branches/jumps
|
||||
// Otherwise increment the PC by four
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
if ((new_pc_stall==1'b0 && alu0_newpc[32]==1'b1) && loadstore_stall!=4'b0001)
|
||||
begin
|
||||
new_pc_stall <= 1'b1;
|
||||
new_pc <= alu0_newpc[31:0];
|
||||
end
|
||||
|
||||
else if (new_pc_stall==1'b0 && alu1_newpc[32]==1'b1)
|
||||
begin
|
||||
new_pc_stall <= 1'b1;
|
||||
new_pc <= alu1_newpc[31:0];
|
||||
end
|
||||
|
||||
else if (new_pc_stall==1'b0 && alu2_newpc[32]==1'b1)
|
||||
begin
|
||||
new_pc_stall <= 1'b1;
|
||||
new_pc <= alu2_newpc[31:0];
|
||||
end
|
||||
|
||||
else if (new_pc_stall==1'b0 && alu3_newpc[32]==1'b1)
|
||||
begin
|
||||
new_pc_stall <= 1'b1;
|
||||
new_pc <= alu3_newpc[31:0];
|
||||
end
|
||||
|
||||
else
|
||||
begin
|
||||
new_pc <= new_pc + 32'h0000_0004;
|
||||
new_pc_stall <= 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
end // Register writebacks
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// MCLR5 ALU cores
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
MCLR5_alu mclr5_alu0
|
||||
(
|
||||
.OPCODE (alu0_opcode),
|
||||
.PC (alu0_pc),
|
||||
.RS1 (alu0_rs1),
|
||||
.RS2 (alu0_rs2),
|
||||
.RD (alu0_rd),
|
||||
.NEWPC (alu0_newpc),
|
||||
.LOAD_DATA (alu0_load_data),
|
||||
.STORE_DATA (alu0_store_data),
|
||||
.LOAD_REQ (alu0_load_req),
|
||||
.STORE_REQ (alu0_store_req),
|
||||
.LOAD_STORE_ADDRESS (alu0_load_store_address)
|
||||
);
|
||||
|
||||
|
||||
MCLR5_alu mclr5_alu1
|
||||
(
|
||||
.OPCODE (alu1_opcode),
|
||||
.PC (alu1_pc),
|
||||
.RS1 (alu1_rs1),
|
||||
.RS2 (alu1_rs2),
|
||||
.RD (alu1_rd),
|
||||
.NEWPC (alu1_newpc),
|
||||
.LOAD_DATA (),
|
||||
.STORE_DATA (),
|
||||
.LOAD_REQ (alu1_load_req),
|
||||
.STORE_REQ (alu1_store_req),
|
||||
.LOAD_STORE_ADDRESS ()
|
||||
);
|
||||
|
||||
|
||||
MCLR5_alu mclr5_alu2
|
||||
(
|
||||
.OPCODE (alu2_opcode),
|
||||
.PC (alu2_pc),
|
||||
.RS1 (alu2_rs1),
|
||||
.RS2 (alu2_rs2),
|
||||
.RD (alu2_rd),
|
||||
.NEWPC (alu2_newpc),
|
||||
.LOAD_DATA (),
|
||||
.STORE_DATA (),
|
||||
.LOAD_REQ (alu2_load_req),
|
||||
.STORE_REQ (alu2_store_req),
|
||||
.LOAD_STORE_ADDRESS ()
|
||||
);
|
||||
|
||||
|
||||
|
||||
MCLR5_alu mclr5_alu3
|
||||
(
|
||||
.OPCODE (alu3_opcode),
|
||||
.PC (alu3_pc),
|
||||
.RS1 (alu3_rs1),
|
||||
.RS2 (alu3_rs2),
|
||||
.RD (alu3_rd),
|
||||
.NEWPC (alu3_newpc),
|
||||
.LOAD_DATA (),
|
||||
.STORE_DATA (),
|
||||
.LOAD_REQ (alu3_load_req),
|
||||
.STORE_REQ (alu3_store_req),
|
||||
.LOAD_STORE_ADDRESS ()
|
||||
);
|
||||
|
||||
|
||||
|
||||
endmodule // MCLR5.v
|
|
@ -0,0 +1,206 @@
|
|||
//
|
||||
//
|
||||
// File Name : MCLR5_alu.v
|
||||
// Author : Ted Fried, MicroCore Labs
|
||||
// Creation : 4/21/2018
|
||||
// Code Type : Synthesizable
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Description:
|
||||
// ============
|
||||
//
|
||||
// Quad-issue Superscalar Risc V Processor ALU core
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (C) 2018 by Ted Fried info@MicroCoreLabs.com
|
||||
//
|
||||
// Permission to use, copy, modify, and distribute this software and its
|
||||
// documentation for any purpose and without fee is hereby granted, provided
|
||||
// that the above copyright notice appear in all copies and that both that
|
||||
// copyright notice and this permission notice appear in supporting documentation.
|
||||
// This software is provided "as is" without express or implied warranty.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Modification History:
|
||||
// =====================
|
||||
//
|
||||
// Revision 1 4/21/18
|
||||
// Initial revision
|
||||
//
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
module MCLR5_alu
|
||||
(
|
||||
|
||||
input [31:0] OPCODE,
|
||||
input [31:0] PC,
|
||||
|
||||
input [31:0] RS1,
|
||||
input [31:0] RS2,
|
||||
output reg [32:0] RD,
|
||||
output reg [32:0] NEWPC,
|
||||
input [31:0] LOAD_DATA,
|
||||
output [31:0] STORE_DATA,
|
||||
output reg LOAD_REQ,
|
||||
output reg STORE_REQ,
|
||||
output reg [31:0] LOAD_STORE_ADDRESS
|
||||
|
||||
);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Internal Signals
|
||||
|
||||
wire beq_taken;
|
||||
wire bne_taken;
|
||||
wire blt_taken;
|
||||
wire bge_taken;
|
||||
wire bltu_taken;
|
||||
wire bgeu_taken;
|
||||
wire slti_true;
|
||||
wire sltiu_true;
|
||||
wire slt_true;
|
||||
wire sltu_true;
|
||||
wire [31:0] i_immediate;
|
||||
wire [31:0] s_immediate;
|
||||
wire [31:0] b_immediate;
|
||||
wire [31:0] u_immediate;
|
||||
wire [31:0] j_immediate;
|
||||
wire [31:0] slli_result;
|
||||
wire [31:0] srli_result;
|
||||
wire [31:0] srai_result;
|
||||
wire [31:0] sll_result;
|
||||
wire [31:0] srl_result;
|
||||
wire [31:0] sra_result;
|
||||
wire [31:0] pc_adjusted;
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// RISC V ALU
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
assign i_immediate = { {21{OPCODE[31]}} , OPCODE[30:25] , OPCODE[24:21] , OPCODE[20] } ;
|
||||
assign s_immediate = { {21{OPCODE[31]}} , OPCODE[30:25] , OPCODE[11:8] , OPCODE[7] } ;
|
||||
assign b_immediate = { {20{OPCODE[31]}} , OPCODE[7] , OPCODE[30:25] , OPCODE[11:8] , 1'b0 } ;
|
||||
assign u_immediate = { OPCODE[31] , OPCODE[30:20] , OPCODE[19:12] , 12'b0 } ;
|
||||
assign j_immediate = { {12{OPCODE[31]}} , OPCODE[19:12] , OPCODE[20] , OPCODE[30:25] , OPCODE[24:21] , 1'b0 } ;
|
||||
|
||||
|
||||
assign slti_true = ($signed(RS1) < $signed(i_immediate)) ? 32'h0000_0001 : 32'h0000_0000;
|
||||
assign sltiu_true = (RS1 < i_immediate) ? 32'h0000_0001 : 32'h0000_0000;
|
||||
assign slt_true = ($signed(RS1) < $signed(RS2)) ? 32'h0000_0001 : 32'h0000_0000;
|
||||
assign sltu_true = (RS1 < RS2) ? 32'h0000_0001 : 32'h0000_0000;
|
||||
|
||||
|
||||
assign slli_result = 32'h0123_4567;
|
||||
assign srli_result = 32'h0123_4567;
|
||||
assign srai_result = 32'h0123_4567;
|
||||
assign sll_result = 32'h0123_4567;
|
||||
assign srl_result = 32'h0123_4567;
|
||||
assign sra_result = 32'h0123_4567;
|
||||
|
||||
assign beq_taken = (RS1 == RS1) ? 1'b1 : 1'b0;
|
||||
assign bne_taken = (RS1 != RS1) ? 1'b1 : 1'b0;
|
||||
assign blt_taken = ($signed(RS1) < $signed(RS2)) ? 1'b1 : 1'b0;
|
||||
assign bge_taken = ($signed(RS1) >= $signed(RS2)) ? 1'b1 : 1'b0;
|
||||
assign bltu_taken = (RS1 < RS2) ? 1'b1 : 1'b0;
|
||||
assign bgeu_taken = (RS1 >= RS2) ? 1'b1 : 1'b0;
|
||||
|
||||
|
||||
assign pc_adjusted = PC - 4'h4; // Subtracts pipelined PC to the true PC
|
||||
|
||||
assign STORE_DATA = RS2;
|
||||
|
||||
|
||||
always @* begin
|
||||
casex (OPCODE)
|
||||
|
||||
32'b???????_?????_?????_???_?????_01101?? : RD = { 1'b1 , {u_immediate[31:12] , 12'b0 } } ; // LUI
|
||||
32'b???????_?????_?????_???_?????_00101?? : RD = { 1'b1 , PC + {u_immediate[31:12] , 12'b0 } } ; // AUIPC
|
||||
32'b???????_?????_?????_???_?????_11011?? : RD = { 1'b1 , PC + 3'h4 } ; // JAL
|
||||
32'b???????_?????_?????_???_?????_11001?? : RD = { 1'b1 , PC + 3'h4 } ; // JALR
|
||||
32'b???????_?????_?????_000_?????_00100?? : RD = { 1'b1 , RS1 + i_immediate } ; // ADDI
|
||||
32'b???????_?????_?????_010_?????_00100?? : RD = { 1'b1 , slti_true } ; // SLTI
|
||||
32'b???????_?????_?????_011_?????_00100?? : RD = { 1'b1 , sltiu_true } ; // SLTIU
|
||||
32'b???????_?????_?????_100_?????_00100?? : RD = { 1'b1 , RS1 ^ i_immediate } ; // XORI
|
||||
32'b???????_?????_?????_110_?????_00100?? : RD = { 1'b1 , RS1 | i_immediate } ; // ORI
|
||||
32'b???????_?????_?????_111_?????_00100?? : RD = { 1'b1 , RS1 & i_immediate } ; // ANDI
|
||||
32'b???????_?????_?????_001_?????_00100?? : RD = { 1'b1 , slli_result } ; // SLLI
|
||||
32'b?0?????_?????_?????_101_?????_00100?? : RD = { 1'b1 , srli_result } ; // SRLI
|
||||
32'b?1?????_?????_?????_101_?????_00100?? : RD = { 1'b1 , srai_result } ; // SRAI
|
||||
32'b?0?????_?????_?????_000_?????_01100?? : RD = { 1'b1 , RS1 + RS2 } ; // ADD
|
||||
32'b?1?????_?????_?????_000_?????_01100?? : RD = { 1'b1 , RS1 - RS2 } ; // SUB
|
||||
32'b???????_?????_?????_001_?????_01100?? : RD = { 1'b1 , sll_result } ; // SLL
|
||||
32'b???????_?????_?????_010_?????_01100?? : RD = { 1'b1 , slt_true } ; // SLT
|
||||
32'b???????_?????_?????_011_?????_01100?? : RD = { 1'b1 , sltu_true } ; // SLTU
|
||||
32'b???????_?????_?????_100_?????_01100?? : RD = { 1'b1 , RS1 ^ RS2 } ; // XOR
|
||||
32'b?0?????_?????_?????_101_?????_01100?? : RD = { 1'b1 , srl_result } ; // SRL
|
||||
32'b?1?????_?????_?????_101_?????_01100?? : RD = { 1'b1 , sra_result } ; // SRA
|
||||
32'b???????_?????_?????_110_?????_01100?? : RD = { 1'b1 , RS1 | RS2 } ; // OR
|
||||
32'b???????_?????_?????_111_?????_01100?? : RD = { 1'b1 , RS1 & RS2 } ; // AND
|
||||
|
||||
32'b???????_?????_?????_010_?????_00000?? : RD = { 1'b1 , LOAD_DATA } ; // LW
|
||||
default : RD = { 1'b0 , 32'h0000_0000 } ;
|
||||
|
||||
endcase
|
||||
|
||||
|
||||
casex (OPCODE)
|
||||
|
||||
32'b???????_?????_?????_010_?????_00000?? : LOAD_STORE_ADDRESS = RS1 + i_immediate ; // Loads
|
||||
32'b???????_?????_?????_010_?????_01000?? : LOAD_STORE_ADDRESS = RS1 + s_immediate ; // Stores
|
||||
default : ;
|
||||
endcase
|
||||
|
||||
|
||||
casex (OPCODE)
|
||||
|
||||
32'b???????_?????_?????_010_?????_00000?? : LOAD_REQ = 1'b1 ;
|
||||
32'b???????_?????_?????_010_?????_01000?? : STORE_REQ = 1'b1 ;
|
||||
default : begin LOAD_REQ = 1'b0 ; STORE_REQ = 1'b0; end
|
||||
|
||||
endcase
|
||||
|
||||
|
||||
casex (OPCODE)
|
||||
|
||||
32'b???????_?????_?????_???_?????_11011?? : NEWPC = { 1'b1 , pc_adjusted + j_immediate } ; // JAL
|
||||
32'b???????_?????_?????_000_?????_11001?? : NEWPC = { 1'b1 , ( RS1 + i_immediate) & 32'hFFFF_FFFE } ; // JALR
|
||||
|
||||
32'b???????_?????_?????_010_?????_00000?? : NEWPC = { 1'b1 , pc_adjusted } ; // LW
|
||||
32'b???????_?????_?????_010_?????_01000?? : NEWPC = { 1'b1 , pc_adjusted } ; // SW
|
||||
|
||||
//32'hBBBBBBBB : NEWPC = { 1'b1 , pc_adjusted + 4'h6 } ; // Temp jump code !!!!
|
||||
|
||||
32'b???????_?????_?????_000_?????_11000?? : if (beq_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BEQ
|
||||
32'b???????_?????_?????_001_?????_11000?? : if (bne_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BNE
|
||||
32'b???????_?????_?????_100_?????_11000?? : if (blt_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BLT
|
||||
32'b???????_?????_?????_101_?????_11000?? : if (bge_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BGE
|
||||
32'b???????_?????_?????_110_?????_11000?? : if (bltu_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BLTU
|
||||
32'b???????_?????_?????_111_?????_11000?? : if (bgeu_taken == 1'b1) NEWPC = { 1'b1 , pc_adjusted + b_immediate } ; // BGEU
|
||||
|
||||
|
||||
default : NEWPC = { 1'b0 , 32'h0000_0000 } ; // No Branch Taken
|
||||
|
||||
endcase
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule // MCLR5_alu.v
|
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
|
@ -0,0 +1,12 @@
|
|||
# Quad-issue Superscalar RISCV
|
||||
|
||||
|
||||
- Up to four instructions can be simultaneously issued and retired.
|
||||
- ALU cores are combinational.
|
||||
- Core can handle branches which occur in any of the four pipelines.
|
||||
- Can also handle register dependancies in the pipeline.
|
||||
|
||||
** Very incomplete! Once it was able to issue multiple instructions and handle branches and register dependancies I got bored and moved on! :)
|
||||
|
||||
|
||||
For questions email me at www.MicroCoreLabs.com
|
Loading…
Reference in New Issue