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 |