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

Subversion Repositories altor32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /altor32/trunk/rtl/cpu_lite
    from Rev 36 to Rev 37
    Reverse comparison

Rev 36 → Rev 37

/altor32_regfile_sim.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
48,11 → 48,11
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] ra_i /*verilator public*/,
input [4:0] rb_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
output reg [31:0] reg_ra_o /*verilator public*/,
output reg [31:0] reg_rb_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
107,37 → 107,37
begin
if (rst_i)
begin
reg_r1_sp <= 32'h00000000;
reg_r2_fp <= 32'h00000000;
reg_r3 <= 32'h00000000;
reg_r4 <= 32'h00000000;
reg_r5 <= 32'h00000000;
reg_r6 <= 32'h00000000;
reg_r7 <= 32'h00000000;
reg_r8 <= 32'h00000000;
reg_r9_lr <= 32'h00000000;
reg_r10 <= 32'h00000000;
reg_r11 <= 32'h00000000;
reg_r12 <= 32'h00000000;
reg_r13 <= 32'h00000000;
reg_r14 <= 32'h00000000;
reg_r15 <= 32'h00000000;
reg_r16 <= 32'h00000000;
reg_r17 <= 32'h00000000;
reg_r18 <= 32'h00000000;
reg_r19 <= 32'h00000000;
reg_r20 <= 32'h00000000;
reg_r21 <= 32'h00000000;
reg_r22 <= 32'h00000000;
reg_r23 <= 32'h00000000;
reg_r24 <= 32'h00000000;
reg_r25 <= 32'h00000000;
reg_r26 <= 32'h00000000;
reg_r27 <= 32'h00000000;
reg_r28 <= 32'h00000000;
reg_r29 <= 32'h00000000;
reg_r30 <= 32'h00000000;
reg_r31 <= 32'h00000000;
reg_r1_sp <= 32'h00000000;
reg_r2_fp <= 32'h00000000;
reg_r3 <= 32'h00000000;
reg_r4 <= 32'h00000000;
reg_r5 <= 32'h00000000;
reg_r6 <= 32'h00000000;
reg_r7 <= 32'h00000000;
reg_r8 <= 32'h00000000;
reg_r9_lr <= 32'h00000000;
reg_r10 <= 32'h00000000;
reg_r11 <= 32'h00000000;
reg_r12 <= 32'h00000000;
reg_r13 <= 32'h00000000;
reg_r14 <= 32'h00000000;
reg_r15 <= 32'h00000000;
reg_r16 <= 32'h00000000;
reg_r17 <= 32'h00000000;
reg_r18 <= 32'h00000000;
reg_r19 <= 32'h00000000;
reg_r20 <= 32'h00000000;
reg_r21 <= 32'h00000000;
reg_r22 <= 32'h00000000;
reg_r23 <= 32'h00000000;
reg_r24 <= 32'h00000000;
reg_r25 <= 32'h00000000;
reg_r26 <= 32'h00000000;
reg_r27 <= 32'h00000000;
reg_r28 <= 32'h00000000;
reg_r29 <= 32'h00000000;
reg_r30 <= 32'h00000000;
reg_r31 <= 32'h00000000;
end
else
begin
217,142 → 217,142
// Asynchronous Register read (Rs & Rd)
always @ *
begin
case (rs_i)
case (ra_i)
5'b00000 :
reg_rs_o = 32'h00000000;
reg_ra_o = 32'h00000000;
5'b00001 :
reg_rs_o = reg_r1_sp;
reg_ra_o = reg_r1_sp;
5'b00010 :
reg_rs_o = reg_r2_fp;
reg_ra_o = reg_r2_fp;
5'b00011 :
reg_rs_o = reg_r3;
reg_ra_o = reg_r3;
5'b00100 :
reg_rs_o = reg_r4;
reg_ra_o = reg_r4;
5'b00101 :
reg_rs_o = reg_r5;
reg_ra_o = reg_r5;
5'b00110 :
reg_rs_o = reg_r6;
reg_ra_o = reg_r6;
5'b00111 :
reg_rs_o = reg_r7;
reg_ra_o = reg_r7;
5'b01000 :
reg_rs_o = reg_r8;
reg_ra_o = reg_r8;
5'b01001 :
reg_rs_o = reg_r9_lr;
reg_ra_o = reg_r9_lr;
5'b01010 :
reg_rs_o = reg_r10;
reg_ra_o = reg_r10;
5'b01011 :
reg_rs_o = reg_r11;
reg_ra_o = reg_r11;
5'b01100 :
reg_rs_o = reg_r12;
reg_ra_o = reg_r12;
5'b01101 :
reg_rs_o = reg_r13;
reg_ra_o = reg_r13;
5'b01110 :
reg_rs_o = reg_r14;
reg_ra_o = reg_r14;
5'b01111 :
reg_rs_o = reg_r15;
reg_ra_o = reg_r15;
5'b10000 :
reg_rs_o = reg_r16;
reg_ra_o = reg_r16;
5'b10001 :
reg_rs_o = reg_r17;
reg_ra_o = reg_r17;
5'b10010 :
reg_rs_o = reg_r18;
reg_ra_o = reg_r18;
5'b10011 :
reg_rs_o = reg_r19;
reg_ra_o = reg_r19;
5'b10100 :
reg_rs_o = reg_r20;
reg_ra_o = reg_r20;
5'b10101 :
reg_rs_o = reg_r21;
reg_ra_o = reg_r21;
5'b10110 :
reg_rs_o = reg_r22;
reg_ra_o = reg_r22;
5'b10111 :
reg_rs_o = reg_r23;
reg_ra_o = reg_r23;
5'b11000 :
reg_rs_o = reg_r24;
reg_ra_o = reg_r24;
5'b11001 :
reg_rs_o = reg_r25;
reg_ra_o = reg_r25;
5'b11010 :
reg_rs_o = reg_r26;
reg_ra_o = reg_r26;
5'b11011 :
reg_rs_o = reg_r27;
reg_ra_o = reg_r27;
5'b11100 :
reg_rs_o = reg_r28;
reg_ra_o = reg_r28;
5'b11101 :
reg_rs_o = reg_r29;
reg_ra_o = reg_r29;
5'b11110 :
reg_rs_o = reg_r30;
reg_ra_o = reg_r30;
5'b11111 :
reg_rs_o = reg_r31;
reg_ra_o = reg_r31;
default :
reg_rs_o = 32'h00000000;
reg_ra_o = 32'h00000000;
endcase
 
case (rt_i)
case (rb_i)
5'b00000 :
reg_rt_o = 32'h00000000;
reg_rb_o = 32'h00000000;
5'b00001 :
reg_rt_o = reg_r1_sp;
reg_rb_o = reg_r1_sp;
5'b00010 :
reg_rt_o = reg_r2_fp;
reg_rb_o = reg_r2_fp;
5'b00011 :
reg_rt_o = reg_r3;
reg_rb_o = reg_r3;
5'b00100 :
reg_rt_o = reg_r4;
reg_rb_o = reg_r4;
5'b00101 :
reg_rt_o = reg_r5;
reg_rb_o = reg_r5;
5'b00110 :
reg_rt_o = reg_r6;
reg_rb_o = reg_r6;
5'b00111 :
reg_rt_o = reg_r7;
reg_rb_o = reg_r7;
5'b01000 :
reg_rt_o = reg_r8;
reg_rb_o = reg_r8;
5'b01001 :
reg_rt_o = reg_r9_lr;
reg_rb_o = reg_r9_lr;
5'b01010 :
reg_rt_o = reg_r10;
reg_rb_o = reg_r10;
5'b01011 :
reg_rt_o = reg_r11;
reg_rb_o = reg_r11;
5'b01100 :
reg_rt_o = reg_r12;
reg_rb_o = reg_r12;
5'b01101 :
reg_rt_o = reg_r13;
reg_rb_o = reg_r13;
5'b01110 :
reg_rt_o = reg_r14;
reg_rb_o = reg_r14;
5'b01111 :
reg_rt_o = reg_r15;
reg_rb_o = reg_r15;
5'b10000 :
reg_rt_o = reg_r16;
reg_rb_o = reg_r16;
5'b10001 :
reg_rt_o = reg_r17;
reg_rb_o = reg_r17;
5'b10010 :
reg_rt_o = reg_r18;
reg_rb_o = reg_r18;
5'b10011 :
reg_rt_o = reg_r19;
reg_rb_o = reg_r19;
5'b10100 :
reg_rt_o = reg_r20;
reg_rb_o = reg_r20;
5'b10101 :
reg_rt_o = reg_r21;
reg_rb_o = reg_r21;
5'b10110 :
reg_rt_o = reg_r22;
reg_rb_o = reg_r22;
5'b10111 :
reg_rt_o = reg_r23;
reg_rb_o = reg_r23;
5'b11000 :
reg_rt_o = reg_r24;
reg_rb_o = reg_r24;
5'b11001 :
reg_rt_o = reg_r25;
reg_rb_o = reg_r25;
5'b11010 :
reg_rt_o = reg_r26;
reg_rb_o = reg_r26;
5'b11011 :
reg_rt_o = reg_r27;
reg_rb_o = reg_r27;
5'b11100 :
reg_rt_o = reg_r28;
reg_rb_o = reg_r28;
5'b11101 :
reg_rt_o = reg_r29;
reg_rb_o = reg_r29;
5'b11110 :
reg_rt_o = reg_r30;
reg_rb_o = reg_r30;
5'b11111 :
reg_rt_o = reg_r31;
reg_rb_o = reg_r31;
default :
reg_rt_o = 32'h00000000;
reg_rb_o = 32'h00000000;
endcase
end
end
361,78 → 361,78
// Asynchronous Register read (Rs & Rd)
always @ *
begin
case (rs_i)
case (ra_i)
5'b00000 :
reg_rs_o = 32'h00000000;
reg_ra_o = 32'h00000000;
5'b00001 :
reg_rs_o = reg_r1_sp;
reg_ra_o = reg_r1_sp;
5'b00010 :
reg_rs_o = reg_r2_fp;
reg_ra_o = reg_r2_fp;
5'b00011 :
reg_rs_o = reg_r3;
reg_ra_o = reg_r3;
5'b00100 :
reg_rs_o = reg_r4;
reg_ra_o = reg_r4;
5'b00101 :
reg_rs_o = reg_r5;
reg_ra_o = reg_r5;
5'b00110 :
reg_rs_o = reg_r6;
reg_ra_o = reg_r6;
5'b00111 :
reg_rs_o = reg_r7;
reg_ra_o = reg_r7;
5'b01000 :
reg_rs_o = reg_r8;
reg_ra_o = reg_r8;
5'b01001 :
reg_rs_o = reg_r9_lr;
reg_ra_o = reg_r9_lr;
5'b01010 :
reg_rs_o = reg_r10;
reg_ra_o = reg_r10;
5'b01011 :
reg_rs_o = reg_r11;
reg_ra_o = reg_r11;
5'b01100 :
reg_rs_o = reg_r12;
reg_ra_o = reg_r12;
5'b01101 :
reg_rs_o = reg_r13;
reg_ra_o = reg_r13;
5'b01110 :
reg_rs_o = reg_r14;
reg_ra_o = reg_r14;
5'b01111 :
reg_rs_o = reg_r15;
reg_ra_o = reg_r15;
default :
reg_rs_o = 32'h00000000;
reg_ra_o = 32'h00000000;
endcase
 
case (rt_i)
case (rb_i)
5'b00000 :
reg_rt_o = 32'h00000000;
reg_rb_o = 32'h00000000;
5'b00001 :
reg_rt_o = reg_r1_sp;
reg_rb_o = reg_r1_sp;
5'b00010 :
reg_rt_o = reg_r2_fp;
reg_rb_o = reg_r2_fp;
5'b00011 :
reg_rt_o = reg_r3;
reg_rb_o = reg_r3;
5'b00100 :
reg_rt_o = reg_r4;
reg_rb_o = reg_r4;
5'b00101 :
reg_rt_o = reg_r5;
reg_rb_o = reg_r5;
5'b00110 :
reg_rt_o = reg_r6;
reg_rb_o = reg_r6;
5'b00111 :
reg_rt_o = reg_r7;
reg_rb_o = reg_r7;
5'b01000 :
reg_rt_o = reg_r8;
reg_rb_o = reg_r8;
5'b01001 :
reg_rt_o = reg_r9_lr;
reg_rb_o = reg_r9_lr;
5'b01010 :
reg_rt_o = reg_r10;
reg_rb_o = reg_r10;
5'b01011 :
reg_rt_o = reg_r11;
reg_rb_o = reg_r11;
5'b01100 :
reg_rt_o = reg_r12;
reg_rb_o = reg_r12;
5'b01101 :
reg_rt_o = reg_r13;
reg_rb_o = reg_r13;
5'b01110 :
reg_rt_o = reg_r14;
reg_rb_o = reg_r14;
5'b01111 :
reg_rt_o = reg_r15;
reg_rb_o = reg_r15;
default :
reg_rt_o = 32'h00000000;
reg_rb_o = 32'h00000000;
endcase
end
end
/altor32_regfile_xil.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
45,15 → 45,15
//-----------------------------------------------------------------
module altor32_regfile_xil
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] ra_i /*verilator public*/,
input [4:0] rb_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output reg [31:0] reg_ra_o /*verilator public*/,
output reg [31:0] reg_rb_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
//-----------------------------------------------------------------
62,45 → 62,19
parameter SUPPORT_32REGS = "ENABLED";
 
//-----------------------------------------------------------------
// Registers
// Registers / Wires
//-----------------------------------------------------------------
reg [4:0] addr_write;
wire [31:0] data_out1;
wire [31:0] data_out2;
reg write_enable;
wire [31:0] data_out1a;
wire [31:0] data_out1b;
wire [31:0] data_out2a;
wire [31:0] data_out2b;
wire wea;
wire web;
wire [31:0] reg_ra_w;
wire [31:0] reg_rb_w;
wire [31:0] ra_0_15_w;
wire [31:0] ra_16_31_w;
wire [31:0] rb_0_15_w;
wire [31:0] rb_16_31_w;
wire write_enable_w;
wire write_banka_w;
wire write_bankb_w;
 
//-----------------------------------------------------------------
// Async Read Process
//-----------------------------------------------------------------
always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i)
begin
// Read Rs
if (rs_i == 5'b00000)
reg_rs_o <= 32'h00000000;
else
reg_rs_o <= data_out1;
 
// Read Rt
if (rt_i == 5'b00000)
reg_rt_o <= 32'h00000000;
else
reg_rt_o <= data_out2;
 
// Write enabled?
addr_write <= rd_i[4:0];
if ((rd_i != 5'b00000) & (wr_i == 1'b1))
write_enable <= 1'b1;
else
write_enable <= 1'b0;
end
 
//-----------------------------------------------------------------
// Register File (using RAM16X1D )
//-----------------------------------------------------------------
 
110,8 → 84,8
genvar i;
for (i=0;i<32;i=i+1)
begin : reg_loop1
RAM16X1D reg_bit1a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1a[i]), .SPO(/* open */));
RAM16X1D reg_bit1b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rs_i[0]), .DPRA1(rs_i[1]), .DPRA2(rs_i[2]), .DPRA3(rs_i[3]), .DPO(data_out1b[i]), .SPO(/* open */));
RAM16X1D reg_bit1a(.WCLK(clk_i), .WE(write_banka_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(ra_0_15_w[i]), .SPO(/* open */));
RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(write_banka_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rb_0_15_w[i]), .SPO(/* open */));
end
end
endgenerate
123,14 → 97,14
genvar i;
for (i=0;i<32;i=i+1)
begin : reg_loop2
RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(wea), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2a[i]), .SPO(/* open */));
RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(web), .A0(addr_write[0]), .A1(addr_write[1]), .A2(addr_write[2]), .A3(addr_write[3]), .D(reg_rd_i[i]), .DPRA0(rt_i[0]), .DPRA1(rt_i[1]), .DPRA2(rt_i[2]), .DPRA3(rt_i[3]), .DPO(data_out2b[i]), .SPO(/* open */));
RAM16X1D reg_bit1b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(ra_16_31_w[i]), .SPO(/* open */));
RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd_i[0]), .A1(rd_i[1]), .A2(rd_i[2]), .A3(rd_i[3]), .D(reg_rd_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rb_16_31_w[i]), .SPO(/* open */));
end
end
else
begin
assign data_out2a = 32'h00000000;
assign data_out2b = 32'h00000000;
assign ra_16_31_w = 32'h00000000;
assign rb_16_31_w = 32'h00000000;
end
endgenerate
 
137,9 → 111,26
//-----------------------------------------------------------------
// Combinatorial Assignments
//-----------------------------------------------------------------
assign data_out1 = (rs_i[4] == 1'b0) ? data_out1a : data_out1b;
assign data_out2 = (rt_i[4] == 1'b0) ? data_out2a : data_out2b;
assign wea = (write_enable & ~ (addr_write[4]));
assign web = (write_enable & addr_write[4]);
assign reg_ra_w = (ra_i[4] == 1'b0) ? ra_0_15_w : ra_16_31_w;
assign reg_rb_w = (rb_i[4] == 1'b0) ? rb_0_15_w : rb_16_31_w;
 
assign write_enable_w = (rd_i != 5'b00000) & wr_i;
 
assign write_banka_w = (write_enable_w & (~rd_i[4]));
assign write_bankb_w = (write_enable_w & rd_i[4]);
 
// Register read ports
always @ *
begin
if (ra_i == 5'b00000)
reg_ra_o = 32'h00000000;
else
reg_ra_o = reg_ra_w;
 
if (rb_i == 5'b00000)
reg_rb_o = 32'h00000000;
else
reg_rb_o = reg_rb_w;
end
 
endmodule
/altor32_lite.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
93,32 → 93,32
//-----------------------------------------------------------------
 
// PC
reg [31:0] r_pc;
reg [31:0] pc_q;
 
// Exception saved program counter
reg [31:0] r_epc;
reg [31:0] epc_q;
 
// Supervisor register
reg [31:0] r_sr;
reg [31:0] sr_q;
 
// Exception saved supervisor register
reg [31:0] r_esr;
reg [31:0] esr_q;
 
// Destination register number (post execute stage)
reg [4:0] r_e_rd;
reg [4:0] ex_rd_q;
 
// ALU input A
reg [31:0] r_e_alu_a;
reg [31:0] ex_alu_a_q;
 
// ALU input B
reg [31:0] r_e_alu_b;
reg [31:0] ex_alu_b_q;
 
// ALU output
wire [31:0] r_e_result;
wire [31:0] ex_result_w;
 
// ALU Carry
wire alu_carry_out;
wire alu_carry_update;
wire alu_carry_out_w;
wire alu_carry_update_w;
 
// ALU Comparisons
wire compare_equal_w;
129,28 → 129,28
wire alu_flag_update;
 
// ALU operation selection
reg [3:0] r_e_alu_func;
reg [3:0] ex_alu_func_q;
 
// Delayed NMI
reg r_nmi;
reg nmi_q;
 
// SIM PUTC
`ifdef SIM_EXT_PUTC
reg [7:0] r_putc;
reg [7:0] putc_q;
`endif
 
wire [4:0] w_ra;
wire [4:0] w_rb;
wire [4:0] w_rd;
wire [4:0] ra_w;
wire [4:0] rb_w;
wire [4:0] rd_w;
 
wire [31:0] w_reg_ra;
wire [31:0] w_reg_rb;
wire [31:0] reg_ra_w;
wire [31:0] reg_rb_w;
 
reg [31:0] r_opcode;
reg [31:0] opcode_q;
 
reg [31:0] r_load_result;
reg [31:0] load_result_r;
 
reg [1:0] mem_offset;
reg [1:0] mem_offset_q;
 
// Current state
parameter STATE_IDLE = 0;
160,7 → 160,7
parameter STATE_MEM = 4;
parameter STATE_WRITE_BACK = 5;
 
reg [3:0] state;
reg [3:0] state_q;
 
//-----------------------------------------------------------------
// Instantiation
170,19 → 170,19
altor32_alu alu
(
// ALU operation select
.op_i(r_e_alu_func),
.op_i(ex_alu_func_q),
 
// Operands
.a_i(r_e_alu_a),
.b_i(r_e_alu_b),
.c_i(r_sr[`OR32_SR_CY]),
.a_i(ex_alu_a_q),
.b_i(ex_alu_b_q),
.c_i(sr_q[`OR32_SR_CY]),
 
// Result
.p_o(r_e_result),
.p_o(ex_result_w),
 
// Carry
.c_o(alu_carry_out),
.c_update_o(alu_carry_update),
.c_o(alu_carry_out_w),
.c_update_o(alu_carry_update_w),
 
// Comparisons
.equal_o(compare_equal_w),
194,12 → 194,14
);
 
// Writeback result
wire [31:0] w_write_res = (state == STATE_MEM) ? r_load_result : r_e_result;
wire [31:0] w_write_res = (state_q == STATE_MEM) ? load_result_r : ex_result_w;
 
// Writeback enable
wire w_write_en = (state == STATE_MEM & mem_ack_i) | (state == STATE_WRITE_BACK);
wire w_write_en = (state_q == STATE_MEM & mem_ack_i) | (state_q == STATE_WRITE_BACK);
 
// Register file
//-----------------------------------------------------------------
// [Xilinx] Register file
//-----------------------------------------------------------------
generate
if (REGISTER_FILE_TYPE == "XILINX")
begin : REGFILE_XIL
215,14 → 217,17
.wr_i(w_write_en),
 
// Tri-port
.rs_i(w_ra),
.rt_i(w_rb),
.rd_i(r_e_rd),
.reg_rs_o(w_reg_ra),
.reg_rt_o(w_reg_rb),
.ra_i(ra_w),
.rb_i(rb_w),
.rd_i(ex_rd_q),
.reg_ra_o(reg_ra_w),
.reg_rb_o(reg_rb_w),
.reg_rd_i(w_write_res)
);
end
//-----------------------------------------------------------------
// [Altera] Register file
//-----------------------------------------------------------------
else if (REGISTER_FILE_TYPE == "ALTERA")
begin : REGFILE_ALT
altor32_regfile_alt
237,14 → 242,17
.wr_i(w_write_en),
 
// Tri-port
.rs_i(w_ra),
.rt_i(w_rb),
.rd_i(r_e_rd),
.reg_rs_o(w_reg_ra),
.reg_rt_o(w_reg_rb),
.ra_i(ra_w),
.rb_i(rb_w),
.rd_i(ex_rd_q),
.reg_ra_o(reg_ra_w),
.reg_rb_o(reg_rb_w),
.reg_rd_i(w_write_res)
);
end
//-----------------------------------------------------------------
// [Simulation] Register file
//-----------------------------------------------------------------
else
begin : REGFILE_SIM
altor32_regfile_sim
259,11 → 267,11
.wr_i(w_write_en),
 
// Tri-port
.rs_i(w_ra),
.rt_i(w_rb),
.rd_i(r_e_rd),
.reg_rs_o(w_reg_ra),
.reg_rt_o(w_reg_rb),
.ra_i(ra_w),
.rb_i(rb_w),
.rd_i(ex_rd_q),
.reg_ra_o(reg_ra_w),
.reg_rb_o(reg_rb_w),
.reg_rd_i(w_write_res)
);
end
290,36 → 298,36
always @ *
begin
// Instruction
inst_r = {2'b00,r_opcode[31:26]};
inst_r = {2'b00,opcode_q[31:26]};
 
// Sub instructions
alu_op_r = {r_opcode[9:6],r_opcode[3:0]};
sfxx_op_r = {5'b00,r_opcode[31:21]} & `INST_OR32_SFMASK;
shift_op_r = r_opcode[7:6];
alu_op_r = {opcode_q[9:6],opcode_q[3:0]};
sfxx_op_r = {5'b00,opcode_q[31:21]} & `INST_OR32_SFMASK;
shift_op_r = opcode_q[7:6];
 
// Branch target
target_int26_r = sign_extend_imm26(r_opcode[25:0]);
target_int26_r = sign_extend_imm26(opcode_q[25:0]);
 
// Store immediate
store_int32_r = sign_extend_imm16({r_opcode[25:21],r_opcode[10:0]});
store_int32_r = sign_extend_imm16({opcode_q[25:21],opcode_q[10:0]});
 
// Signed & unsigned imm -> 32-bits
uint16_r = r_opcode[15:0];
int32_r = sign_extend_imm16(r_opcode[15:0]);
uint32_r = extend_imm16(r_opcode[15:0]);
uint16_r = opcode_q[15:0];
int32_r = sign_extend_imm16(opcode_q[15:0]);
uint32_r = extend_imm16(opcode_q[15:0]);
 
// Register values [ra/rb]
reg_ra_r = w_reg_ra;
reg_rb_r = w_reg_rb;
reg_ra_r = reg_ra_w;
reg_rb_r = reg_rb_w;
 
// Shift ammount (from register[rb])
shift_rb_r = {26'b00,w_reg_rb[5:0]};
shift_rb_r = {26'b00,reg_rb_w[5:0]};
 
// Shift ammount (from immediate)
shift_imm_r = {26'b00,r_opcode[5:0]};
shift_imm_r = {26'b00,opcode_q[5:0]};
 
// MTSPR/MFSPR operand
mxspr_uint16_r = (w_reg_ra[15:0] | {5'b00000,r_opcode[10:0]});
mxspr_uint16_r = (reg_ra_w[15:0] | {5'b00000,opcode_q[10:0]});
end
 
//-----------------------------------------------------------------
383,8 → 391,8
wire inst_sfltu_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFLTU); // l.sfltu
wire inst_sfne_w = (inst_sfxx_w || inst_sfxxi_w) & (sfxx_op_r == `INST_OR32_SFNE); // l.sfne
 
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_SYS); // l.sys
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (r_opcode[31:24] == `INST_OR32_TRAP); // l.trap
wire inst_sys_w = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_SYS); // l.sys
wire inst_trap_w = (inst_r == `INST_OR32_MISC) & (opcode_q[31:24] == `INST_OR32_TRAP); // l.trap
 
//-----------------------------------------------------------------
// Load/Store operation?
408,9 → 416,9
reg [3:0] next_state_r;
always @ *
begin
next_state_r = state;
next_state_r = state_q;
 
case (state)
case (state_q)
//-----------------------------------------
// IDLE -
//-----------------------------------------
471,9 → 479,9
always @ (posedge rst_i or posedge clk_i )
begin
if (rst_i == 1'b1)
state <= STATE_IDLE;
state_q <= STATE_IDLE;
else
state <= next_state_r;
state_q <= next_state_r;
end
 
//-----------------------------------------------------------------
490,8 → 498,8
mem_stb_o <= 1'b0;
mem_cyc_o <= 1'b0;
 
r_opcode <= 32'h00000000;
mem_offset <= 2'b0;
opcode_q <= 32'h00000000;
mem_offset_q <= 2'b0;
end
else
begin
499,7 → 507,7
if (~mem_stall_i)
mem_stb_o <= 1'b0;
case (state)
case (state_q)
 
//-----------------------------------------
// FETCH - Issue instruction fetch
507,7 → 515,7
STATE_FETCH :
begin
// Start fetch from memory
mem_addr_o <= r_pc;
mem_addr_o <= pc_q;
mem_stb_o <= 1'b1;
mem_we_o <= 1'b0;
mem_cyc_o <= 1'b1;
520,7 → 528,7
// Data ready from memory?
if (mem_ack_i)
begin
r_opcode <= mem_dat_i;
opcode_q <= mem_dat_i;
mem_cyc_o <= 1'b0;
end
end
530,9 → 538,9
STATE_EXEC :
begin
`ifdef CONF_CORE_TRACE
$display("%08x: Execute 0x%08x", r_pc, r_opcode);
$display(" rA[%d] = 0x%08x", w_ra, reg_ra_r);
$display(" rB[%d] = 0x%08x", w_rb, reg_rb_r);
$display("%08x: Execute 0x%08x", pc_q, opcode_q);
$display(" rA[%d] = 0x%08x", ra_w, reg_ra_r);
$display(" rB[%d] = 0x%08x", rb_w, reg_rb_r);
`endif
 
case (1'b1)
540,7 → 548,7
load_inst_r:
begin
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
mem_offset <= mem_addr_r[1:0];
mem_offset_q <= mem_addr_r[1:0];
mem_dat_o <= 32'h00000000;
mem_sel_o <= 4'b1111;
mem_we_o <= 1'b0;
548,7 → 556,7
mem_cyc_o <= 1'b1;
 
`ifdef CONF_CORE_DEBUG
$display(" Load from 0x%08x to R%d", mem_addr_r, w_rd);
$display(" Load from 0x%08x to R%d", mem_addr_r, rd_w);
`endif
end
 
555,7 → 563,7
inst_sb_w: // l.sb
begin
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
mem_offset <= mem_addr_r[1:0];
mem_offset_q <= mem_addr_r[1:0];
case (mem_addr_r[1:0])
2'b00 :
begin
597,7 → 605,7
inst_sh_w: // l.sh
begin
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
mem_offset <= mem_addr_r[1:0];
mem_offset_q <= mem_addr_r[1:0];
case (mem_addr_r[1:0])
2'b00 :
begin
623,7 → 631,7
inst_sw_w: // l.sw
begin
mem_addr_o <= {mem_addr_r[31:2], 2'b0};
mem_offset <= mem_addr_r[1:0];
mem_offset_q <= mem_addr_r[1:0];
mem_dat_o <= reg_rb_r;
mem_sel_o <= 4'b1111;
mem_we_o <= 1'b1;
631,7 → 639,7
mem_cyc_o <= 1'b1;
 
`ifdef CONF_CORE_DEBUG
$display(" Store R%d to 0x%08x = 0x%08x", w_rb, {mem_addr_r[31:2],2'b00}, reg_rb_r);
$display(" Store R%d to 0x%08x = 0x%08x", rb_w, {mem_addr_r[31:2],2'b00}, reg_rb_r);
`endif
end
default:
659,15 → 667,15
 
// If simulation, RA = 03 if NOP instruction
`ifdef SIMULATION
wire [7:0] v_fetch_inst = {2'b00, r_opcode[31:26]};
wire [7:0] v_fetch_inst = {2'b00, opcode_q[31:26]};
wire v_is_nop = (v_fetch_inst == `INST_OR32_NOP);
assign w_ra = v_is_nop ? 5'd3 : r_opcode[20:16];
assign ra_w = v_is_nop ? 5'd3 : opcode_q[20:16];
`else
assign w_ra = r_opcode[20:16];
assign ra_w = opcode_q[20:16];
`endif
 
assign w_rb = r_opcode[15:11];
assign w_rd = r_opcode[25:21];
assign rb_w = opcode_q[15:11];
assign rd_w = opcode_q[25:21];
 
//-----------------------------------------------------------------
// Next PC
677,7 → 685,7
always @ *
begin
// Next expected PC (current PC + 4)
next_pc_r = (r_pc + 4);
next_pc_r = (pc_q + 4);
end
 
//-----------------------------------------------------------------
687,15 → 695,15
reg compare_result_r;
always @ *
begin
next_sr_r = r_sr;
next_sr_r = sr_q;
 
// Update SR.F
if (alu_flag_update)
next_sr_r[`OR32_SR_F] = compare_result_r;
next_sr_r[`OR32_SR_F] = compare_result_r;
 
// Latch carry if updated
if (alu_carry_update)
next_sr_r[`OR32_SR_CY] = alu_carry_out;
if (alu_carry_update_w)
next_sr_r[`OR32_SR_CY] = alu_carry_out_w;
 
case (1'b1)
inst_mtspr_w:
714,13 → 722,13
end
inst_rfe_w:
begin
next_sr_r[`OR32_SR_F] = r_esr[`OR32_SR_F];
next_sr_r[`OR32_SR_CY] = r_esr[`OR32_SR_CY];
next_sr_r[`OR32_SR_IEE] = r_esr[`OR32_SR_IEE];
next_sr_r[`OR32_SR_F] = esr_q[`OR32_SR_F];
next_sr_r[`OR32_SR_CY] = esr_q[`OR32_SR_CY];
next_sr_r[`OR32_SR_IEE] = esr_q[`OR32_SR_IEE];
end
inst_sfxx_w,
inst_sfxxi_w:
next_sr_r[`OR32_SR_F] = compare_result_r;
next_sr_r[`OR32_SR_F] = compare_result_r;
default:
;
endcase
734,8 → 742,8
 
always @ *
begin
next_epc_r = r_epc;
next_esr_r = r_esr;
next_epc_r = epc_q;
next_esr_r = esr_q;
case (1'b1)
inst_mtspr_w: // l.mtspr
896,7 → 904,7
// EPCR - EPC Exception saved PC
`SPR_REG_EPCR:
begin
alu_input_a_r = r_epc;
alu_input_a_r = epc_q;
write_rd_r = 1'b1;
end
 
904,9 → 912,9
`SPR_REG_ESR:
begin
alu_input_a_r = 32'b0;
alu_input_a_r[`OR32_SR_F] = r_esr[`OR32_SR_F];
alu_input_a_r[`OR32_SR_CY] = r_esr[`OR32_SR_CY];
alu_input_a_r[`OR32_SR_IEE] = r_esr[`OR32_SR_IEE];
alu_input_a_r[`OR32_SR_F] = esr_q[`OR32_SR_F];
alu_input_a_r[`OR32_SR_CY] = esr_q[`OR32_SR_CY];
alu_input_a_r[`OR32_SR_IEE] = esr_q[`OR32_SR_IEE];
write_rd_r = 1'b1;
end
default:
1043,14 → 1051,14
branch_except_r = 1'b0;
 
// Default branch target is relative to current PC
branch_target_r = (r_pc + {target_int26_r[29:0],2'b00});
branch_target_r = (pc_q + {target_int26_r[29:0],2'b00});
 
case (1'b1)
inst_bf_w: // l.bf
branch_r = r_sr[`OR32_SR_F];
branch_r = sr_q[`OR32_SR_F];
 
inst_bnf_w: // l.bnf
branch_r = ~r_sr[`OR32_SR_F];
branch_r = ~sr_q[`OR32_SR_F];
 
inst_j_w: // l.j
branch_r = 1'b1;
1079,7 → 1087,7
inst_rfe_w: // l.rfe
begin
branch_r = 1'b1;
branch_target_r = r_epc;
branch_target_r = epc_q;
end
 
inst_sys_w: // l.sys
1170,26 → 1178,26
begin
if (rst_i == 1'b1)
begin
r_e_alu_func <= `ALU_NONE;
r_e_alu_a <= 32'h00000000;
r_e_alu_b <= 32'h00000000;
r_e_rd <= 5'b00000;
ex_alu_func_q <= `ALU_NONE;
ex_alu_a_q <= 32'h00000000;
ex_alu_b_q <= 32'h00000000;
ex_rd_q <= 5'b00000;
end
else
begin
// Update ALU input flops
r_e_alu_func <= alu_func_r;
r_e_alu_a <= alu_input_a_r;
r_e_alu_b <= alu_input_b_r;
ex_alu_func_q <= alu_func_r;
ex_alu_a_q <= alu_input_a_r;
ex_alu_b_q <= alu_input_b_r;
 
// Branch and link (Rd = LR/R9)
if (branch_link_r)
r_e_rd <= 5'd9;
ex_rd_q <= 5'd9;
// Instruction with register writeback
else if (write_rd_r)
r_e_rd <= w_rd;
ex_rd_q <= rd_w;
else
r_e_rd <= 5'b0;
ex_rd_q <= 5'b0;
end
end
 
1200,59 → 1208,59
begin
if (rst_i == 1'b1)
begin
r_pc <= BOOT_VECTOR + `VECTOR_RESET;
pc_q <= BOOT_VECTOR + `VECTOR_RESET;
 
// Status registers
r_epc <= 32'h00000000;
r_sr <= 32'h00000000;
r_esr <= 32'h00000000;
epc_q <= 32'h00000000;
sr_q <= 32'h00000000;
esr_q <= 32'h00000000;
 
fault_o <= 1'b0;
 
r_nmi <= 1'b0;
nmi_q <= 1'b0;
end
else
begin
// Record NMI in-case it can't be processed this cycle
if (nmi_i)
r_nmi <= 1'b1;
nmi_q <= 1'b1;
 
// Core disabled?
if (~enable_i)
begin
// Reset
r_pc <= BOOT_VECTOR + `VECTOR_RESET;
pc_q <= BOOT_VECTOR + `VECTOR_RESET;
 
// Status registers
r_epc <= 32'h00000000;
r_sr <= 32'h00000000;
r_esr <= 32'h00000000;
epc_q <= 32'h00000000;
sr_q <= 32'h00000000;
esr_q <= 32'h00000000;
 
fault_o <= 1'b0;
 
r_nmi <= 1'b0;
nmi_q <= 1'b0;
end
// Write-back?
else if (w_write_en)
begin
// Update SR
r_sr <= next_sr_r;
sr_q <= next_sr_r;
 
// Exception: Instruction opcode not valid / supported, invalid PC
if (invalid_inst_r || (r_pc[1:0] != 2'b00))
if (invalid_inst_r || (pc_q[1:0] != 2'b00))
begin
// Save PC of next instruction
r_epc <= next_pc_r;
r_esr <= next_sr_r;
epc_q <= next_pc_r;
esr_q <= next_sr_r;
 
// Disable further interrupts
r_sr <= 32'b0;
sr_q <= 32'b0;
 
// Set PC to exception vector
if (invalid_inst_r)
r_pc <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
pc_q <= ISR_VECTOR + `VECTOR_ILLEGAL_INST;
else
r_pc <= ISR_VECTOR + `VECTOR_BUS_ERROR;
pc_q <= ISR_VECTOR + `VECTOR_BUS_ERROR;
 
fault_o <= 1'b1;
end
1260,14 → 1268,14
else if (branch_except_r)
begin
// Save PC of next instruction
r_epc <= next_pc_r;
r_esr <= next_sr_r;
epc_q <= next_pc_r;
esr_q <= next_sr_r;
 
// Disable further interrupts
r_sr <= 32'b0;
sr_q <= 32'b0;
 
// Set PC to exception vector
r_pc <= branch_target_r;
pc_q <= branch_target_r;
`ifdef CONF_CORE_DEBUG
$display(" Exception 0x%08x", branch_target_r);
1274,24 → 1282,24
`endif
end
// Non-maskable interrupt
else if (nmi_i | r_nmi)
else if (nmi_i | nmi_q)
begin
r_nmi <= 1'b0;
nmi_q <= 1'b0;
 
// Save PC of next instruction
if (branch_r)
r_epc <= branch_target_r;
epc_q <= branch_target_r;
// Next expected PC (current PC + 4)
else
r_epc <= next_pc_r;
epc_q <= next_pc_r;
 
r_esr <= next_sr_r;
esr_q <= next_sr_r;
 
// Disable further interrupts
r_sr <= 32'b0;
sr_q <= 32'b0;
 
// Set PC to exception vector
r_pc <= ISR_VECTOR + `VECTOR_NMI;
pc_q <= ISR_VECTOR + `VECTOR_NMI;
`ifdef CONF_CORE_DEBUG
$display(" NMI 0x%08x", ISR_VECTOR + `VECTOR_NMI);
1302,18 → 1310,18
begin
// Save PC of next instruction & SR
if (branch_r)
r_epc <= branch_target_r;
epc_q <= branch_target_r;
// Next expected PC (current PC + 4)
else
r_epc <= next_pc_r;
epc_q <= next_pc_r;
 
r_esr <= next_sr_r;
esr_q <= next_sr_r;
 
// Disable further interrupts
r_sr <= 32'b0;
sr_q <= 32'b0;
 
// Set PC to external interrupt vector
r_pc <= ISR_VECTOR + `VECTOR_EXTINT;
pc_q <= ISR_VECTOR + `VECTOR_EXTINT;
`ifdef CONF_CORE_DEBUG
$display(" External Interrupt 0x%08x", ISR_VECTOR + `VECTOR_EXTINT);
1323,7 → 1331,7
else if (branch_r)
begin
// Perform branch
r_pc <= branch_target_r;
pc_q <= branch_target_r;
`ifdef CONF_CORE_DEBUG
$display(" Branch to 0x%08x", branch_target_r);
1334,9 → 1342,9
begin
// Update EPC / ESR which may have been updated
// by an MTSPR write
r_pc <= next_pc_r;
r_epc <= next_epc_r;
r_esr <= next_esr_r;
pc_q <= next_pc_r;
epc_q <= next_epc_r;
esr_q <= next_esr_r;
end
end
end
1347,7 → 1355,7
//-------------------------------------------------------------------
always @ *
begin
r_load_result = 32'h00000000;
load_result_r = 32'h00000000;
 
case (1'b1)
 
1354,36 → 1362,36
inst_lbs_w, // l.lbs
inst_lbz_w: // l.lbz
begin
case (mem_offset)
2'b00 : r_load_result[7:0] = mem_dat_i[31:24];
2'b01 : r_load_result[7:0] = mem_dat_i[23:16];
2'b10 : r_load_result[7:0] = mem_dat_i[15:8];
2'b11 : r_load_result[7:0] = mem_dat_i[7:0];
case (mem_offset_q)
2'b00 : load_result_r[7:0] = mem_dat_i[31:24];
2'b01 : load_result_r[7:0] = mem_dat_i[23:16];
2'b10 : load_result_r[7:0] = mem_dat_i[15:8];
2'b11 : load_result_r[7:0] = mem_dat_i[7:0];
default : ;
endcase
// Sign extend LB
if (inst_lbs_w && r_load_result[7])
r_load_result[31:8] = 24'hFFFFFF;
if (inst_lbs_w && load_result_r[7])
load_result_r[31:8] = 24'hFFFFFF;
end
inst_lhs_w, // l.lhs
inst_lhz_w: // l.lhz
begin
case (mem_offset)
2'b00 : r_load_result[15:0] = mem_dat_i[31:16];
2'b10 : r_load_result[15:0] = mem_dat_i[15:0];
case (mem_offset_q)
2'b00 : load_result_r[15:0] = mem_dat_i[31:16];
2'b10 : load_result_r[15:0] = mem_dat_i[15:0];
default : ;
endcase
 
// Sign extend LH
if (inst_lhs_w && r_load_result[15])
r_load_result[31:16] = 16'hFFFF;
if (inst_lhs_w && load_result_r[15])
load_result_r[31:16] = 16'hFFFF;
end
 
// l.lwz l.lws
default :
r_load_result = mem_dat_i;
load_result_r = mem_dat_i;
endcase
end
 
1418,15 → 1426,15
if (rst_i == 1'b1)
begin
`ifdef SIM_EXT_PUTC
r_putc <= 8'b0;
putc_q <= 8'b0;
`endif
end
else
begin
`ifdef SIM_EXT_PUTC
r_putc <= 8'b0;
putc_q <= 8'b0;
`endif
if (inst_nop_w && state == STATE_EXEC)
if (inst_nop_w && state_q == STATE_EXEC)
begin
case (uint16_r)
// NOP_PUTC
1433,7 → 1441,7
16'h0004:
begin
`ifdef SIM_EXT_PUTC
r_putc <= reg_ra_r[7:0];
putc_q <= reg_ra_r[7:0];
`else
$write("%c", reg_ra_r[7:0]);
`endif
1454,16 → 1462,16
`ifdef verilator
function [31:0] get_opcode_ex;
// verilator public
get_opcode_ex = (state == STATE_EXEC) ? r_opcode : `OPCODE_INST_BUBBLE;
get_opcode_ex = (state_q == STATE_EXEC) ? opcode_q : `OPCODE_INST_BUBBLE;
endfunction
function [31:0] get_pc_ex;
// verilator public
get_pc_ex = r_pc;
get_pc_ex = pc_q;
endfunction
function [7:0] get_putc;
// verilator public
`ifdef SIM_EXT_PUTC
get_putc = r_putc;
get_putc = putc_q;
`else
get_putc = 8'b0;
`endif
1470,23 → 1478,23
endfunction
function [0:0] get_reg_valid;
// verilator public
get_reg_valid = (state == STATE_EXEC) ? 1'b1 : 1'b0;
get_reg_valid = (state_q == STATE_EXEC) ? 1'b1 : 1'b0;
endfunction
function [4:0] get_reg_ra;
// verilator public
get_reg_ra = w_ra;
get_reg_ra = ra_w;
endfunction
function [31:0] get_reg_ra_value;
// verilator public
get_reg_ra_value = w_reg_ra;
get_reg_ra_value = reg_ra_w;
endfunction
function [4:0] get_reg_rb;
// verilator public
get_reg_rb = w_rb;
get_reg_rb = rb_w;
endfunction
function [31:0] get_reg_rb_value;
// verilator public
get_reg_rb_value = w_reg_rb;
get_reg_rb_value = reg_rb_w;
endfunction
`endif
 
/altor32_regfile_alt.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
45,15 → 45,15
//-----------------------------------------------------------------
module altor32_regfile_alt
(
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] rs_i /*verilator public*/,
input [4:0] rt_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output reg [31:0] reg_rs_o /*verilator public*/,
output reg [31:0] reg_rt_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
input clk_i /*verilator public*/,
input rst_i /*verilator public*/,
input wr_i /*verilator public*/,
input [4:0] ra_i /*verilator public*/,
input [4:0] rb_i /*verilator public*/,
input [4:0] rd_i /*verilator public*/,
output reg [31:0] reg_ra_o /*verilator public*/,
output reg [31:0] reg_rb_o /*verilator public*/,
input [31:0] reg_rd_i /*verilator public*/
);
 
//-----------------------------------------------------------------
64,42 → 64,18
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
wire clk_delayed;
wire [31:0] data_out1;
wire [31:0] data_out2;
reg write_enable;
wire clk_delayed_w;
wire [31:0] reg_ra_w;
wire [31:0] reg_rb_w;
wire write_enable_w;
 
reg [4:0] addr_reg;
reg [31:0] data_reg;
reg [4:0] addr_q;
reg [31:0] data_q;
 
wire [31:0] q1;
wire [31:0] q2;
wire [31:0] ra_w;
wire [31:0] rb_w;
 
//-----------------------------------------------------------------
// Async Read Process
//-----------------------------------------------------------------
always @ (clk_i or rs_i or rt_i or rd_i or reg_rd_i or data_out1 or data_out2 or rst_i or wr_i)
begin
// Read Rs
if (rs_i == 5'b00000)
reg_rs_o <= 32'h00000000;
else
reg_rs_o <= data_out1;
 
// Read Rt
if (rt_i == 5'b00000)
reg_rt_o <= 32'h00000000;
else
reg_rt_o <= data_out2;
 
// Write enabled?
if ((rd_i != 5'b00000) & (wr_i == 1'b1))
write_enable <= 1'b1;
else
write_enable <= 1'b0;
end
 
//-----------------------------------------------------------------
// Sync addr & data
//-----------------------------------------------------------------
always @ (posedge clk_i or posedge rst_i)
106,14 → 82,14
begin
if (rst_i)
begin
addr_reg <= 5'b00000;
data_reg <= 32'h00000000;
addr_q <= 5'b00000;
data_q <= 32'h00000000;
 
end
else
begin
addr_reg <= rd_i;
data_reg <= reg_rd_i;
addr_q <= rd_i;
data_q <= reg_rd_i;
end
end
 
139,16 → 115,16
)
lpm1
(
.rdclock(clk_delayed),
.rdclock(clk_delayed_w),
.rdclken(1'b1),
.rdaddress(rs_i),
.rdaddress(ra_i),
.rden(1'b1),
.data(reg_rd_i),
.wraddress(rd_i),
.wren(write_enable),
.wren(write_enable_w),
.wrclock(clk_i),
.wrclken(1'b1),
.q(q1)
.q(ra_w)
);
 
 
166,16 → 142,16
)
lpm2
(
.rdclock(clk_delayed),
.rdclock(clk_delayed_w),
.rdclken(1'b1),
.rdaddress(rt_i),
.rdaddress(rb_i),
.rden(1'b1),
.data(reg_rd_i),
.wraddress(rd_i),
.wren(write_enable),
.wren(write_enable_w),
.wrclock(clk_i),
.wrclken(1'b1),
.q(q2)
.q(rb_w)
);
 
//-----------------------------------------------------------------
183,10 → 159,26
//-----------------------------------------------------------------
 
// Delayed clock
assign clk_delayed = !clk_i;
assign clk_delayed_w = !clk_i;
 
// Register read ports
always @ *
begin
if (ra_i == 5'b00000)
reg_ra_o = 32'h00000000;
else
reg_ra_o = reg_ra_w;
 
if (rb_i == 5'b00000)
reg_rb_o = 32'h00000000;
else
reg_rb_o = reg_rb_w;
end
 
assign write_enable_w = (rd_i != 5'b00000) & wr_i;
 
// Reads are bypassed during write-back
assign data_out1 = (rs_i != addr_reg) ? q1 : data_reg;
assign data_out2 = (rt_i != addr_reg) ? q2 : data_reg;
assign reg_ra_w = (ra_i != addr_q) ? ra_w : data_q;
assign reg_rb_w = (rb_i != addr_q) ? rb_w : data_q;
 
endmodule
/altor32_funcs.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
/altor32.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
/altor32_alu.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not
36,12 → 36,6
//-----------------------------------------------------------------
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Module - ALU
//-----------------------------------------------------------------
module altor32_alu
71,20 → 65,26
);
 
//-----------------------------------------------------------------
// Includes
//-----------------------------------------------------------------
`include "altor32_defs.v"
`include "altor32_funcs.v"
 
//-----------------------------------------------------------------
// Registers
//-----------------------------------------------------------------
reg [31:0] result;
reg [31:0] result_r;
 
reg [31:16] shift_right_fill;
reg [31:0] shift_right_1;
reg [31:0] shift_right_2;
reg [31:0] shift_right_4;
reg [31:0] shift_right_8;
reg [31:16] shift_right_fill_r;
reg [31:0] shift_right_1_r;
reg [31:0] shift_right_2_r;
reg [31:0] shift_right_4_r;
reg [31:0] shift_right_8_r;
 
reg [31:0] shift_left_1;
reg [31:0] shift_left_2;
reg [31:0] shift_left_4;
reg [31:0] shift_left_8;
reg [31:0] shift_left_1_r;
reg [31:0] shift_left_2_r;
reg [31:0] shift_left_4_r;
reg [31:0] shift_left_8_r;
 
//-----------------------------------------------------------------
// ALU
98,29 → 98,29
`ALU_SHIFTL :
begin
if (b_i[0] == 1'b1)
shift_left_1 = {a_i[30:0],1'b0};
shift_left_1_r = {a_i[30:0],1'b0};
else
shift_left_1 = a_i;
shift_left_1_r = a_i;
 
if (b_i[1] == 1'b1)
shift_left_2 = {shift_left_1[29:0],2'b00};
shift_left_2_r = {shift_left_1_r[29:0],2'b00};
else
shift_left_2 = shift_left_1;
shift_left_2_r = shift_left_1_r;
 
if (b_i[2] == 1'b1)
shift_left_4 = {shift_left_2[27:0],4'b0000};
shift_left_4_r = {shift_left_2_r[27:0],4'b0000};
else
shift_left_4 = shift_left_2;
shift_left_4_r = shift_left_2_r;
 
if (b_i[3] == 1'b1)
shift_left_8 = {shift_left_4[23:0],8'b00000000};
shift_left_8_r = {shift_left_4_r[23:0],8'b00000000};
else
shift_left_8 = shift_left_4;
shift_left_8_r = shift_left_4_r;
 
if (b_i[4] == 1'b1)
result = {shift_left_8[15:0],16'b0000000000000000};
result_r = {shift_left_8_r[15:0],16'b0000000000000000};
else
result = shift_left_8;
result_r = shift_left_8_r;
 
c_o = 1'b0;
c_update_o = 1'b0;
132,34 → 132,34
begin
// Arithmetic shift? Fill with 1's if MSB set
if (a_i[31] == 1'b1 && op_i == `ALU_SHIRTR_ARITH)
shift_right_fill = 16'b1111111111111111;
shift_right_fill_r = 16'b1111111111111111;
else
shift_right_fill = 16'b0000000000000000;
shift_right_fill_r = 16'b0000000000000000;
 
if (b_i[0] == 1'b1)
shift_right_1 = {shift_right_fill[31], a_i[31:1]};
shift_right_1_r = {shift_right_fill_r[31], a_i[31:1]};
else
shift_right_1 = a_i;
shift_right_1_r = a_i;
 
if (b_i[1] == 1'b1)
shift_right_2 = {shift_right_fill[31:30], shift_right_1[31:2]};
shift_right_2_r = {shift_right_fill_r[31:30], shift_right_1_r[31:2]};
else
shift_right_2 = shift_right_1;
shift_right_2_r = shift_right_1_r;
 
if (b_i[2] == 1'b1)
shift_right_4 = {shift_right_fill[31:28], shift_right_2[31:4]};
shift_right_4_r = {shift_right_fill_r[31:28], shift_right_2_r[31:4]};
else
shift_right_4 = shift_right_2;
shift_right_4_r = shift_right_2_r;
 
if (b_i[3] == 1'b1)
shift_right_8 = {shift_right_fill[31:24], shift_right_4[31:8]};
shift_right_8_r = {shift_right_fill_r[31:24], shift_right_4_r[31:8]};
else
shift_right_8 = shift_right_4;
shift_right_8_r = shift_right_4_r;
 
if (b_i[4] == 1'b1)
result = {shift_right_fill[31:16], shift_right_8[31:16]};
result_r = {shift_right_fill_r[31:16], shift_right_8_r[31:16]};
else
result = shift_right_8;
result_r = shift_right_8_r;
 
c_o = 1'b0;
c_update_o = 1'b0;
169,17 → 169,17
//----------------------------------------------
`ALU_ADD :
begin
{c_o, result} = (a_i + b_i);
c_update_o = 1'b1;
{c_o, result_r} = (a_i + b_i);
c_update_o = 1'b1;
end
`ALU_ADDC :
begin
{c_o, result} = (a_i + b_i) + {31'h00000000, c_i};
c_update_o = 1'b1;
{c_o, result_r} = (a_i + b_i) + {31'h00000000, c_i};
c_update_o = 1'b1;
end
`ALU_SUB :
begin
result = (a_i - b_i);
result_r = (a_i - b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
188,25 → 188,25
//----------------------------------------------
`ALU_AND :
begin
result = (a_i & b_i);
result_r = (a_i & b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
`ALU_OR :
begin
result = (a_i | b_i);
result_r = (a_i | b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
`ALU_XOR :
begin
result = (a_i ^ b_i);
result_r = (a_i ^ b_i);
c_o = 1'b0;
c_update_o = 1'b0;
end
default :
begin
result = a_i;
result_r = a_i;
c_o = 1'b0;
c_update_o = 1'b0;
end
213,7 → 213,7
endcase
end
 
assign p_o = result;
assign p_o = result_r;
 
//-----------------------------------------------------------------
// Comparisons
/altor32_defs.v
10,7 → 10,7
// License: LGPL
//-----------------------------------------------------------------
//
// Copyright (C) 2011 - 2013 Ultra-Embedded.com
// Copyright (C) 2011 - 2014 Ultra-Embedded.com
//
// This source file may be used and distributed without
// restriction provided that this copyright statement is not

powered by: WebSVN 2.1.0

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