URL
https://opencores.org/ocsvn/mpx/mpx/trunk
Subversion Repositories mpx
Compare Revisions
- This comparison shows the changes necessary to convert path
/mpx/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
/mpx/mpx_regfile_xil.v
0,0 → 1,142
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module mpx_regfile_xil |
( |
clk_i, |
rst_i, |
en_i, |
wr_i, |
rs_i, |
rt_i, |
rd_i, |
reg_rs_o, |
reg_rt_o, |
reg_rd_i |
); |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input en_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 [31:0] reg_rs_o /*verilator public*/; |
output [31:0] reg_rt_o /*verilator public*/; |
input [31:0] reg_rd_i /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
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; |
|
reg [31:0] reg_rs_o; |
reg [31:0] reg_rt_o; |
|
//----------------------------------------------------------------- |
// 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 ) |
//----------------------------------------------------------------- |
generate |
begin |
genvar i; |
for (i=0;i<32;i=i+1) |
begin : reg_loop |
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_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 */)); |
end |
end |
endgenerate |
|
//----------------------------------------------------------------- |
// 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]); |
|
endmodule |
/mpx/mpx_funcs.v
0,0 → 1,301
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// shift_left: Shift left by specified amount |
// Inputs: x = input, y = shift amount |
// Return: x << y |
//----------------------------------------------------------------- |
function [31:0] shift_left; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] shift1l; |
reg [31:0] shift2l; |
reg [31:0] shift4l; |
reg [31:0] shift8l; |
reg [31:0] shift16l; |
begin |
if (y[0] == 1'b1) |
shift1l = {x[30:0],1'b0}; |
else |
shift1l = x; |
|
if (y[1] == 1'b1) |
shift2l = {shift1l[29:0],2'b00}; |
else |
shift2l = shift1l; |
|
if (y[2] == 1'b1) |
shift4l = {shift2l[27:0],4'b0000}; |
else |
shift4l = shift2l; |
|
if (y[3] == 1'b1) |
shift8l = {shift4l[23:0],8'b00000000}; |
else |
shift8l = shift4l; |
|
if (y[4] == 1'b1) |
shift16l = {shift8l[15:0],16'b0000000000000000}; |
else |
shift16l = shift8l; |
|
shift_left = shift16l; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// shift_right: Shift right by specified amount |
// Inputs: x = input, y = shift amount |
// Return: x >> y |
//----------------------------------------------------------------- |
function [31:0] shift_right; |
input [31:0] x; |
input [31:0] y; |
reg [31:16] fill; |
reg [31:0] shift1r; |
reg [31:0] shift2r; |
reg [31:0] shift4r; |
reg [31:0] shift8r; |
reg [31:0] shift16r; |
begin |
fill = 16'b0000000000000000; |
if (y[0] == 1'b1) |
shift1r = {fill[31],x[31:1]}; |
else |
shift1r = x; |
|
if (y[1] == 1'b1) |
shift2r = {fill[31:30],shift1r[31:2]}; |
else |
shift2r = shift1r; |
|
if (y[2] == 1'b1) |
shift4r = {fill[31:28],shift2r[31:4]}; |
else |
shift4r = shift2r; |
|
if (y[3] == 1'b1) |
shift8r = {fill[31:24],shift4r[31:8]}; |
else |
shift8r = shift4r; |
|
if (y[4] == 1'b1) |
shift16r = {fill[31:16],shift8r[31:16]}; |
else |
shift16r = shift8r; |
|
shift_right = shift16r; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// shift_right_arith: Shift right by specified amount (sign extend) |
// Inputs: x = input, y = shift amount |
// Return: (int)x >> y |
//----------------------------------------------------------------- |
function [31:0] shift_right_arith; |
input [31:0] x; |
input [31:0] y; |
reg [31:16] fill; |
reg [31:0] shift1r; |
reg [31:0] shift2r; |
reg [31:0] shift4r; |
reg [31:0] shift8r; |
reg [31:0] shift16r; |
begin |
if (x[31] == 1'b1) |
fill = 16'b1111111111111111; |
else |
fill = 16'b0000000000000000; |
|
if (y[0] == 1'b1) |
shift1r = {fill[31],x[31:1]}; |
else |
shift1r = x; |
|
if (y[1] == 1'b1) |
shift2r = {fill[31:30],shift1r[31:2]}; |
else |
shift2r = shift1r; |
|
if (y[2] == 1'b1) |
shift4r = {fill[31:28],shift2r[31:4]}; |
else |
shift4r = shift2r; |
|
if (y[3] == 1'b1) |
shift8r = {fill[31:24],shift4r[31:8]}; |
else |
shift8r = shift4r; |
|
if (y[4] == 1'b1) |
shift16r = {fill[31:16],shift8r[31:16]}; |
else |
shift16r = shift8r; |
|
shift_right_arith = shift16r; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_signed: Less than operator (signed) |
// Inputs: x = left operand, y = right operand |
// Return: (int)x < (int)y |
//----------------------------------------------------------------- |
function [0:0] less_than_signed; |
input [31:0] x; |
input [31:0] y; |
reg [31:0] v; |
begin |
v = (x - y); |
if (x[31] != y[31]) |
less_than_signed = x[31]; |
else |
less_than_signed = v[31]; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than: Less than operator (unsigned) |
// Inputs: x = left operand, y = right operand |
// Return: x < y |
//----------------------------------------------------------------- |
function [0:0] less_than; |
input [31:0] x; |
input [31:0] y; |
begin |
if (x < y) |
less_than = 1'b1; |
else |
less_than = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// sign_extend_imm16: Extend 16-bit signed value to 32-bit signed. |
// Inputs: x = operand |
// Return: (int)((short)x) |
//----------------------------------------------------------------- |
function [31:0] sign_extend_imm16; |
input [15:0] x; |
reg [31:0] y; |
begin |
if (x[15] == 1'b0) |
y[31:16] = 16'b0000000000000000; |
else |
y[31:16] = 16'b1111111111111111; |
|
y[15:0] = x; |
sign_extend_imm16 = y; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// extend_imm16: Extend 16-bit unsigned value to 32-bit unsigned. |
// Inputs: x = operand |
// Return: (unsigned int)x |
//----------------------------------------------------------------- |
function [31:0] extend_imm16; |
input [15:0] x; |
begin |
extend_imm16 = {16'h0000,x}; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_zero: Is signed value less than 0? |
// Inputs: x = operand |
// Return: ((int)x) < 0 |
//----------------------------------------------------------------- |
function [0:0] less_than_zero; |
input [31:0] x; |
begin |
if ((x != 32'h00000000) & (x[31] == 1'b1)) |
less_than_zero = 1'b1; |
else |
less_than_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// less_than_equal_zero: Is signed value less than or equal to 0? |
// Inputs: x = operand |
// Return: ((int)x) <= 0 |
//----------------------------------------------------------------- |
function [0:0] less_than_equal_zero; |
input [31:0] x; |
begin |
if ((x == 32'h00000000) | (x[31] == 1'b1)) |
less_than_equal_zero = 1'b1; |
else |
less_than_equal_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// more_than_equal_zero: Is signed value more than or equal to 0? |
// Inputs: x = operand |
// Return: ((int)x) >= 0 |
//----------------------------------------------------------------- |
function [0:0] more_than_equal_zero; |
input [31:0] x; |
begin |
if ((x == 32'h00000000) | (x[31] == 1'b0)) |
more_than_equal_zero = 1'b1; |
else |
more_than_equal_zero = 1'b0; |
end |
endfunction |
|
//----------------------------------------------------------------- |
// more_than_equal_zero: Is signed value more than 0? |
// Inputs: x = operand |
// Return: ((int)x) > 0 |
//----------------------------------------------------------------- |
function [0:0] more_than_zero; |
input [31:0] x; |
begin |
if (((x != 32'h00000000) & (x[31] == 1'b0))) |
more_than_zero = 1'b1; |
else |
more_than_zero = 1'b0; |
end |
endfunction |
/mpx/mpx.v
0,0 → 1,1302
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "mpx_defs.v" |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module mpx |
( |
// General |
clk_i, |
rst_i, |
en_i, |
intr_i, |
step_done_o, |
fault_o, |
|
// Data Memory |
mem_addr_o, |
mem_data_out_o, |
mem_data_in_i, |
mem_wr_o, |
mem_rd_o, |
mem_pause_i, |
|
// Debug Access |
dbg_reg_addr_i, |
dbg_reg_out_o, |
dbg_pc_o |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] BOOT_VECTOR = 32'h00000000; |
parameter [31:0] ISR_VECTOR = 32'h0000003C; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
// General |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input en_i /*verilator public*/; |
input intr_i /*verilator public*/; |
output fault_o /*verilator public*/; |
output step_done_o /*verilator public*/; |
|
// Data Memory |
output [31:0] mem_addr_o /*verilator public*/; |
output [31:0] mem_data_out_o /*verilator public*/; |
input [31:0] mem_data_in_i /*verilator public*/; |
output [3:0] mem_wr_o /*verilator public*/; |
output mem_rd_o /*verilator public*/; |
input mem_pause_i /*verilator public*/; |
|
// Debug Register Access |
input [8:0] dbg_reg_addr_i /*verilator public*/; |
output [31:0] dbg_reg_out_o /*verilator public*/; |
output [31:0] dbg_pc_o /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Other registers |
reg [31:0] r_pc; |
reg [31:0] r_epc; |
reg [31:0] r_status; |
reg [3:0] r_cause; |
reg [31:0] r_fault_info; |
reg [31:0] r_isr_vector; |
reg [31:0] r_lo; |
reg [31:0] r_hi; |
|
// Register file access |
wire [4:0] r_rt; |
wire [4:0] r_rd; |
reg [4:0] r_rd_wb; |
wire [4:0] r_rs; |
wire [4:0] r_rs_muxed; |
wire [31:0] r_reg_rt; |
wire [31:0] r_reg_rs; |
reg [31:0] r_reg_result; |
reg [31:0] r_reg_rd_out; |
reg r_writeback; |
|
// Pipeline registers |
reg [31:0] r_opcode; |
reg [31:0] d_opcode; |
reg r_branch_dslot; |
reg [4:0] d_rd_wb; |
reg [4:0] d2_rd_wb; |
reg [31:0] d_reg_result; |
reg c_load_op; |
reg [31:0] c_mem_forward; |
reg d_mem_access; |
|
// Memory |
reg [31:0] mem_addr; |
wire [31:0] mem_addr_mux; |
reg [31:0] mem_addr_last; |
reg [31:0] mem_data_out; |
wire [31:0] mem_data_in; |
reg [3:0] mem_wr; |
reg mem_rd; |
reg [1:0] mem_offset; |
reg [1:0] d_mem_offset; |
reg r_mem_access; |
reg [31:0] r_pc_branch; |
reg r_take_intr; |
reg d_take_intr; |
|
// ALU |
reg [31:0] alu_a; |
reg [31:0] alu_b; |
wire [31:0] alu_result; |
reg [31:0] d_alu_result; |
reg [3:0] alu_func; |
reg [3:0] d_alu_func; |
|
reg step_done_o; |
reg fault_o; |
wire [31:0] mem_addr_o; |
wire [31:0] mem_data_out_o; |
wire [3:0] mem_wr_o; |
wire mem_rd_o; |
wire [31:0] dbg_reg_out_o; |
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
mpx_alu alu |
( |
.input_a(alu_a), |
.input_b(alu_b), |
.func(alu_func), |
.result(alu_result) |
); |
|
`ifdef CONF_MPX_TARGET_SIM |
mpx_regfile_sim |
`else |
mpx_regfile_xil |
`endif |
reg_bank |
( |
// Clocking |
.clk_i(clk_i), |
.rst_i(rst_i), |
.en_i(1'b1), |
.wr_i(r_writeback), |
|
// Tri-port |
.rs_i(r_rs_muxed), |
.rt_i(r_rt), |
.rd_i(d2_rd_wb), |
.reg_rs_o(r_reg_rs), |
.reg_rt_o(r_reg_rt), |
.reg_rd_i(r_reg_rd_out) |
); |
|
// Debug access to register set |
assign r_rs_muxed = en_i ? r_rs : dbg_reg_addr_i[4:0]; |
assign dbg_reg_out_o = r_reg_rs; |
assign dbg_pc_o = r_pc; |
|
//------------------------------------------------------------------- |
// Pipeline |
//------------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i ) |
begin |
if (rst_i == 1'b1) |
begin |
d_opcode <= 32'h00000000; |
d_rd_wb <= 5'b00000; |
d2_rd_wb <= 5'b00000; |
d_reg_result <= 32'h00000000; |
d_alu_result <= 32'h00000000; |
d_alu_func <= 4'b0000; |
d_mem_offset <= 2'b00; |
d_mem_access <= 1'b0; |
d_take_intr <= 1'b0; |
mem_addr_last<= 32'h00000000; |
end |
else if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) |
begin |
d_opcode <= r_opcode; |
d_rd_wb <= r_rd_wb; |
d2_rd_wb <= d_rd_wb; |
d_reg_result <= r_reg_result; |
d_alu_result <= alu_result; |
d_alu_func <= alu_func; |
d_mem_offset <= mem_offset; |
d_mem_access <= r_mem_access; |
d_take_intr <= r_take_intr; |
|
if (r_mem_access == 1'b1) |
mem_addr_last <= mem_addr; |
else |
mem_addr_last <= r_pc; |
end |
end |
|
//------------------------------------------------------------------- |
// Execute |
//------------------------------------------------------------------- |
reg [7:0] v_inst; |
reg [4:0] v_rs; |
reg [4:0] v_rt; |
reg [4:0] v_rd; |
reg [4:0] v_re; |
reg [7:0] v_func; |
reg [15:0] v_imm; |
reg [31:0] v_imm_uint32; |
reg [31:0] v_imm_int32; |
reg [25:0] v_target; |
|
reg [31:0] v_reg_rs; |
reg [31:0] v_reg_rt; |
|
reg [31:0] v_pc; |
reg [31:0] v_pc_next; |
|
reg [31:0] v_reg_result; |
|
reg [31:0] v_offset; |
|
reg v_exception; |
reg v_emulate; |
|
reg v_branch; |
reg v_jmp; |
reg v_write_rt; |
reg v_write_rd; |
|
reg [31:0] v_mem_addr; |
reg v_mem_access; |
reg [31:0] v_mem_data_in; |
|
reg [31:0] v_status; |
|
always @ (posedge clk_i or posedge rst_i ) |
begin |
if (rst_i == 1'b1) |
begin |
|
// Default to no ALU operation |
alu_func <= `ALU_NONE; |
|
r_rd_wb <= 5'b00000; |
r_pc <= BOOT_VECTOR; |
|
r_epc <= 32'h00000000; |
r_status <= 32'h00000000; |
r_cause <= `EXCEPTION_NONE; |
r_fault_info <= 32'h00000000; |
r_lo <= 32'h00000000; |
r_hi <= 32'h00000000; |
r_branch_dslot <= 1'b0; |
r_pc_branch <= 32'h00000000; |
r_take_intr <= 1'b0; |
|
r_opcode <= 32'h00000000; |
|
mem_addr <= 32'h00000000; |
mem_data_out <= 32'h00000000; |
mem_rd <= 1'b0; |
mem_wr <= 4'b0000; |
mem_offset <= 2'b00; |
|
// Default ISR vector address |
r_isr_vector <= ISR_VECTOR; |
|
fault_o <= 1'b0; |
r_mem_access <= 1'b0; |
|
end |
else if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) |
begin |
|
mem_rd <= 1'b0; |
mem_wr <= 4'b0000; |
|
v_exception = 1'b0; |
v_emulate = 1'b0; |
v_branch = 1'b0; |
v_jmp = 1'b0; |
v_write_rt = 1'b0; |
v_write_rd = 1'b0; |
v_status = r_status; |
v_mem_access = 1'b0; |
v_mem_data_in = mem_data_in_i; |
|
// If memory access was done, check for no instruction to process. |
// As memory access has a 1 cycle latency, invalid mem_data_in_i is |
// aligned with d_mem_access not r_mem_access. |
if (d_mem_access == 1'b1) |
v_mem_data_in = `OPCODE_INST_BUBBLE; |
|
// Flush pipeline due to an exception/interrupt? |
// NOTE: When d_take_intr=1, mem_data_in_i will be invalid for one more cycle |
if ((r_take_intr == 1'b1) || (d_take_intr == 1'b1)) |
v_mem_data_in = `OPCODE_INST_BUBBLE; |
|
r_take_intr <= 1'b0; |
|
// Decode opcode |
r_opcode <= v_mem_data_in; |
v_inst = {2'b00,v_mem_data_in[31:26]}; |
v_rs = v_mem_data_in[25:21]; |
v_rt = v_mem_data_in[20:16]; |
v_rd = v_mem_data_in[15:11]; |
v_re = v_mem_data_in[10:6]; |
v_func = {2'b00,v_mem_data_in[5:0]}; |
v_imm = v_mem_data_in[15:0]; |
v_target = v_mem_data_in[25:0]; |
|
// Signed & unsigned imm -> 32-bits |
v_imm_int32 = sign_extend_imm16(v_imm); |
v_imm_uint32 = extend_imm16(v_imm); |
|
// Load register[rs] |
v_reg_rs = r_reg_rs; |
|
// Load register[rt] |
v_reg_rt = r_reg_rt; |
|
// Register[rs] hazard detection & forwarding logic |
// (higher priority = latest results!) |
if (v_rs != 5'b00000) |
begin |
if (v_rs == r_rd_wb) |
begin |
// Result from memory / other |
if (alu_func == `ALU_NONE) |
begin |
v_reg_rs = r_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_rs = alu_result; |
end |
end |
else if (v_rs == d_rd_wb) |
begin |
// Result from memory load? |
if (c_load_op == 1'b1) |
begin |
v_reg_rs = c_mem_forward; |
end |
// Result from memory / other |
else if (d_alu_func == `ALU_NONE) |
begin |
v_reg_rs = d_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_rs = d_alu_result; |
end |
end |
else if (v_rs == d2_rd_wb) |
begin |
v_reg_rs = r_reg_rd_out; |
end |
end |
|
// Register[rt] hazard detection & forwarding logic |
// (higher priority = latest results!) |
if (v_rt != 5'b00000) |
begin |
if (v_rt == r_rd_wb) |
begin |
// Result from memory / other |
if (alu_func == `ALU_NONE) |
begin |
v_reg_rt = r_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_rt = alu_result; |
end |
end |
else if (v_rt == d_rd_wb) |
begin |
// Result from memory load? |
if (c_load_op == 1'b1) |
begin |
v_reg_rt = c_mem_forward; |
end |
// Result from non ALU function |
else if (d_alu_func == `ALU_NONE) |
begin |
v_reg_rt = d_reg_result; |
end |
// Result from ALU |
else |
begin |
v_reg_rt = d_alu_result; |
end |
|
end |
else if (v_rt == d2_rd_wb) |
begin |
v_reg_rt = r_reg_rd_out; |
end |
end |
|
// Zero result |
v_reg_result = 32'h00000000; |
|
// Update PC to next value |
v_pc = (r_pc + 4); |
|
// Default to no ALU operation |
alu_func <= `ALU_NONE; |
|
// Default target is r_rd |
r_rd_wb <= r_rd; |
|
// Reset branch delay slot status |
r_branch_dslot <= 1'b0; |
|
// Execute instruction |
case (v_inst) |
8'h00 : |
case (v_func) |
`INSTR_R_SLL: |
begin |
alu_func <= `ALU_SHIFTL; |
alu_a <= v_reg_rt; |
alu_b <= {27'b0, v_re}; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SRL: |
begin |
alu_func <= `ALU_SHIFTR; |
alu_a <= v_reg_rt; |
alu_b <= {27'b0, v_re}; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SRA: |
begin |
alu_func <= `ALU_SHIRTR_ARITH; |
alu_a <= v_reg_rt; |
alu_b <= {27'b0, v_re}; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SLLV: |
begin |
alu_func <= `ALU_SHIFTL; |
alu_a <= v_reg_rt; |
alu_b <= v_reg_rs; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SRLV: |
begin |
alu_func <= `ALU_SHIFTR; |
alu_a <= v_reg_rt; |
alu_b <= v_reg_rs; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SRAV: |
begin |
alu_func <= `ALU_SHIRTR_ARITH; |
alu_a <= v_reg_rt; |
alu_b <= v_reg_rs; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_JR: |
begin |
v_pc = v_reg_rs; |
v_jmp = 1'b1; |
end |
|
`INSTR_R_JALR: |
begin |
v_reg_result = v_pc; |
v_write_rd = 1'b1; |
v_pc = v_reg_rs; |
v_jmp = 1'b1; |
end |
|
`INSTR_R_SYSCALL: |
begin |
v_exception = 1'b1; |
r_cause <= `EXCEPTION_SYSCALL; |
end |
|
`INSTR_R_BREAK: |
begin |
v_exception = 1'b1; |
r_cause <= `EXCEPTION_BREAK; |
end |
|
`INSTR_R_MFHI: |
begin |
v_reg_result = r_hi; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_MTHI: |
begin |
r_hi <= v_reg_rs; |
end |
|
`INSTR_R_MFLO: |
begin |
v_reg_result = r_lo; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_MTLO: |
begin |
r_lo <= v_reg_rs; |
end |
|
`INSTR_R_MULT: |
begin |
v_exception = 1'b1; |
v_emulate = 1'b1; |
r_cause <= `EXCEPTION_MULT; |
end |
|
`INSTR_R_MULTU: |
begin |
v_exception = 1'b1; |
v_emulate = 1'b1; |
r_cause <= `EXCEPTION_UMULT; |
end |
|
`INSTR_R_DIV: |
begin |
v_exception = 1'b1; |
v_emulate = 1'b1; |
r_cause <= `EXCEPTION_DIV; |
end |
|
`INSTR_R_DIVU: |
begin |
v_exception = 1'b1; |
v_emulate = 1'b1; |
r_cause <= `EXCEPTION_UDIV; |
end |
|
`INSTR_R_ADD: |
begin |
alu_func <= `ALU_ADD; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_ADDU: |
begin |
alu_func <= `ALU_ADD; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SUB: |
begin |
alu_func <= `ALU_SUB; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SUBU: |
begin |
alu_func <= `ALU_SUB; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_AND: |
begin |
alu_func <= `ALU_AND; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_OR: |
begin |
alu_func <= `ALU_OR; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_XOR: |
begin |
alu_func <= `ALU_XOR; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_NOR: |
begin |
alu_func <= `ALU_NOR; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SLT: |
begin |
alu_func <= `ALU_SLT; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
|
`INSTR_R_SLTU: |
begin |
alu_func <= `ALU_SLTU; |
alu_a <= v_reg_rs; |
alu_b <= v_reg_rt; |
v_write_rd = 1'b1; |
end |
default : |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
r_cause <= `EXCEPTION_FAULT; |
r_fault_info <= v_mem_data_in; |
end |
endcase |
|
// REGIMM |
`INSTR_I_REGIMM : |
case (v_rt) |
`INSTR_I_COND_BLTZAL : // BLTZAL [ branch = ((int)v_reg_rs < 0) ] |
begin |
v_reg_result = v_pc; |
v_write_rd = 1'b1; |
r_rd_wb <= 5'b11111; // Write to $ra |
v_branch = less_than_zero(v_reg_rs); |
end |
|
`INSTR_I_COND_BLTZ : // BLTZ [ branch = ((int)v_reg_rs < 0) ] |
begin |
v_branch = less_than_zero(v_reg_rs); |
end |
|
`INSTR_I_COND_BGEZAL : // BGEZAL [ branch = ((int)v_reg_rs >= 0) ] |
begin |
v_reg_result = v_pc; |
v_write_rd = 1'b1; |
r_rd_wb <= 5'b11111; // Write to $ra |
v_branch = more_than_equal_zero(v_reg_rs); |
end |
|
`INSTR_I_COND_BGEZ : // BGEZ [ branch = ((int)v_reg_rs >= 0) ] |
begin |
v_branch = more_than_equal_zero(v_reg_rs); |
end |
|
default : |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
r_cause <= `EXCEPTION_FAULT; |
r_fault_info <= v_mem_data_in; |
end |
endcase |
|
`INSTR_J_JAL: |
begin |
v_reg_result = v_pc; |
v_write_rd = 1'b1; |
r_rd_wb <= 5'b11111; // Write to $ra |
v_pc = {{v_pc[31:28],v_target[25:0]},2'b00}; |
v_jmp = 1'b1; |
end |
|
`INSTR_J_J: |
begin |
v_pc = {{v_pc[31:28],v_target[25:0]},2'b00}; |
v_jmp = 1'b1; |
end |
|
`INSTR_J_BEQ: |
begin |
if ((v_reg_rs == v_reg_rt)) |
v_branch = 1'b1; |
end |
|
`INSTR_J_BNE: |
begin |
if ((!(v_reg_rs==v_reg_rt))) |
v_branch = 1'b1; |
end |
|
`INSTR_J_BLEZ : // BLEZ [ branch = (int)v_reg_rs <= 0 ] |
v_branch = less_than_equal_zero(v_reg_rs); |
|
`INSTR_J_BGTZ : // BGTZ [ branch = (int)v_reg_rs > 0 ] |
v_branch = more_than_zero(v_reg_rs); |
|
`INSTR_I_ADDI: |
begin |
alu_func <= `ALU_ADD; |
alu_a <= v_reg_rs; |
alu_b <= v_imm_int32; |
v_write_rt = 1'b1; |
end |
|
`INSTR_I_ADDIU: |
begin |
alu_func <= `ALU_ADD; |
alu_a <= v_reg_rs; |
alu_b <= v_imm_int32; |
v_write_rt = 1'b1; |
end |
|
`INSTR_I_SLTI: |
begin |
alu_func <= `ALU_SLT; |
alu_a <= v_reg_rs; |
alu_b <= v_imm_int32; |
v_write_rt = 1'b1; |
end |
|
`INSTR_I_SLTIU: |
begin |
alu_func <= `ALU_SLTU; |
alu_a <= v_reg_rs; |
alu_b <= v_imm_int32; |
v_write_rt = 1'b1; |
end |
|
`INSTR_I_ANDI: |
begin |
alu_func <= `ALU_AND; |
alu_a <= v_reg_rs; |
alu_b <= v_imm_uint32; |
v_write_rt = 1'b1; |
end |
|
`INSTR_I_ORI: |
begin |
alu_func <= `ALU_OR; |
alu_a <= v_reg_rs; |
alu_b <= v_imm_uint32; |
v_write_rt = 1'b1; |
end |
|
`INSTR_I_XORI: |
begin |
alu_func <= `ALU_XOR; |
alu_a <= v_reg_rs; |
alu_b <= v_imm_uint32; |
v_write_rt = 1'b1; |
end |
|
`INSTR_I_LUI: |
begin |
v_reg_result = {v_imm,16'h0000}; |
v_write_rt = 1'b1; |
end |
|
`INSTR_COP0: |
begin |
|
// Move from CP0 |
if (v_rs[2] == 1'b0) |
case (v_rd) |
`COP0_STATUS: |
begin |
v_reg_result = r_status; |
v_write_rt = 1'b1; |
end |
|
`COP0_CAUSE: |
begin |
v_reg_result = {28'h0000000,r_cause}; |
v_write_rt = 1'b1; |
end |
|
`COP0_EPC: |
begin |
v_reg_result = r_epc; |
v_write_rt = 1'b1; |
end |
|
`COP0_ISR_VECT: |
begin |
v_reg_result = r_isr_vector; |
v_write_rt = 1'b1; |
end |
|
`COP0_FAULT_INFO: |
begin |
v_reg_result = r_fault_info; |
v_write_rt = 1'b1; |
end |
|
default : |
begin |
end |
|
endcase |
|
// Move to CP0 |
else |
case (v_rd) |
`COP0_STATUS: |
begin |
r_status <= v_reg_rt; |
v_status = v_reg_rt; |
end |
|
`COP0_CAUSE: |
r_cause <= v_reg_rt[3:0]; |
|
`COP0_EPC: |
r_epc <= v_reg_rt; |
|
`COP0_ISR_VECT: |
r_isr_vector <= v_reg_rt; |
|
`COP0_FAULT_INFO: |
r_fault_info <= v_reg_rt; |
|
default : |
begin |
end |
endcase |
end |
|
// Memory load / store instructions |
|
`INSTR_I_LB, `INSTR_I_LH, `INSTR_I_LW, `INSTR_I_LBU, `INSTR_I_LHU : |
begin |
v_mem_addr = (v_reg_rs + v_imm_int32); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
mem_data_out <= 32'h00000000; |
mem_rd <= 1'b1; |
mem_offset <= v_mem_addr[1:0]; |
v_write_rt = 1'b1; |
v_mem_access = 1'b1; |
end |
|
`INSTR_I_SB: |
begin |
v_mem_addr = (v_reg_rs + v_imm_int32); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
case (v_mem_addr[1:0]) |
2'b00 : |
begin |
mem_data_out <= {v_reg_rt[7:0],24'h000000}; |
mem_wr <= 4'b1000; |
v_mem_access = 1'b1; |
end |
2'b01 : |
begin |
mem_data_out <= {{8'h00,v_reg_rt[7:0]},16'h0000}; |
mem_wr <= 4'b0100; |
v_mem_access = 1'b1; |
end |
2'b10 : |
begin |
mem_data_out <= {{16'h0000,v_reg_rt[7:0]},8'h00}; |
mem_wr <= 4'b0010; |
v_mem_access = 1'b1; |
end |
2'b11 : |
begin |
mem_data_out <= {24'h000000,v_reg_rt[7:0]}; |
mem_wr <= 4'b0001; |
v_mem_access = 1'b1; |
end |
default : |
begin |
mem_data_out <= 32'h00000000; |
mem_wr <= 4'b0000; |
end |
endcase |
end |
|
`INSTR_I_SH: |
begin |
v_mem_addr = (v_reg_rs + v_imm_int32); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
case (v_mem_addr[1:0]) |
2'b00 : |
begin |
mem_data_out <= {v_reg_rt[15:0],16'h0000}; |
mem_wr <= 4'b1100; |
v_mem_access = 1'b1; |
end |
2'b10 : |
begin |
mem_data_out <= {16'h0000,v_reg_rt[15:0]}; |
mem_wr <= 4'b0011; |
v_mem_access = 1'b1; |
end |
default : |
begin |
mem_data_out <= 32'h00000000; |
mem_wr <= 4'b0000; |
end |
endcase |
end |
|
`INSTR_I_SW: |
begin |
v_mem_addr = (v_reg_rs + v_imm_int32); |
mem_addr <= {v_mem_addr[31:2],2'b00}; |
mem_data_out <= v_reg_rt; |
mem_wr <= 4'b1111; |
v_mem_access = 1'b1; |
end |
|
`INSTR_BUBBLE: |
begin |
end |
|
default : |
begin |
fault_o <= 1'b1; |
v_exception = 1'b1; |
r_cause <= `EXCEPTION_FAULT; |
r_fault_info <= v_mem_data_in; |
end |
endcase |
|
// Handle branches |
if (v_branch == 1'b1) |
begin |
v_offset = v_imm_int32; |
v_offset = {v_offset[29:0],2'b00}; |
v_pc = (r_pc + v_offset); |
|
// Next instruction is branch delay slot |
r_branch_dslot <= 1'b1; |
r_pc_branch <= v_pc; |
end |
// If not branching, handle interrupts / exceptions |
else if ((v_jmp == 1'b0) && (v_inst != `INSTR_BUBBLE)) |
begin |
|
// Exception (Fault/Mult/Div/Syscall/Break) |
if (v_exception == 1'b1) |
begin |
|
// Schedule interrupt after pipeline flush |
r_take_intr <= 1'b1; |
|
// Record instruction to continue from |
r_epc <= r_pc; |
|
// Disable interrupts by shifting left status register |
r_status <= {v_status[30:0],1'b0}; |
end |
// External interrupt (and not handling an exception, branch or bubble)? |
// NOTE: d_mem_access & r_branch_dslot are exclusive as this would result in a bubble |
else if ((intr_i == 1'b1) && (v_status[0] == 1'b1)) |
begin |
// Schedule interrupt after pipeline flush |
r_take_intr <= 1'b1; |
|
// Interrupt src is external |
r_cause <= `EXCEPTION_EXTINT; |
|
// Record instruction to continue from |
r_epc <= r_pc; |
|
// Disable interrupts by shifting left status register |
r_status <= {v_status[30:0],1'b0}; |
end |
end |
// Handle jumps |
else if (v_jmp == 1'b1) |
begin |
// Next instruction is branch delay slot |
r_branch_dslot <= 1'b1; |
r_pc_branch <= v_pc; |
end |
|
// Update to new PC value only if last cycle wasn't a memory access |
if (r_mem_access == 1'b0) |
r_pc <= v_pc; |
|
// Stall in branch delay slot due to mem access? |
if ((d_mem_access == 1'b1) && (r_branch_dslot == 1'b1)) |
r_pc <= r_pc_branch; |
|
// If pipeline flushed due to interrupt request |
if (r_take_intr == 1'b1) |
begin |
// Jump to ISR |
r_pc <= r_isr_vector; |
end |
|
// Update other registers with variable values |
r_reg_result <= v_reg_result; |
r_mem_access <= v_mem_access; |
|
// Target is Register[rt] |
if (v_write_rt == 1'b1) |
begin |
// Store new value to register[rt] instead of register[rd] |
r_rd_wb <= r_rt; |
end |
// No writeback required? |
else if ((v_write_rt == 1'b0) && (v_write_rd == 1'b0)) |
begin |
// Target register is $0 which is read-only |
r_rd_wb <= 5'b00000; |
end |
end |
end |
|
//------------------------------------------------------------------- |
// Writeback |
//------------------------------------------------------------------- |
reg [31:0] wb_v_reg_result; |
reg [7:0] wb_v_inst; |
|
always @ (posedge clk_i or posedge rst_i ) |
begin |
if (rst_i == 1'b1) |
begin |
r_writeback <= 1'b1; |
step_done_o <= 1'b0; |
end |
else |
begin |
r_writeback <= 1'b0; |
step_done_o <= 1'b0; |
|
if ((en_i == 1'b1) && (mem_pause_i == 1'b0)) |
begin |
|
wb_v_reg_result = d_reg_result; |
|
// Handle delayed result instructions |
wb_v_inst = {2'b00,d_opcode[31:26]}; |
case (wb_v_inst) |
`INSTR_I_LB: |
begin |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; |
2'b01 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; |
2'b10 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; |
2'b11 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
// Sign extend LB |
if (wb_v_reg_result[7] == 1'b1) |
wb_v_reg_result = {24'hFFFFFF,wb_v_reg_result[7:0]}; |
end |
|
`INSTR_I_LBU: |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; |
2'b01 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; |
2'b10 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; |
2'b11 : |
wb_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
`INSTR_I_LH: |
begin |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; |
2'b10 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
// Sign extend LH |
if (wb_v_reg_result[15] == 1'b1) |
wb_v_reg_result = {16'h1111,wb_v_reg_result[15:0]}; |
end |
|
`INSTR_I_LHU: |
case (d_mem_offset) |
2'b00 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; |
2'b10 : |
wb_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; |
default : |
wb_v_reg_result = 32'h00000000; |
endcase |
|
`INSTR_I_LW: |
wb_v_reg_result = mem_data_in_i; |
|
default : |
wb_v_reg_result = d_reg_result; |
endcase |
|
// Result from memory / other |
if ((d_alu_func == `ALU_NONE)) |
begin |
r_reg_rd_out <= wb_v_reg_result; |
end |
// Result from ALU |
else |
begin |
r_reg_rd_out <= d_alu_result; |
end |
|
// Register writeback required? |
if (d_rd_wb != 5'b00000) |
r_writeback <= 1'b1; |
|
// If instruction was not bubble, output step done flag |
if (wb_v_inst != `INSTR_BUBBLE) |
step_done_o <= 1'b1; |
end |
end |
end |
|
//------------------------------------------------------------------- |
// Combinatorial |
//-----------------------------------------------------------------// |
|
// Memory access mux |
assign mem_data_in = mem_data_in_i; |
assign mem_addr_mux = (r_mem_access == 1'b1) ? mem_addr : r_pc; |
assign mem_addr_o = (mem_pause_i == 1'b1) ? mem_addr_last : mem_addr_mux; |
assign mem_data_out_o = mem_data_out; |
assign mem_rd_o = (r_mem_access == 1'b1) ? mem_rd : 1'b1; |
assign mem_wr_o = (mem_pause_i == 1'b0) ? mem_wr : 4'b0000; |
|
// Opcode register decoding |
assign r_rs = mem_data_in_i[25:21]; |
assign r_rt = mem_data_in_i[20:16]; |
assign r_rd = mem_data_in_i[15:11]; |
|
//------------------------------------------------------------------- |
// Async memory result forwarding |
//------------------------------------------------------------------- |
reg [31:0] ldf_v_reg_result; |
reg [7:0] ldf_v_inst; |
|
always @ (d_opcode or mem_offset or mem_data_in_i ) |
begin |
|
// Handle delayed result instructions |
ldf_v_inst = {2'b00,d_opcode[31:26]}; |
case (ldf_v_inst) |
|
`INSTR_I_LB: |
begin |
c_load_op = 1'b1; |
case (mem_offset) |
2'b00 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; |
2'b01 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; |
2'b10 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; |
2'b11 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; |
default : |
ldf_v_reg_result = 32'h00000000; |
endcase |
|
// Sign extend LB |
if (ldf_v_reg_result[7] == 1'b1) |
ldf_v_reg_result = {24'hFFFFFF,ldf_v_reg_result[7:0]}; |
end |
|
`INSTR_I_LBU: |
begin |
c_load_op = 1'b1; |
case (mem_offset) |
2'b00 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[31:24]}; |
2'b01 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[23:16]}; |
2'b10 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[15:8]}; |
2'b11 : |
ldf_v_reg_result = {24'h000000,mem_data_in_i[7:0]}; |
default : |
ldf_v_reg_result = 32'h00000000; |
endcase |
end |
|
`INSTR_I_LH: |
begin |
c_load_op = 1'b1; |
case (mem_offset) |
2'b00 : |
ldf_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; |
2'b10 : |
ldf_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; |
default : |
ldf_v_reg_result = 32'h00000000; |
endcase |
|
// Sign extend LH |
if (ldf_v_reg_result[15] == 1'b1) |
ldf_v_reg_result = {16'h1111,ldf_v_reg_result[15:0]}; |
end |
|
`INSTR_I_LHU: |
begin |
c_load_op = 1'b1; |
case (mem_offset) |
2'b00 : |
ldf_v_reg_result = {16'h0000,mem_data_in_i[31:16]}; |
2'b10 : |
ldf_v_reg_result = {16'h0000,mem_data_in_i[15:0]}; |
default : |
ldf_v_reg_result = 32'h00000000; |
endcase |
end |
|
`INSTR_I_LW: |
begin |
c_load_op = 1'b1; |
ldf_v_reg_result = mem_data_in_i; |
end |
|
default : |
begin |
c_load_op = 1'b0; |
ldf_v_reg_result = 32'h00000000; |
end |
endcase |
|
c_mem_forward = ldf_v_reg_result; |
end |
|
`include "mpx_funcs.v" |
|
endmodule |
/mpx/mpx_alu.v
0,0 → 1,113
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "mpx_defs.v" |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module mpx_alu |
( |
input_a, |
input_b, |
func, |
result |
); |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input [31:0] input_a /*verilator public*/; |
input [31:0] input_b /*verilator public*/; |
input [3:0] func /*verilator public*/; |
output [31:0] result /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [31:0] result; |
|
//----------------------------------------------------------------- |
// ALU |
//----------------------------------------------------------------- |
always @ (func or input_a or input_b ) |
begin |
case (func) |
`ALU_SHIFTL : result = shift_left(input_a, input_b); |
`ALU_SHIFTR : result = shift_right(input_a, input_b); |
`ALU_SHIRTR_ARITH: result = shift_right_arith(input_a, input_b); |
`ALU_ADD : result = (input_a + input_b); |
`ALU_SUB : result = (input_a - input_b); |
`ALU_AND : result = (input_a & input_b); |
`ALU_OR : result = (input_a | input_b); |
`ALU_XOR : result = (input_a ^ input_b); |
`ALU_NOR : result = (~(input_a | input_b)); |
`ALU_SLT : |
begin |
if (less_than_signed(input_a, input_b) == 1'b1) |
result = 32'h00000001; |
else |
result = 32'h00000000; |
end |
`ALU_SLTE : |
begin |
if ((less_than_signed(input_a, input_b) == 1'b1) || (input_a == input_b)) |
result = 32'h00000001; |
else |
result = 32'h00000000; |
end |
`ALU_SLTU : |
begin |
if (less_than(input_a, input_b) == 1'b1) |
result = 32'h00000001; |
else |
result = 32'h00000000; |
end |
default : |
result = 32'h00000000; |
endcase |
end |
|
`include "mpx_funcs.v" |
|
endmodule |
/mpx/mpx_defs.v
0,0 → 1,150
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// ALU Operations |
//----------------------------------------------------------------- |
`define ALU_NONE 4'b0000 |
`define ALU_SHIFTL 4'b0001 |
`define ALU_SHIFTR 4'b0010 |
`define ALU_SHIRTR_ARITH 4'b0011 |
`define ALU_ADD 4'b0100 |
`define ALU_SUB 4'b0101 |
`define ALU_AND 4'b0110 |
`define ALU_OR 4'b0111 |
`define ALU_XOR 4'b1000 |
`define ALU_NOR 4'b1001 |
`define ALU_SLT 4'b1010 |
`define ALU_SLTE 4'b1011 |
`define ALU_SLTU 4'b1100 |
|
//----------------------------------------------------------------- |
// Instructions |
//----------------------------------------------------------------- |
|
// R Type |
`define INSTR_R_SLL 8'h00 |
`define INSTR_R_SRL 8'h02 |
`define INSTR_R_SRA 8'h03 |
`define INSTR_R_SLLV 8'h04 |
`define INSTR_R_SRLV 8'h06 |
`define INSTR_R_SRAV 8'h07 |
`define INSTR_R_JR 8'h08 |
`define INSTR_R_JALR 8'h09 |
`define INSTR_R_SYSCALL 8'h0c |
`define INSTR_R_BREAK 8'h0d |
`define INSTR_R_MFHI 8'h10 |
`define INSTR_R_MTHI 8'h11 |
`define INSTR_R_MFLO 8'h12 |
`define INSTR_R_MTLO 8'h13 |
`define INSTR_R_MULT 8'h18 |
`define INSTR_R_MULTU 8'h19 |
`define INSTR_R_DIV 8'h1a |
`define INSTR_R_DIVU 8'h1b |
`define INSTR_R_ADD 8'h20 |
`define INSTR_R_ADDU 8'h21 |
`define INSTR_R_SUB 8'h22 |
`define INSTR_R_SUBU 8'h23 |
`define INSTR_R_AND 8'h24 |
`define INSTR_R_OR 8'h25 |
`define INSTR_R_XOR 8'h26 |
`define INSTR_R_NOR 8'h27 |
`define INSTR_R_SLT 8'h2a |
`define INSTR_R_SLTU 8'h2b |
|
`define INSTR_COP0 8'h10 |
|
// J Type |
`define INSTR_J_JAL 8'h03 |
`define INSTR_J_J 8'h02 |
`define INSTR_J_BEQ 8'h04 |
`define INSTR_J_BNE 8'h05 |
`define INSTR_J_BLEZ 8'h06 |
`define INSTR_J_BGTZ 8'h07 |
|
// I Type |
`define INSTR_I_ADDI 8'h08 |
`define INSTR_I_ADDIU 8'h09 |
`define INSTR_I_SLTI 8'h0a |
`define INSTR_I_SLTIU 8'h0b |
`define INSTR_I_ANDI 8'h0c |
`define INSTR_I_ORI 8'h0d |
`define INSTR_I_XORI 8'h0e |
`define INSTR_I_LUI 8'h0f |
`define INSTR_I_LB 8'h20 |
`define INSTR_I_LH 8'h21 |
`define INSTR_I_LW 8'h23 |
`define INSTR_I_LBU 8'h24 |
`define INSTR_I_LHU 8'h25 |
`define INSTR_I_SB 8'h28 |
`define INSTR_I_SH 8'h29 |
`define INSTR_I_SW 8'h2b |
|
`define INSTR_I_REGIMM 8'h01 |
`define INSTR_I_COND_BLTZAL 5'b10000 |
`define INSTR_I_COND_BLTZ 5'b00000 |
`define INSTR_I_COND_BGEZAL 5'b10001 |
`define INSTR_I_COND_BGEZ 5'b00001 |
|
`define INSTR_BUBBLE 8'h3F |
|
`define OPCODE_INST_BUBBLE 32'hFC000000 |
|
//----------------------------------------------------------------- |
// COP0 |
//----------------------------------------------------------------- |
`define COP0_STATUS 5'b01100 |
`define COP0_CAUSE 5'b01101 |
`define COP0_EPC 5'b01110 |
`define COP0_ISR_VECT 5'b01111 |
`define COP0_FAULT_INFO 5'b10000 |
|
//----------------------------------------------------------------- |
// Exception Cause (COP0_CAUSE) |
//----------------------------------------------------------------- |
`define EXCEPTION_NONE 4'b0000 |
`define EXCEPTION_SYSCALL 4'b0001 |
`define EXCEPTION_BREAK 4'b0010 |
`define EXCEPTION_EXTINT 4'b0011 |
`define EXCEPTION_FAULT 4'b0100 |
`define EXCEPTION_MULT 4'b0101 |
`define EXCEPTION_UMULT 4'b0110 |
`define EXCEPTION_DIV 4'b0111 |
`define EXCEPTION_UDIV 4'b1000 |
/mpx/mpx_regfile_sim.v
0,0 → 1,369
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "mpx_defs.v" |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module mpx_regfile_sim |
( |
clk_i, |
rst_i, |
en_i, |
wr_i, |
rs_i, |
rt_i, |
rd_i, |
reg_rs_o, |
reg_rt_o, |
reg_rd_i |
); |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input en_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 [31:0] reg_rs_o /*verilator public*/; |
output [31:0] reg_rt_o /*verilator public*/; |
input [31:0] reg_rd_i /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
|
// Register file |
reg [31:0] reg_r1_at; |
reg [31:0] reg_r2_v0; |
reg [31:0] reg_r3_v1; |
reg [31:0] reg_r4_a0; |
reg [31:0] reg_r5_a1; |
reg [31:0] reg_r6_a2; |
reg [31:0] reg_r7_a3; |
reg [31:0] reg_r8; |
reg [31:0] reg_r9; |
reg [31:0] reg_r10; |
reg [31:0] reg_r11; |
reg [31:0] reg_r12; |
reg [31:0] reg_r13; |
reg [31:0] reg_r14; |
reg [31:0] reg_r15; |
reg [31:0] reg_r16; |
reg [31:0] reg_r17; |
reg [31:0] reg_r18; |
reg [31:0] reg_r19; |
reg [31:0] reg_r20; |
reg [31:0] reg_r21; |
reg [31:0] reg_r22; |
reg [31:0] reg_r23; |
reg [31:0] reg_r24; |
reg [31:0] reg_r25; |
reg [31:0] reg_k0; |
reg [31:0] reg_k1; |
reg [31:0] reg_gp; |
reg [31:0] reg_sp; |
reg [31:0] reg_fp; |
reg [31:0] reg_ra; |
|
//----------------------------------------------------------------- |
// Register File (for simulation) |
//----------------------------------------------------------------- |
|
// Synchronous register write back |
always @ (posedge clk_i or posedge rst_i) |
begin |
if (rst_i) |
begin |
reg_r1_at <= 32'h00000000; |
reg_r2_v0 <= 32'h00000000; |
reg_r3_v1 <= 32'h00000000; |
reg_r4_a0 <= 32'h00000000; |
reg_r5_a1 <= 32'h00000000; |
reg_r6_a2 <= 32'h00000000; |
reg_r7_a3 <= 32'h00000000; |
reg_r8 <= 32'h00000000; |
reg_r9 <= 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_k0 <= 32'h00000000; |
reg_k1 <= 32'h00000000; |
reg_gp <= 32'h00000000; |
reg_sp <= 32'h00000000; |
reg_fp <= 32'h00000000; |
reg_ra <= 32'h00000000; |
end |
else if (en_i == 1'b1) |
begin |
if (wr_i == 1'b1) |
case (rd_i[4:0]) |
5'b00001 : |
reg_r1_at <= reg_rd_i; |
5'b00010 : |
reg_r2_v0 <= reg_rd_i; |
5'b00011 : |
reg_r3_v1 <= reg_rd_i; |
5'b00100 : |
reg_r4_a0 <= reg_rd_i; |
5'b00101 : |
reg_r5_a1 <= reg_rd_i; |
5'b00110 : |
reg_r6_a2 <= reg_rd_i; |
5'b00111 : |
reg_r7_a3 <= reg_rd_i; |
5'b01000 : |
reg_r8 <= reg_rd_i; |
5'b01001 : |
reg_r9 <= reg_rd_i; |
5'b01010 : |
reg_r10 <= reg_rd_i; |
5'b01011 : |
reg_r11 <= reg_rd_i; |
5'b01100 : |
reg_r12 <= reg_rd_i; |
5'b01101 : |
reg_r13 <= reg_rd_i; |
5'b01110 : |
reg_r14 <= reg_rd_i; |
5'b01111 : |
reg_r15 <= reg_rd_i; |
5'b10000 : |
reg_r16 <= reg_rd_i; |
5'b10001 : |
reg_r17 <= reg_rd_i; |
5'b10010 : |
reg_r18 <= reg_rd_i; |
5'b10011 : |
reg_r19 <= reg_rd_i; |
5'b10100 : |
reg_r20 <= reg_rd_i; |
5'b10101 : |
reg_r21 <= reg_rd_i; |
5'b10110 : |
reg_r22 <= reg_rd_i; |
5'b10111 : |
reg_r23 <= reg_rd_i; |
5'b11000 : |
reg_r24 <= reg_rd_i; |
5'b11001 : |
reg_r25 <= reg_rd_i; |
5'b11010 : |
reg_k0 <= reg_rd_i; |
5'b11011 : |
reg_k1 <= reg_rd_i; |
5'b11100 : |
reg_gp <= reg_rd_i; |
5'b11101 : |
reg_sp <= reg_rd_i; |
5'b11110 : |
reg_fp <= reg_rd_i; |
5'b11111 : |
reg_ra <= reg_rd_i; |
default : |
; |
endcase |
end |
end |
|
// Asynchronous Register read (Rs & Rd) |
always @ (rs_i or rt_i or reg_r1_at or reg_r2_v0 or reg_r3_v1 or reg_r4_a0 or reg_r5_a1 or reg_r6_a2 or reg_r7_a3 or reg_r8 or reg_r9 or reg_r10 or reg_r11 or reg_r12 or reg_r13 or reg_r14 or reg_r15 or reg_r16 or reg_r17 or reg_r18 or reg_r19 or reg_r20 or reg_r21 or reg_r22 or reg_r23 or reg_r24 or reg_r25 or reg_k0 or reg_k1 or reg_gp or reg_sp or reg_fp or reg_ra ) |
begin |
case (rs_i) |
5'b00000 : |
reg_rs_o = 32'h00000000; |
5'b00001 : |
reg_rs_o = reg_r1_at; |
5'b00010 : |
reg_rs_o = reg_r2_v0; |
5'b00011 : |
reg_rs_o = reg_r3_v1; |
5'b00100 : |
reg_rs_o = reg_r4_a0; |
5'b00101 : |
reg_rs_o = reg_r5_a1; |
5'b00110 : |
reg_rs_o = reg_r6_a2; |
5'b00111 : |
reg_rs_o = reg_r7_a3; |
5'b01000 : |
reg_rs_o = reg_r8; |
5'b01001 : |
reg_rs_o = reg_r9; |
5'b01010 : |
reg_rs_o = reg_r10; |
5'b01011 : |
reg_rs_o = reg_r11; |
5'b01100 : |
reg_rs_o = reg_r12; |
5'b01101 : |
reg_rs_o = reg_r13; |
5'b01110 : |
reg_rs_o = reg_r14; |
5'b01111 : |
reg_rs_o = reg_r15; |
5'b10000 : |
reg_rs_o = reg_r16; |
5'b10001 : |
reg_rs_o = reg_r17; |
5'b10010 : |
reg_rs_o = reg_r18; |
5'b10011 : |
reg_rs_o = reg_r19; |
5'b10100 : |
reg_rs_o = reg_r20; |
5'b10101 : |
reg_rs_o = reg_r21; |
5'b10110 : |
reg_rs_o = reg_r22; |
5'b10111 : |
reg_rs_o = reg_r23; |
5'b11000 : |
reg_rs_o = reg_r24; |
5'b11001 : |
reg_rs_o = reg_r25; |
5'b11010 : |
reg_rs_o = reg_k0; |
5'b11011 : |
reg_rs_o = reg_k1; |
5'b11100 : |
reg_rs_o = reg_gp; |
5'b11101 : |
reg_rs_o = reg_sp; |
5'b11110 : |
reg_rs_o = reg_fp; |
5'b11111 : |
reg_rs_o = reg_ra; |
default : |
reg_rs_o = 32'h00000000; |
endcase |
|
case (rt_i) |
5'b00000 : |
reg_rt_o = 32'h00000000; |
5'b00001 : |
reg_rt_o = reg_r1_at; |
5'b00010 : |
reg_rt_o = reg_r2_v0; |
5'b00011 : |
reg_rt_o = reg_r3_v1; |
5'b00100 : |
reg_rt_o = reg_r4_a0; |
5'b00101 : |
reg_rt_o = reg_r5_a1; |
5'b00110 : |
reg_rt_o = reg_r6_a2; |
5'b00111 : |
reg_rt_o = reg_r7_a3; |
5'b01000 : |
reg_rt_o = reg_r8; |
5'b01001 : |
reg_rt_o = reg_r9; |
5'b01010 : |
reg_rt_o = reg_r10; |
5'b01011 : |
reg_rt_o = reg_r11; |
5'b01100 : |
reg_rt_o = reg_r12; |
5'b01101 : |
reg_rt_o = reg_r13; |
5'b01110 : |
reg_rt_o = reg_r14; |
5'b01111 : |
reg_rt_o = reg_r15; |
5'b10000 : |
reg_rt_o = reg_r16; |
5'b10001 : |
reg_rt_o = reg_r17; |
5'b10010 : |
reg_rt_o = reg_r18; |
5'b10011 : |
reg_rt_o = reg_r19; |
5'b10100 : |
reg_rt_o = reg_r20; |
5'b10101 : |
reg_rt_o = reg_r21; |
5'b10110 : |
reg_rt_o = reg_r22; |
5'b10111 : |
reg_rt_o = reg_r23; |
5'b11000 : |
reg_rt_o = reg_r24; |
5'b11001 : |
reg_rt_o = reg_r25; |
5'b11010 : |
reg_rt_o = reg_k0; |
5'b11011 : |
reg_rt_o = reg_k1; |
5'b11100 : |
reg_rt_o = reg_gp; |
5'b11101 : |
reg_rt_o = reg_sp; |
5'b11110 : |
reg_rt_o = reg_fp; |
5'b11111 : |
reg_rt_o = reg_ra; |
default : |
reg_rt_o = 32'h00000000; |
endcase |
end |
|
endmodule |
/soc/uart.v
0,0 → 1,284
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module: |
//----------------------------------------------------------------- |
module uart |
( |
// Clock & Reset |
clk_i, |
rst_i, |
// Status |
tx_busy_o, |
rx_ready_o, |
// Data |
data_i, |
wr_i, |
data_o, |
rd_i, |
// UART pins |
rxd_i, |
txd_o |
); |
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] UART_DIVISOR = 278; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input [7:0] data_i /*verilator public*/; |
output [7:0] data_o /*verilator public*/; |
input wr_i /*verilator public*/; |
input rd_i /*verilator public*/; |
output tx_busy_o /*verilator public*/; |
output rx_ready_o /*verilator public*/; |
input rxd_i /*verilator public*/; |
output txd_o /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
parameter FULL_BIT = UART_DIVISOR; |
parameter HALF_BIT = (FULL_BIT / 2); |
|
// TX Signals |
reg [7:0] tx_buf; |
reg tx_buf_full; |
reg tx_busy; |
reg [3:0] tx_bits; |
integer tx_count; |
reg [7:0] tx_shift_reg; |
reg txd_o; |
|
// RX Signals |
reg i_rxd; |
reg [7:0] data_o; |
reg [3:0] rx_bits; |
integer rx_count; |
reg [7:0] rx_shift_reg; |
reg rx_ready_o; |
|
//----------------------------------------------------------------- |
// Re-sync RXD |
//----------------------------------------------------------------- |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
i_rxd <= 1'b1; |
else |
i_rxd <= rxd_i; |
end |
|
//----------------------------------------------------------------- |
// RX Process |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i ) |
begin |
if (rst_i == 1'b1) |
begin |
rx_bits <= 0; |
rx_count <= 0; |
rx_ready_o <= 1'b0; |
rx_shift_reg <= 8'h00; |
data_o <= 8'h00; |
end |
else |
begin |
|
// If reading data, reset data ready state |
if (rd_i == 1'b1) |
rx_ready_o <= 1'b0; |
|
// Rx bit timer |
if (rx_count != 0) |
rx_count <= (rx_count - 1); |
else |
begin |
//------------------------------- |
// Start bit detection |
//------------------------------- |
if (rx_bits == 0) |
begin |
// If RXD low, check again in half bit time |
if (i_rxd == 1'b0) |
begin |
rx_count <= HALF_BIT; |
rx_bits <= 1; |
end |
end |
//------------------------------- |
// Start bit (mid bit time point) |
//------------------------------- |
else if (rx_bits == 1) |
begin |
// RXD should still be low at mid point of bit period |
if (i_rxd == 1'b0) |
begin |
rx_count <= FULL_BIT; |
rx_bits <= (rx_bits + 1); |
rx_shift_reg <= 8'h00; |
end |
// Start bit not still low, reset RX process |
else |
begin |
rx_bits <= 0; |
end |
end |
//------------------------------- |
// Stop bit |
//------------------------------- |
else if (rx_bits == 10) |
begin |
// RXD should be still high |
if (i_rxd == 1'b1) |
begin |
rx_count <= 0; |
rx_bits <= 0; |
data_o <= rx_shift_reg; |
rx_ready_o <= 1'b1; |
end |
// Bad Stop bit - wait for a full bit period |
// before allowing start bit detection again |
else |
begin |
rx_count <= FULL_BIT; |
rx_bits <= 0; |
end |
end |
//------------------------------- |
// Data bits |
//------------------------------- |
else |
begin |
// Receive data LSB first |
rx_shift_reg[7] <= i_rxd; |
rx_shift_reg[6:0]<= rx_shift_reg[7:1]; |
rx_count <= FULL_BIT; |
rx_bits <= (rx_bits + 1); |
end |
end |
end |
end |
|
//----------------------------------------------------------------- |
// TX Process |
//----------------------------------------------------------------- |
always @ (posedge clk_i or posedge rst_i ) |
begin |
if (rst_i == 1'b1) |
begin |
tx_count <= 0; |
tx_bits <= 0; |
tx_busy <= 1'b0; |
txd_o <= 1'b1; |
tx_shift_reg <= 8'h00; |
tx_buf <= 8'h00; |
tx_buf_full <= 1'b0; |
end |
else |
begin |
|
// Buffer data to transmit |
if (wr_i == 1'b1) |
begin |
tx_buf <= data_i; |
tx_buf_full <= 1'b1; |
end |
|
// Tx bit timer |
if (tx_count != 0) |
tx_count <= (tx_count - 1); |
else |
begin |
|
//------------------------------- |
// Start bit (TXD = L) |
//------------------------------- |
if (tx_bits == 0) |
begin |
|
tx_busy <= 1'b0; |
|
// Data in buffer ready to transmit? |
if (tx_buf_full == 1'b1) |
begin |
tx_shift_reg <= tx_buf; |
tx_busy <= 1'b1; |
txd_o <= 1'b0; |
tx_buf_full <= 1'b0; |
tx_bits <= 1; |
tx_count <= FULL_BIT; |
end |
end |
//------------------------------- |
// Stop bit (TXD = H) |
//------------------------------- |
else if (tx_bits == 9) |
begin |
txd_o <= 1'b1; |
tx_bits <= 0; |
tx_count <= FULL_BIT; |
end |
//------------------------------- |
// Data bits |
//------------------------------- |
else |
begin |
// Shift data out LSB first |
txd_o <= tx_shift_reg[0]; |
tx_shift_reg[6:0]<= tx_shift_reg[7:1]; |
tx_bits <= (tx_bits + 1); |
tx_count <= FULL_BIT; |
end |
end |
end |
end |
|
//----------------------------------------------------------------- |
// Combinatorial |
//----------------------------------------------------------------- |
assign tx_busy_o = (tx_busy | tx_buf_full | wr_i); |
|
endmodule |
/soc/mpx_soc.v
0,0 → 1,528
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Includes |
//----------------------------------------------------------------- |
`include "mpx_soc_defs.v" |
|
//----------------------------------------------------------------- |
// Module: |
//----------------------------------------------------------------- |
module mpx_soc |
( |
// General - Clocking & Reset |
clk_i, |
rst_i, |
en_i, |
ext_intr_i, |
fault_o, |
|
// UART |
uart_tx_o, |
uart_rx_i, |
|
// Memory |
int_mem_addr_o, |
int_mem_data_o, |
int_mem_data_i, |
int_mem_wr_o, |
int_mem_rd_o, |
|
// External IO |
ext_io_addr_o, |
ext_io_data_o, |
ext_io_data_i, |
ext_io_wr_o, |
ext_io_rd_o, |
ext_io_pause_i, |
|
// Debug Register Access |
dbg_reg_addr_i, |
dbg_reg_out_o, |
dbg_pc_o, |
|
// Debug UART output |
dbg_uart_data_o, |
dbg_uart_wr_o |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] CLK_KHZ = 12288; |
parameter [31:0] UART_BAUD = 115200; |
parameter [31:0] EXTERNAL_INTERRUPTS = 1; |
parameter CORE_ID = 0; |
parameter BOOT_VECTOR = 0; |
parameter ISR_VECTOR = 0; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
input rst_i /*verilator public*/; |
input en_i /*verilator public*/; |
output fault_o /*verilator public*/; |
input [(EXTERNAL_INTERRUPTS - 1):0] ext_intr_i /*verilator public*/; |
output uart_tx_o /*verilator public*/; |
input uart_rx_i /*verilator public*/; |
output [31:0] int_mem_addr_o /*verilator public*/; |
output [31:0] int_mem_data_o /*verilator public*/; |
input [31:0] int_mem_data_i /*verilator public*/; |
output [3:0] int_mem_wr_o /*verilator public*/; |
output int_mem_rd_o /*verilator public*/; |
output [31:0] ext_io_addr_o /*verilator public*/; |
output [31:0] ext_io_data_o /*verilator public*/; |
input [31:0] ext_io_data_i /*verilator public*/; |
output [3:0] ext_io_wr_o /*verilator public*/; |
output ext_io_rd_o /*verilator public*/; |
input ext_io_pause_i /*verilator public*/; |
input [8:0] dbg_reg_addr_i /*verilator public*/; |
output [31:0] dbg_reg_out_o /*verilator public*/; |
output [31:0] dbg_pc_o /*verilator public*/; |
output [7:0] dbg_uart_data_o /*verilator public*/; |
output dbg_uart_wr_o /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [31:0] v_irq_status; |
reg [2:0] r_mem_sel; |
|
wire [31:0] cpu_address; |
wire [3:0] cpu_byte_we; |
wire cpu_oe; |
wire [31:0] cpu_data_w; |
reg [31:0] cpu_data_r; |
reg cpu_pause; |
|
reg [31:0] io_address; |
reg [31:0] io_data_w; |
reg [31:0] io_data_r; |
reg [3:0] io_wr; |
reg io_rd; |
|
// UART |
reg [7:0] uart_tx_data; |
wire [7:0] uart_rx_data; |
reg uart_wr; |
reg uart_rd; |
wire uart_tx_busy; |
wire uart_rx_avail; |
|
// Systick Timer |
reg systick_intr; |
reg [31:0] systick_count; |
reg [31:0] systick_clk_count; |
|
// Hi-res system clock tick counter |
reg [31:0] hr_timer_cnt; |
reg [31:0] hr_timer_match; |
|
// IRQ Status |
wire intr_in; |
reg [31:0] irq_status; |
reg [31:0] irq_mask; |
|
// Output Signals |
wire uart_tx_o; |
reg [31:0] int_mem_addr_o; |
reg [31:0] int_mem_data_o; |
reg [3:0] int_mem_wr_o; |
reg int_mem_rd_o; |
reg [31:0] ext_io_addr_o; |
reg [31:0] ext_io_data_o; |
reg [3:0] ext_io_wr_o; |
reg ext_io_rd_o; |
|
|
//----------------------------------------------------------------- |
// Instantiation |
//----------------------------------------------------------------- |
|
// MPX CPU |
mpx |
#( |
.BOOT_VECTOR(BOOT_VECTOR), |
.ISR_VECTOR(ISR_VECTOR) |
) |
u1_cpu |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
.en_i(en_i), |
.intr_i(intr_in), |
.step_done_o(/*open */), |
.fault_o(fault_o), |
.mem_addr_o(cpu_address), |
.mem_data_out_o(cpu_data_w), |
.mem_data_in_i(cpu_data_r), |
.mem_wr_o(cpu_byte_we), |
.mem_rd_o(cpu_oe), |
.mem_pause_i(cpu_pause), |
.dbg_reg_addr_i(dbg_reg_addr_i), |
.dbg_reg_out_o(dbg_reg_out_o), |
.dbg_pc_o(dbg_pc_o) |
); |
|
// UART |
uart |
#( |
.UART_DIVISOR(((CLK_KHZ * 1000) / UART_BAUD)) |
) |
u3_uart |
( |
.clk_i(clk_i), |
.rst_i(rst_i), |
.data_i(uart_tx_data), |
.data_o(uart_rx_data), |
.wr_i(uart_wr), |
.rd_i(uart_rd), |
.tx_busy_o(uart_tx_busy), |
.rx_ready_o(uart_rx_avail), |
.rxd_i(uart_rx_i), |
.txd_o(uart_tx_o) |
); |
|
//----------------------------------------------------------------- |
// I/O Handlers |
//----------------------------------------------------------------- |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
// UART |
uart_tx_data <= 8'h00; |
uart_wr <= 1'b0; |
|
// Interrupt Status |
irq_status <= 32'h00000000; |
irq_mask <= 32'h00000000; |
hr_timer_cnt <= 32'h00000000; |
hr_timer_match <= 32'h00000000; |
|
end |
else |
begin |
|
uart_wr <= 1'b0; |
|
// Get current IRQ status |
v_irq_status = irq_status; |
|
// Clock tick counter |
hr_timer_cnt <= (hr_timer_cnt + 1); |
|
// Systick IRQ? |
if (systick_intr == 1'b1) |
v_irq_status[`IRQ_SYSTICK] = 1'b1; |
|
// UART IRQ? |
if (uart_rx_avail == 1'b1) |
v_irq_status[`IRQ_UART_RX_AVAIL] = 1'b1; |
|
// Hi-res Timer IRQ [IRQ6] |
if ((hr_timer_match != 32'h00000000) && (hr_timer_match == hr_timer_cnt)) |
v_irq_status[`IRQ_PIT] = 1'b1; |
|
// External interrupts |
begin : ext_ints_loop |
integer i; |
for (i=0; i< EXTERNAL_INTERRUPTS; i=i+1) |
begin |
if (ext_intr_i[i] == 1'b1) |
v_irq_status[(`IRQ_EXT_FIRST + i)] = 1'b1; |
end |
end |
|
// Update IRQ status |
irq_status <= v_irq_status; |
|
// IO Write Cycle |
if (io_wr != 4'b0000) |
case (io_address[7:0]) |
|
`UART_UDR : |
begin |
uart_tx_data <= io_data_w[7:0]; |
uart_wr <= 1'b1; |
end |
|
`IRQ_MASK_SET : |
irq_mask <= (irq_mask | io_data_w); |
|
`IRQ_MASK_CLR : |
irq_mask <= (irq_mask & ~ (io_data_w)); |
|
`IRQ_STATUS : // (IRQ Acknowledge) |
irq_status <= (v_irq_status & ~ (io_data_w)); |
|
`SYS_CLK_COUNT : |
hr_timer_match <= io_data_w; |
|
default : |
; |
endcase |
end |
end |
|
// IO memory space READ handler |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
io_data_r <= 32'h00000000; |
uart_rd <= 1'b0; |
end |
else |
begin |
uart_rd <= 1'b0; |
|
// Read cycle? |
if (io_rd == 1'b1) |
case (io_address[7:0]) |
|
`CORE_ID : |
io_data_r <= CORE_ID; |
|
`UART_USR : |
io_data_r <= {27'h0000000, 1'b0, uart_tx_busy, 1'b0, 1'b0, uart_rx_avail}; |
|
`UART_UDR : |
begin |
io_data_r <= {24'h000000,uart_rx_data}; |
uart_rd <= 1'b1; |
end |
|
`TIMER_VAL : // (32-bit 1ms counter) |
io_data_r <= systick_count; |
|
`IRQ_MASK_SET : |
io_data_r <= irq_mask; |
|
`IRQ_MASK_CLR : |
io_data_r <= irq_mask; |
|
`IRQ_STATUS : |
io_data_r <= (irq_status & irq_mask); |
|
`SYS_CLK_COUNT : |
io_data_r <= hr_timer_cnt; |
|
default : |
io_data_r <= 32'h00000000; |
endcase |
end |
end |
|
// SysTick Timer (1 ms resolution) |
always @ (posedge rst_i or posedge clk_i ) |
begin |
if (rst_i == 1'b1) |
begin |
systick_count <= 32'h00000000; |
systick_clk_count <= 32'h00000000; |
systick_intr <= 1'b0; |
end |
else |
begin |
systick_intr <= 1'b0; |
|
if (systick_clk_count == CLK_KHZ) |
begin |
systick_count <= (systick_count + 1); |
systick_intr <= 1'b1; |
systick_clk_count <= 32'h00000000; |
end |
else |
systick_clk_count <= (systick_clk_count + 1); |
end |
end |
|
//----------------------------------------------------------------- |
// Memory Map |
//----------------------------------------------------------------- |
always @ (cpu_address or cpu_byte_we or cpu_oe or cpu_data_w ) |
begin |
case (cpu_address[30:28]) |
|
// Memory |
`MEM_REGION_INTERNAL : |
begin |
int_mem_addr_o = cpu_address; |
int_mem_wr_o = cpu_byte_we; |
int_mem_rd_o = cpu_oe; |
int_mem_data_o = cpu_data_w; |
|
io_address = 32'h00000000; |
io_wr = 4'b0000; |
io_rd = 1'b0; |
io_data_w = 32'h00000000; |
|
ext_io_addr_o = 32'h00000000; |
ext_io_wr_o = 4'b0000; |
ext_io_rd_o = 1'b0; |
ext_io_data_o = 32'h00000000; |
end |
|
// Core I/O peripherals |
`MEM_REGION_CORE_IO : |
begin |
io_address = cpu_address; |
io_wr = cpu_byte_we; |
io_rd = cpu_oe; |
io_data_w = cpu_data_w; |
|
int_mem_addr_o = 32'h00000000; |
int_mem_wr_o = 4'b0000; |
int_mem_rd_o = 1'b0; |
int_mem_data_o = 32'h00000000; |
|
ext_io_addr_o = 32'h00000000; |
ext_io_wr_o = 4'b0000; |
ext_io_rd_o = 1'b0; |
ext_io_data_o = 32'h00000000; |
end |
|
// Extended I/O peripherals |
`MEM_REGION_EXT_IO : |
begin |
ext_io_addr_o = cpu_address; |
ext_io_wr_o = cpu_byte_we; |
ext_io_rd_o = cpu_oe; |
ext_io_data_o = cpu_data_w; |
|
int_mem_addr_o = 32'h00000000; |
int_mem_wr_o = 4'b0000; |
int_mem_rd_o = 1'b0; |
int_mem_data_o = 32'h00000000; |
|
io_address = 32'h00000000; |
io_wr = 4'b0000; |
io_rd = 1'b0; |
io_data_w = 32'h00000000; |
end |
|
default : |
begin |
io_address = 32'h00000000; |
io_wr = 4'b0000; |
io_rd = 1'b0; |
io_data_w = 32'h00000000; |
|
int_mem_addr_o = 32'h00000000; |
int_mem_wr_o = 4'b0000; |
int_mem_rd_o = 1'b0; |
int_mem_data_o = 32'h00000000; |
|
ext_io_addr_o = 32'h00000000; |
ext_io_wr_o = 4'b0000; |
ext_io_rd_o = 1'b0; |
ext_io_data_o = 32'h00000000; |
end |
endcase |
end |
|
//----------------------------------------------------------------- |
// Read Port |
//----------------------------------------------------------------- |
always @ (r_mem_sel or int_mem_data_i or io_data_r or ext_io_data_i) |
begin |
case (r_mem_sel) |
|
// Memory |
`MEM_REGION_INTERNAL : |
begin |
cpu_data_r = int_mem_data_i; |
cpu_pause = 1'b0; |
end |
|
// Core I/O peripherals |
`MEM_REGION_CORE_IO : |
begin |
cpu_data_r = io_data_r; |
cpu_pause = 1'b0; |
end |
|
// Extended I/O peripherals |
`MEM_REGION_EXT_IO : |
begin |
cpu_data_r = ext_io_data_i; |
cpu_pause = 1'b0; |
end |
|
default : |
begin |
cpu_data_r = 32'h00000000; |
cpu_pause = 1'b0; |
end |
endcase |
end |
|
//----------------------------------------------------------------- |
// Registered device select |
//----------------------------------------------------------------- |
reg [31:0] v_mem_sel; |
|
always @ (posedge clk_i or posedge rst_i ) |
begin |
if (rst_i == 1'b1) |
begin |
v_mem_sel = BOOT_VECTOR; |
r_mem_sel <= v_mem_sel[30:28]; |
end |
else |
r_mem_sel <= cpu_address[30:28]; |
end |
|
//----------------------------------------------------------------- |
// Combinatorial Logic |
//----------------------------------------------------------------- |
assign intr_in = ((irq_mask & irq_status) != 32'h00000000) ? 1'b1 : 1'b0; |
|
//----------------------------------------------------------------- |
// External Interface |
//----------------------------------------------------------------- |
// Debug UART |
assign dbg_uart_data_o = uart_tx_data; |
assign dbg_uart_wr_o = uart_wr; |
|
endmodule |
/soc/mpx_soc_defs.v
0,0 → 1,70
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Memory Map |
//----------------------------------------------------------------- |
`define MEM_REGION_INTERNAL 3'b001 |
`define MEM_REGION_CORE_IO 3'b010 |
`define MEM_REGION_EXT_IO 3'b011 |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
|
// General |
`define CORE_ID 8'h00 |
|
// Basic Peripherals |
`define UART_USR 8'h04 |
`define UART_UDR 8'h08 |
`define TIMER_VAL 8'h10 |
`define IRQ_MASK_SET 8'h14 |
`define IRQ_MASK_STATUS 8'h14 |
`define IRQ_MASK_CLR 8'h18 |
`define IRQ_STATUS 8'h1C |
`define IRQ_SYSTICK (0) |
`define IRQ_UART_RX_AVAIL (1) |
`define IRQ_SW (2) |
`define IRQ_PIT (6) |
`define IRQ_EXT_FIRST (8) |
|
`define SYS_CLK_COUNT 8'h60 |
|
/sim/main.cpp
0,0 → 1,119
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
#include <stdio.h> |
#include <unistd.h> |
|
#include "mpx_top.h" |
#include "verilated.h" |
|
//----------------------------------------------------------------- |
// Defines |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Locals |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// main |
//----------------------------------------------------------------- |
int main(int argc, char **argv, char **env) |
{ |
FILE *f; |
char *filename; |
int err; |
|
Verilated::commandArgs(argc, argv); |
|
mpx_test_init(); |
|
if (argc <= 1) |
{ |
argc = 2; |
filename = (char*)".\\test.bin"; |
} |
else |
filename = argv[1]; |
|
printf("Opening %s\n", filename); |
f = fopen(filename, "rb"); |
if (f) |
{ |
long size; |
char *buf; |
|
// Get size |
fseek(f, 0, SEEK_END); |
size = ftell(f); |
rewind(f); |
|
buf = (char*)malloc(size+1); |
if (buf) |
{ |
unsigned int addr; |
|
// Read file data in |
int len = fread(buf, 1, size, f); |
buf[len] = 0; |
|
for (addr=0;addr<len;addr++) |
mpx_test_load(addr, buf[addr]); |
|
free(buf); |
fclose(f); |
} |
} |
else |
{ |
printf("No file to execute!\n"); |
return 0; |
} |
|
// Run |
err = mpx_test_run(-1); |
|
if (err == MPX_RUN_RES_FAULT) |
printf("FAULT PC %x!\n", mpx_test_getpc()); |
|
mpx_test_done(); |
|
printf("Exit\n"); |
exit(0); |
} |
/sim/sram.v
0,0 → 1,90
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
|
//----------------------------------------------------------------- |
// Module |
//----------------------------------------------------------------- |
module sram |
( |
clk_i, |
adr_i, |
dat_i, |
wr_i, |
dat_o |
); |
|
//----------------------------------------------------------------- |
// Params |
//----------------------------------------------------------------- |
parameter [31:0] WIDTH = 8; |
parameter [31:0] SIZE = 14; |
|
//----------------------------------------------------------------- |
// I/O |
//----------------------------------------------------------------- |
input clk_i /*verilator public*/; |
output [(WIDTH - 1):0] dat_o /*verilator public*/; |
input [(WIDTH - 1):0] dat_i /*verilator public*/; |
input [(SIZE - 1):0] adr_i /*verilator public*/; |
input wr_i /*verilator public*/; |
|
//----------------------------------------------------------------- |
// Registers |
//----------------------------------------------------------------- |
reg [(WIDTH - 1):0] ram [((2<< (SIZE-1)) - 1):0] /*verilator public*/; |
reg [(SIZE - 1):0] rd_addr; |
wire [(WIDTH - 1):0] dat_o; |
|
//----------------------------------------------------------------- |
// Processes |
//----------------------------------------------------------------- |
always @ (posedge clk_i) |
begin |
if (wr_i == 1'b1) |
ram[adr_i] <= dat_i; |
rd_addr <= adr_i; |
end |
|
//------------------------------------------------------------------- |
// Combinatorial |
//------------------------------------------------------------------- |
assign dat_o = ram[rd_addr]; |
|
endmodule |
/sim/mpx_top.cpp
0,0 → 1,257
//----------------------------------------------------------------- |
// MPX 32-bit Soft-Core Processor |
// V0.1 |
// Ultra-Embedded.com |
// Copyright 2011 - 2012 |
// |
// Email: admin@ultra-embedded.com |
// |
// License: LGPL |
// |
// If you would like a version with a different license for use |
// in commercial projects please contact the above email address |
// for more details. |
//----------------------------------------------------------------- |
// |
// Copyright (C) 2011 - 2012 Ultra-Embedded.com |
// |
// This source file may be used and distributed without |
// restriction provided that this copyright statement is not |
// removed from the file and that any derivative work contains |
// the original copyright notice and the associated disclaimer. |
// |
// This source file is free software; you can redistribute it |
// and/or modify it under the terms of the GNU Lesser General |
// Public License as published by the Free Software Foundation; |
// either version 2.1 of the License, or (at your option) any |
// later version. |
// |
// This source is distributed in the hope that it will be |
// useful, but WITHOUT ANY WARRANTY; without even the implied |
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
// PURPOSE. See the GNU Lesser General Public License for more |
// details. |
// |
// You should have received a copy of the GNU Lesser General |
// Public License along with this source; if not, write to the |
// Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
// Boston, MA 02111-1307 USA |
//----------------------------------------------------------------- |
#include <stdio.h> |
#include <unistd.h> |
#include <math.h> |
#include <time.h> |
|
#include "mpx_top.h" |
|
#include "Vmpx_top.h" |
#include "Vmpx_top_mpx_top.h" |
#include "Vmpx_top_sram4__S13.h" |
#include "Vmpx_top_sram__S13.h" |
#include "verilated.h" |
|
#if VM_TRACE |
#include <verilated_vcd_c.h> |
#endif |
|
//----------------------------------------------------------------- |
// Defines |
//----------------------------------------------------------------- |
#define MEMORY_SIZE (512 * 1024) |
|
//----------------------------------------------------------------- |
// Locals |
//----------------------------------------------------------------- |
static Vmpx_top *top; |
static unsigned int _stop_pc = 0xFFFFFFFF; |
|
#if VM_TRACE |
static unsigned int main_time = 0; |
static VerilatedVcdC* tfp; |
#endif |
|
//----------------------------------------------------------------- |
// mpx_test_init |
//----------------------------------------------------------------- |
int mpx_test_init(void) |
{ |
top = new Vmpx_top(); |
|
#if VM_TRACE |
// If verilator was invoked with --trace |
Verilated::traceEverOn(true); |
VL_PRINTF("Enabling GTKWave Trace Output...\n"); |
tfp = new VerilatedVcdC; |
top->trace (tfp, 99); |
tfp->open ("wave_dump.vcd"); |
#endif |
|
// Initial |
top->clk_i = 0; |
top->rst_i = 1; |
top->en_i = 1; |
top->intr_i = 0; |
top->dbg_reg_addr_i = 0; |
top->eval(); |
|
// Reset |
top->clk_i = 1; |
top->rst_i = 1; |
top->eval(); |
|
top->clk_i = 0; |
top->rst_i = 0; |
top->eval(); |
|
return 0; |
} |
//----------------------------------------------------------------- |
// mpx_test_load |
//----------------------------------------------------------------- |
int mpx_test_load(unsigned int addr, unsigned char val) |
{ |
if (addr >= MEMORY_SIZE) |
return -1; |
|
switch (addr & 0x3) |
{ |
case 0: |
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__3__KET____DOT__u1_bram->ram[addr >> 2] = val; |
break; |
case 1: |
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__2__KET____DOT__u1_bram->ram[addr >> 2] = val; |
break; |
case 2: |
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__1__KET____DOT__u1_bram->ram[addr >> 2] = val; |
break; |
case 3: |
top->v->u1_bram->sram_gen__DOT__sram_loop__BRA__0__KET____DOT__u1_bram->ram[addr >> 2] = val; |
break; |
} |
|
return 0; |
} |
//----------------------------------------------------------------- |
// mpx_test_setbreakpoint |
//----------------------------------------------------------------- |
int mpx_test_setbreakpoint(int bp, unsigned int pc) |
{ |
if (bp != 0) |
return -1; |
else |
{ |
_stop_pc = pc; |
return 0; |
} |
} |
//----------------------------------------------------------------- |
// mpx_test_run |
//----------------------------------------------------------------- |
int mpx_test_run(int cycles) |
{ |
int current_cycle = 0; |
unsigned int last_pc = top->dbg_pc_o; |
|
// Run until fault or number of cycles completed |
while (!Verilated::gotFinish() && !top->fault_o && (current_cycle < cycles || cycles == -1)) |
{ |
// CLK->L |
top->clk_i = 0; |
top->eval(); |
|
#if VM_TRACE |
if (tfp) tfp->dump (main_time++); |
#endif |
|
// CLK->H |
top->clk_i = 1; |
top->eval(); |
|
#if VM_TRACE |
if (tfp) tfp->dump (main_time++); |
#endif |
|
if (top->uart_wr_o) |
printf("%c", top->uart_data_o); |
|
if (last_pc != top->dbg_pc_o) |
{ |
last_pc = top->dbg_pc_o; |
current_cycle++; |
} |
|
if (_stop_pc == top->dbg_pc_o) |
break; |
} |
|
// Fault |
if (top->fault_o) |
return MPX_RUN_RES_FAULT; |
// Number of cycles reached |
else if (current_cycle >= cycles) |
return MPX_RUN_RES_MAX_CYCLES; |
// Breakpoint hit |
else if (_stop_pc == top->dbg_pc_o) |
return MPX_RUN_RES_BREAKPOINT; |
// No error |
else |
return MPX_RUN_RES_OK; |
} |
//----------------------------------------------------------------- |
// mpx_test_reset |
//----------------------------------------------------------------- |
void mpx_test_reset(void) |
{ |
// Reset = H |
top->rst_i = 1; |
|
// Clock |
top->clk_i = 1; |
top->eval(); |
top->clk_i = 0; |
top->eval(); |
|
// Reset = L |
top->rst_i = 0; |
top->eval(); |
} |
//----------------------------------------------------------------- |
// mpx_test_getreg |
//----------------------------------------------------------------- |
unsigned int mpx_test_getreg(int reg) |
{ |
top->en_i = 0; |
|
top->dbg_reg_addr_i = reg; |
|
// Clock |
top->clk_i = 1; |
top->eval(); |
top->clk_i = 0; |
top->eval(); |
|
top->en_i = 1; |
|
return top->dbg_reg_out_o; |
} |
//----------------------------------------------------------------- |
// mpx_test_reset |
//----------------------------------------------------------------- |
unsigned int mpx_test_getpc(void) |
{ |
return top->dbg_pc_o; |
} |
//----------------------------------------------------------------- |
// mpx_test_done |
//----------------------------------------------------------------- |
void mpx_test_done(void) |
{ |
top->final(); |
#if VM_TRACE |
if (tfp) |
{ |
tfp->close(); |
tfp = NULL; |
} |
#endif |
} |
/sim/run_mpx
0,0 → 1,4
rm ./obj_dir/* |
verilator --cc mpx_top.v main.cpp mpx_top.cpp -I../mpx -I../soc +define+CONF_MPX_TARGET_SIM+ --exe $2 |
make -j -f Vmpx_top.mk -C ./obj_dir/ |
./obj_dir/Vmpx_top $1 |
/sim/test_image.bin
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
sim/test_image.bin
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: sim/mpx_top.v
===================================================================
--- sim/mpx_top.v (nonexistent)
+++ sim/mpx_top.v (revision 2)
@@ -0,0 +1,161 @@
+//-----------------------------------------------------------------
+// MPX 32-bit Soft-Core Processor
+// V0.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2012
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//
+// If you would like a version with a different license for use
+// in commercial projects please contact the above email address
+// for more details.
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2012 Ultra-Embedded.com
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// Module
+//-----------------------------------------------------------------
+module mpx_top
+(
+ // Clocking & Reset
+ clk_i,
+ rst_i,
+ // Global Enable
+ en_i,
+ // Fault Output
+ fault_o,
+ // Interrupt Input
+ intr_i,
+ // Debug Register Access
+ dbg_reg_addr_i,
+ dbg_reg_out_o,
+ dbg_pc_o,
+ // UART output
+ uart_data_o,
+ uart_wr_o
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter CLK_KHZ = (8192*7);
+parameter SRAM_ADDR_WIDTH = 19;
+
+//-----------------------------------------------------------------
+// I/O
+//-----------------------------------------------------------------
+input clk_i /*verilator public*/;
+input rst_i /*verilator public*/;
+input en_i /*verilator public*/;
+output fault_o /*verilator public*/;
+input intr_i /*verilator public*/;
+input [8:0] dbg_reg_addr_i /*verilator public*/;
+output [31:0] dbg_reg_out_o /*verilator public*/;
+output [31:0] dbg_pc_o /*verilator public*/;
+output [7:0] uart_data_o /*verilator public*/;
+output uart_wr_o /*verilator public*/;
+
+//-----------------------------------------------------------------
+// Registers / Wires
+//-----------------------------------------------------------------
+wire fault_o;
+wire [31:0] dbg_reg_out_o;
+wire [31:0] dbg_pc_o;
+wire [7:0] uart_data_o;
+wire uart_wr_o;
+wire [31:0] int_mem_addr_o;
+wire [31:0] int_mem_data_o;
+wire [31:0] int_mem_data_i;
+wire [3:0] int_mem_wr_o;
+
+//-----------------------------------------------------------------
+// Instantiation
+//-----------------------------------------------------------------
+
+sram4
+#(
+ .SRAM_ADDR_WIDTH(SRAM_ADDR_WIDTH)
+)
+u1_bram
+(
+ .clk_i(clk_i),
+ .address_i(int_mem_addr_o),
+ .data_i(int_mem_data_o),
+ .data_o(int_mem_data_i),
+ .wr_i(int_mem_wr_o)
+);
+
+mpx_soc
+#(
+ .CLK_KHZ(CLK_KHZ),
+ .UART_BAUD(115200),
+ .EXTERNAL_INTERRUPTS(1),
+ .CORE_ID(32'h00000000),
+ .BOOT_VECTOR(32'h10000000),
+ .ISR_VECTOR(32'h1000003C)
+)
+u1_cpu
+(
+ // Clock / Status
+ .clk_i(clk_i),
+ .rst_i(rst_i),
+ .en_i(en_i),
+ .ext_intr_i(intr_i),
+ .fault_o(fault_o),
+
+ // UART
+ .uart_tx_o(/* open */),
+ .uart_rx_i(1'b0),
+
+ // Internal Memory
+ .int_mem_addr_o(int_mem_addr_o),
+ .int_mem_data_o(int_mem_data_o),
+ .int_mem_data_i(int_mem_data_i),
+ .int_mem_wr_o(int_mem_wr_o),
+ .int_mem_rd_o(/*open */),
+
+ // External I/O or Memory
+ .ext_io_addr_o(/*open */),
+ .ext_io_data_o(/*open */),
+ .ext_io_data_i(32'h00000000),
+ .ext_io_wr_o(/*open */),
+ .ext_io_rd_o(/*open */),
+ .ext_io_pause_i(1'b0),
+
+ // Debug Register Access
+ .dbg_reg_addr_i(dbg_reg_addr_i),
+ .dbg_reg_out_o(dbg_reg_out_o),
+ .dbg_pc_o(dbg_pc_o),
+
+ // Debug UART output
+ .dbg_uart_data_o(uart_data_o),
+ .dbg_uart_wr_o(uart_wr_o)
+);
+
+endmodule
Index: sim/sram4.v
===================================================================
--- sim/sram4.v (nonexistent)
+++ sim/sram4.v (revision 2)
@@ -0,0 +1,100 @@
+//-----------------------------------------------------------------
+// MPX 32-bit Soft-Core Processor
+// V0.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2012
+//
+// Email: admin@ultra-embedded.com
+//
+// License: LGPL
+//
+// If you would like a version with a different license for use
+// in commercial projects please contact the above email address
+// for more details.
+//-----------------------------------------------------------------
+//
+// Copyright (C) 2011 - 2012 Ultra-Embedded.com
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be
+// useful, but WITHOUT ANY WARRANTY; without even the implied
+// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+// Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// Module
+//-----------------------------------------------------------------
+module sram4
+(
+ clk_i,
+ address_i,
+ data_i,
+ data_o,
+ wr_i
+);
+
+//-----------------------------------------------------------------
+// Params
+//-----------------------------------------------------------------
+parameter [31:0] SRAM_ADDR_WIDTH = 14;
+
+//-----------------------------------------------------------------
+// I/O
+//-----------------------------------------------------------------
+input clk_i /*verilator public*/;
+input [31:0] address_i /*verilator public*/;
+input [31:0] data_i /*verilator public*/;
+output [31:0] data_o /*verilator public*/;
+input [3:0] wr_i /*verilator public*/;
+
+//-----------------------------------------------------------------
+// Registers
+//-----------------------------------------------------------------
+wire [31:0] address;
+wire [31:0] data_o;
+
+//-----------------------------------------------------------------
+// Implementation
+//-----------------------------------------------------------------
+assign {address} = {2'b00, address_i[31:2]};
+
+generate
+begin : sram_gen
+genvar i;
+for (i=0;i<4;i=i+1)
+ begin :sram_loop
+ sram
+ #(
+ .WIDTH(8),
+ .SIZE(SRAM_ADDR_WIDTH)
+ )
+ u1_bram
+ (
+ .clk_i(clk_i),
+ .dat_o(data_o[(((i + 1) * 8) - 1):(i * 8)]),
+ .dat_i(data_i[(((i + 1) * 8) - 1):(i * 8)]),
+ .adr_i(address[(SRAM_ADDR_WIDTH - 1):0]),
+ .wr_i(wr_i[i])
+ );
+ end
+end
+endgenerate
+
+endmodule
Index: sim/Readme.txt
===================================================================
--- sim/Readme.txt (nonexistent)
+++ sim/Readme.txt (revision 2)
@@ -0,0 +1,32 @@
+MPX RTL Simulation
+------------------
+
+This directory contains the Verilator RTL simulation model.
+
+Requirements:
+- verilator-3.831 or newer
+
+To run applications:
+./run_mpx image.bin
+
+Where image.bin is your compiled source which has a starting address of 0x10000000.
+
+Example Image:
+./run_mpx test_image.bin
+
+Expected Output:
+
+Test:
+1. Initialised data
+2. Multiply
+3. Divide
+4. Shift left
+5. Shift right
+6. Shift right arithmetic
+7. Signed comparision
+8. Word access
+9. Byte access
+10. SYSCALL return PC check
+11. Comparision
+Correct comparision
+Total test clock cycles: 1679037
\ No newline at end of file
Index: sim/mpx_top.h
===================================================================
--- sim/mpx_top.h (nonexistent)
+++ sim/mpx_top.h (revision 2)
@@ -0,0 +1,24 @@
+#ifndef __MPX_TOP_H__
+#define __MPX_TOP_H__
+
+//--------------------------------------------------------------------
+// Defines
+//--------------------------------------------------------------------
+#define MPX_RUN_RES_FAULT -1
+#define MPX_RUN_RES_OK 0
+#define MPX_RUN_RES_MAX_CYCLES 1
+#define MPX_RUN_RES_BREAKPOINT 2
+
+//--------------------------------------------------------------------
+// Prototypes
+//--------------------------------------------------------------------
+int mpx_test_init(void);
+int mpx_test_load(unsigned int addr, unsigned char val);
+void mpx_test_reset(void);
+void mpx_test_done(void);
+unsigned int mpx_test_getreg(int reg);
+unsigned int mpx_test_getpc(void);
+int mpx_test_run(int cycles);
+int mpx_test_setbreakpoint(int bp, unsigned int pc);
+
+#endif