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

Subversion Repositories mpx

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /mpx
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/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
/trunk/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
/trunk/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
/trunk/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
/trunk/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
/trunk/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
/trunk/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
/trunk/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
/trunk/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
 
/trunk/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);
}
/trunk/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
/trunk/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
}
/trunk/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
/trunk/sim/test_image.bin Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/sim/test_image.bin Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/sim/mpx_top.v =================================================================== --- trunk/sim/mpx_top.v (nonexistent) +++ trunk/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: trunk/sim/sram4.v =================================================================== --- trunk/sim/sram4.v (nonexistent) +++ trunk/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: trunk/sim/Readme.txt =================================================================== --- trunk/sim/Readme.txt (nonexistent) +++ trunk/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: trunk/sim/mpx_top.h =================================================================== --- trunk/sim/mpx_top.h (nonexistent) +++ trunk/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

powered by: WebSVN 2.1.0

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