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

Subversion Repositories openfire_core

Compare Revisions

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

Rev 1 → Rev 2

/trunk/openfire_top_syn/hdl/verilog/openfire_cpu.v
0,0 → 1,375
/*
 
MODULE: openfire_cpu
 
DESCRIPTION: This is the top module for the openfire processor, instantiating
the fetch, decode, execute, pipeline_ctrl, and register file modules.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
 
`ifdef FSL_LINK
// pc is output to create FSL_debug port at the next level up
module openfire_cpu (
clock, reset, stall, // inputs
dmem_data_in, imem_data_in,
dmem_addr, imem_addr, dmem_data_out, dmem_we, dmem_en, pc, // outputs
fsl0_s_control, fsl0_s_exists, fsl0_m_full,
fsl0_m_control, fsl0_m_write, fsl0_s_read,
fsl1_s_control, fsl1_s_exists, fsl1_m_full,
fsl1_m_control, fsl1_m_write, fsl1_s_read,
fsl2_s_control, fsl2_s_exists, fsl2_m_full,
fsl2_m_control, fsl2_m_write, fsl2_s_read,
fsl3_s_control, fsl3_s_exists, fsl3_m_full,
fsl3_m_control, fsl3_m_write, fsl3_s_read,
fsl4_s_control, fsl4_s_exists, fsl4_m_full,
fsl4_m_control, fsl4_m_write, fsl4_s_read,
fsl5_s_control, fsl5_s_exists, fsl5_m_full,
fsl5_m_control, fsl5_m_write, fsl5_s_read,
fsl6_s_control, fsl6_s_exists, fsl6_m_full,
fsl6_m_control, fsl6_m_write, fsl6_s_read,
fsl7_s_control, fsl7_s_exists, fsl7_m_full,
fsl7_m_control, fsl7_m_write, fsl7_s_read,
fsl0_s_data, fsl1_s_data, fsl2_s_data, fsl3_s_data,
fsl4_s_data, fsl5_s_data, fsl6_s_data, fsl7_s_data,
fsl0_m_data, fsl1_m_data, fsl2_m_data, fsl3_m_data,
fsl4_m_data, fsl5_m_data, fsl6_m_data, fsl7_m_data ); // FSL
`else
module openfire_cpu (
clock, reset, stall, // inputs
dmem_data_in, imem_data_in,
dmem_addr, imem_addr, dmem_data_out, dmem_we, dmem_en); // outputs
`endif
 
input clock;
input reset;
input stall;
input [31:0] dmem_data_in;
input [31:0] imem_data_in;
 
output [31:0] dmem_data_out;
output [31:0] dmem_addr;
output [31:0] imem_addr;
output dmem_we;
output dmem_en; // Change: Added dmem_en signal to indicate dmem access
 
wire [31:0] dmem_addr_internal;
wire branch_taken;
wire [`D_WIDTH-1:0] pc_branch;
wire [`D_WIDTH-1:0] pc_decode;
wire [`D_WIDTH-1:0] pc_exe_rf;
wire [31:0] instruction;
wire [4:0] regA_addr;
wire [4:0] regB_addr;
wire [4:0] regD_addr;
wire [`D_WIDTH-1:0] immediate;
 
wire [1:0] alu_inputA_sel;
wire [1:0] alu_inputB_sel;
wire [1:0] alu_inputC_sel;
wire [3:0] alu_fns_sel;
wire [2:0] comparator_fns_sel;
wire we_alu_branch;
wire we_load;
wire we_store;
wire [2:0] regfile_input_sel;
wire [1:0] dmem_input_sel;
wire delay_bit;
wire [`D_WIDTH-1:0] result;
 
wire [`D_WIDTH-1:0] regA;
wire [`D_WIDTH-1:0] regB;
wire [`D_WIDTH-1:0] regD;
wire we_load_dly;
wire we_store_dly;
wire update_carry;
wire stall_exe;
wire stall_decode;
wire stall_fetch;
wire instr_complete;
wire flush;
wire branch_instr;
wire [1:0] byte_sel;
 
`ifdef FSL_LINK
//From Decode Logic
wire fsl_get;
wire fsl_cmd_vld;
wire fsl_control;
wire fsl_blocking;
wire [2:0] fsl_number;
//FSL Specific Wires
input wire fsl0_s_control;
input wire fsl0_s_exists;
input wire fsl0_m_full;
output wire fsl0_m_control;
output wire fsl0_m_write;
output wire fsl0_s_read;
input wire fsl1_s_control;
input wire fsl1_s_exists;
input wire fsl1_m_full;
output wire fsl1_m_control;
output wire fsl1_m_write;
output wire fsl1_s_read;
input wire fsl2_s_control;
input wire fsl2_s_exists;
input wire fsl2_m_full;
output wire fsl2_m_control;
output wire fsl2_m_write;
output wire fsl2_s_read;
input wire fsl3_s_control;
input wire fsl3_s_exists;
input wire fsl3_m_full;
output wire fsl3_m_control;
output wire fsl3_m_write;
output wire fsl3_s_read;
input wire fsl4_s_control;
input wire fsl4_s_exists;
input wire fsl4_m_full;
output wire fsl4_m_control;
output wire fsl4_m_write;
output wire fsl4_s_read;
input wire fsl5_s_control;
input wire fsl5_s_exists;
input wire fsl5_m_full;
output wire fsl5_m_control;
output wire fsl5_m_write;
output wire fsl5_s_read;
input wire fsl6_s_control;
input wire fsl6_s_exists;
input wire fsl6_m_full;
output wire fsl6_m_control;
output wire fsl6_m_write;
output wire fsl6_s_read;
input wire fsl7_s_control;
input wire fsl7_s_exists;
input wire fsl7_m_full;
output wire fsl7_m_control;
output wire fsl7_m_write;
output wire fsl7_s_read;
 
input wire [31:0] fsl0_s_data;
input wire [31:0] fsl1_s_data;
input wire [31:0] fsl2_s_data;
input wire [31:0] fsl3_s_data;
input wire [31:0] fsl4_s_data;
input wire [31:0] fsl5_s_data;
input wire [31:0] fsl6_s_data;
input wire [31:0] fsl7_s_data;
output reg [31:0] fsl0_m_data;
output reg [31:0] fsl1_m_data;
output reg [31:0] fsl2_m_data;
output reg [31:0] fsl3_m_data;
output reg [31:0] fsl4_m_data;
output reg [31:0] fsl5_m_data;
output reg [31:0] fsl6_m_data;
output reg [31:0] fsl7_m_data;
 
//For FSL PC DEBUG
output [31:0] pc;
`endif
 
assign dmem_we = we_store_dly;
assign dmem_en = we_store_dly | we_load_dly;
assign dmem_addr = dmem_addr_internal; // Change: Address is now byte-addressed
 
openfire_fetch FETCH ( .stall(stall_fetch), .clock(clock),
.reset(reset), .branch_taken(branch_taken),
.pc_branch(pc_branch), .idata(imem_data_in), .imem_addr(imem_addr),
.pc_decode(pc_decode), .instruction(instruction));
 
`ifdef FSL_LINK
assign pc = pc_exe_rf; // Change: adjusted PC width to 32 bits
//assign fsl_m_data = {{(32-`D_WIDTH){1'b0}},regA}; // zero pad FSL to 32-bits
always @ (regA or fsl_number) begin
fsl0_m_data = 0;
fsl1_m_data = 0;
fsl2_m_data = 0;
fsl3_m_data = 0;
fsl4_m_data = 0;
fsl5_m_data = 0;
fsl6_m_data = 0;
fsl7_m_data = 0;
 
case (fsl_number)
0 : fsl0_m_data = regA;
1 : fsl1_m_data = regA;
2 : fsl2_m_data = regA;
3 : fsl3_m_data = regA;
4 : fsl4_m_data = regA;
5 : fsl5_m_data = regA;
6 : fsl6_m_data = regA;
7 : fsl7_m_data = regA;
endcase
end
 
openfire_decode DECODE (.clock(clock), .stall(stall_decode),
.reset(reset), .pc_decode(pc_decode), .instruction(instruction),
.regA_addr(regA_addr),
.regB_addr(regB_addr), .regD_addr(regD_addr),
.immediate(immediate), .pc_exe(pc_exe_rf),
.alu_inputA_sel(alu_inputA_sel), .alu_inputB_sel(alu_inputB_sel),
.alu_inputC_sel(alu_inputC_sel), .alu_fns_sel(alu_fns_sel),
.comparator_fns_sel(comparator_fns_sel), .branch_instr(branch_instr),
.we_alu_branch(we_alu_branch), .we_load(we_load),
.we_store(we_store), .regfile_input_sel(regfile_input_sel),
.dmem_input_sel(dmem_input_sel), .flush(flush),
.delay_bit(delay_bit), .update_carry(update_carry),
.fsl_get(fsl_get), .fsl_control(fsl_control),
.fsl_blocking(fsl_blocking), .fsl_cmd_vld(fsl_cmd_vld),
.fsl_number(fsl_number));
openfire_execute EXECUTE (.clock(clock), .reset(reset),
.stall(stall_exe), .immediate(immediate),
.pc_exe(pc_exe_rf), .alu_inputA_sel(alu_inputA_sel),
.alu_inputB_sel(alu_inputB_sel), .alu_inputC_sel(alu_inputC_sel),
.alu_fns_sel(alu_fns_sel), .comparator_fns_sel(comparator_fns_sel),
.we_load(we_load), .we_store(we_store), .update_carry(update_carry),
.regA(regA), .regB(regB), .regD(regD), .alu_result(result),
.pc_branch(pc_branch), .branch_taken(branch_taken), .dmem_input_sel(dmem_input_sel),
.we_regfile(we_load_dly), .we_store_dly(we_store_dly),
.dmem_addr(dmem_addr_internal), .dmem_data_in(dmem_data_in),
.dmem_data_out(dmem_data_out), .instr_complete(instr_complete),
.byte_sel(byte_sel),
.branch_instr(branch_instr),
.fsl_get(fsl_get), .fsl_cmd_vld(fsl_cmd_vld), .fsl_control(fsl_control),
.fsl_blocking(fsl_blocking), .fsl_number(fsl_number),
 
.fsl0_s_control(fsl0_s_control),
.fsl0_s_exists(fsl0_s_exists),
.fsl0_m_full(fsl0_m_full),
.fsl0_m_control(fsl0_m_control),
.fsl0_m_write(fsl0_m_write),
.fsl0_s_read(fsl0_s_read),
.fsl1_s_control(fsl1_s_control),
.fsl1_s_exists(fsl1_s_exists),
.fsl1_m_full(fsl1_m_full),
.fsl1_m_control(fsl1_m_control),
.fsl1_m_write(fsl1_m_write),
.fsl1_s_read(fsl1_s_read),
.fsl2_s_control(fsl2_s_control),
.fsl2_s_exists(fsl2_s_exists),
.fsl2_m_full(fsl2_m_full),
.fsl2_m_control(fsl2_m_control),
.fsl2_m_write(fsl2_m_write),
.fsl2_s_read(fsl2_s_read),
.fsl3_s_control(fsl3_s_control),
.fsl3_s_exists(fsl3_s_exists),
.fsl3_m_full(fsl3_m_full),
.fsl3_m_control(fsl3_m_control),
.fsl3_m_write(fsl3_m_write),
.fsl3_s_read(fsl3_s_read),
.fsl4_s_control(fsl4_s_control),
.fsl4_s_exists(fsl4_s_exists),
.fsl4_m_full(fsl4_m_full),
.fsl4_m_control(fsl4_m_control),
.fsl4_m_write(fsl4_m_write),
.fsl4_s_read(fsl4_s_read),
.fsl5_s_control(fsl5_s_control),
.fsl5_s_exists(fsl5_s_exists),
.fsl5_m_full(fsl5_m_full),
.fsl5_m_control(fsl5_m_control),
.fsl5_m_write(fsl5_m_write),
.fsl5_s_read(fsl5_s_read),
.fsl6_s_control(fsl6_s_control),
.fsl6_s_exists(fsl6_s_exists),
.fsl6_m_full(fsl6_m_full),
.fsl6_m_control(fsl6_m_control),
.fsl6_m_write(fsl6_m_write),
.fsl6_s_read(fsl6_s_read),
.fsl7_s_control(fsl7_s_control),
.fsl7_s_exists(fsl7_s_exists),
.fsl7_m_full(fsl7_m_full),
.fsl7_m_control(fsl7_m_control),
.fsl7_m_write(fsl7_m_write),
.fsl7_s_read(fsl7_s_read)
);
openfire_regfile REGFILE (.reset(reset), .clock(clock), .regA_addr(regA_addr),
.regB_addr(regB_addr), .regD_addr(regD_addr), .result(result),
.pc_regfile(pc_exe_rf), .dmem_data(dmem_data_in),
.regfile_input_sel(regfile_input_sel), .we_load_dly(we_load_dly),
.we_alu_branch(we_alu_branch), .regA(regA), .regB(regB), .regD(regD),
.enable(~stall_exe), .dmem_addr_lsb(byte_sel), .fsl_number(fsl_number),
.fsl0_s_data(fsl0_s_data),
.fsl1_s_data(fsl1_s_data),
.fsl2_s_data(fsl2_s_data),
.fsl3_s_data(fsl3_s_data),
.fsl4_s_data(fsl4_s_data),
.fsl5_s_data(fsl5_s_data),
.fsl6_s_data(fsl6_s_data),
.fsl7_s_data(fsl7_s_data)
);
`else
openfire_decode DECODE (.clock(clock), .stall(stall_decode),
.reset(reset), .pc_decode(pc_decode), .instruction(instruction),
.regA_addr(regA_addr),
.regB_addr(regB_addr), .regD_addr(regD_addr),
.immediate(immediate), .pc_exe(pc_exe_rf),
.alu_inputA_sel(alu_inputA_sel), .alu_inputB_sel(alu_inputB_sel),
.alu_inputC_sel(alu_inputC_sel), .alu_fns_sel(alu_fns_sel),
.comparator_fns_sel(comparator_fns_sel),
.we_alu_branch(we_alu_branch), .we_load(we_load),
.we_store(we_store), .regfile_input_sel(regfile_input_sel),
.dmem_input_sel(dmem_input_sel), .flush(flush), .branch_instr(branch_instr),
.delay_bit(delay_bit), .update_carry(update_carry));
openfire_execute EXECUTE (.clock(clock), .reset(reset),
.stall(stall_exe), .immediate(immediate),
.pc_exe(pc_exe_rf), .alu_inputA_sel(alu_inputA_sel),
.alu_inputB_sel(alu_inputB_sel), .alu_inputC_sel(alu_inputC_sel),
.alu_fns_sel(alu_fns_sel), .comparator_fns_sel(comparator_fns_sel),
.we_load(we_load), .we_store(we_store), .update_carry(update_carry),
.regA(regA), .regB(regB), .regD(regD), .alu_result(result),
.pc_branch(pc_branch), .branch_taken(branch_taken), .dmem_input_sel(dmem_input_sel),
.we_regfile(we_load_dly), .we_store_dly(we_store_dly), .branch_instr(branch_instr),
.dmem_addr(dmem_addr_internal), .dmem_data_in(dmem_data_in), .byte_sel(byte_sel),
.dmem_data_out(dmem_data_out), .instr_complete(instr_complete));
openfire_regfile REGFILE (.reset(reset), .clock(clock), .regA_addr(regA_addr),
.regB_addr(regB_addr), .regD_addr(regD_addr), .result(result),
.pc_regfile(pc_exe_rf), .dmem_data(dmem_data_in),
.regfile_input_sel(regfile_input_sel), .we_load_dly(we_load_dly),
.we_alu_branch(we_alu_branch), .regA(regA), .regB(regB), .regD(regD),
.enable(~stall_exe), .dmem_addr_lsb(byte_sel));
`endif
 
openfire_pipeline_ctrl PIPELINE (.clock(clock), .reset(reset), .stall(stall), .flush(flush),
.branch_taken(branch_taken), .instr_complete(instr_complete), .delay_bit(delay_bit),
.stall_fetch(stall_fetch), .stall_decode(stall_decode), .stall_exe(stall_exe));
endmodule
/trunk/openfire_top_syn/hdl/verilog/openfire_fetch.v
0,0 → 1,89
/*
 
MODULE: openfire_fetch
 
DESCRIPTION: The fetch module interfaces with the instruction memory and
fetches the next instruction.
 
TO DO:
- Add prefetch buffer
- Add LMB interface
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
 
module openfire_fetch(
stall, clock, reset, // top level
branch_taken, pc_branch, idata, // inputs
instruction, imem_addr, pc_decode); // outputs
// From top level -- all active high unless otherwise noted
input stall;
input reset;
input clock;
 
// From EXECUTE module
input branch_taken; // strobe for latching in new pc
input [`D_WIDTH-1:0] pc_branch; // PC of branch
 
// From Instr Mem
input [31:0] idata;
 
output [31:0] imem_addr;
output [`D_WIDTH-1:0] pc_decode;
output [31:0] instruction;
 
reg [`D_WIDTH-1:0] pc_fetch; // PCs only need to contain addressable instr mem
reg [`D_WIDTH-1:0] pc_decode; // delayed PC for DECODE
reg [31:0] instruction;
 
assign imem_addr = pc_fetch;
 
always@(posedge clock)
if (reset)
begin
pc_fetch <= 0;
pc_decode <= 0;
instruction <= 32'h80000000; // Execute NoOp on reset
end
else if (!stall)
begin
pc_fetch <= branch_taken ? pc_branch : pc_fetch + 4; // update PC to branch or increment pc
pc_decode <= pc_fetch;
instruction <= idata;
end
endmodule
/trunk/openfire_top_syn/hdl/verilog/openfire_pipeline_ctrl.v
0,0 → 1,131
/*
 
MODULE: openfire_pipeline_ctrl
 
DESCRIPTION: Pipeline controller to stall various modules. FETCH and DECODE
are stalled on multicycle instructions (currently only loads & stores & MULs).
DECODE and EXECUTE cycles are stalled on branchs. See below for timing.
 
TO DO:
- Expand to handle memory miss stalls
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
module openfire_pipeline_ctrl(
clock, reset, stall, // top level
branch_taken, instr_complete, delay_bit, // inputs
stall_fetch, stall_decode, stall_exe, flush); // outputs
 
// From top level
input clock;
input stall;
input reset;
 
// From EXECUTE
input branch_taken;
input instr_complete;
input delay_bit;
 
output stall_fetch;
output stall_decode;
output stall_exe;
output flush; // flush DECODE instruction
 
reg [1:0] branch_cnt;
 
assign stall_fetch = ~instr_complete | stall;
assign stall_decode = ~instr_complete | branch_cnt[1] | stall;
assign stall_exe = stall | branch_cnt[0];
assign flush = branch_taken & ~delay_bit;
 
always@(posedge clock)
begin
if (reset)
branch_cnt <= 0;
else if (~stall)
if (branch_taken)
branch_cnt <= 2;
else if (instr_complete & |branch_cnt)
branch_cnt <= branch_cnt - 1;
end
 
endmodule
 
/*
TIMING DIAGRAM
 
Branch with Delay (F = Fetch, D = Decode, E = Execute)
 
|--------|--------|--------|--------|--------|--------|
____ ____ ____ ____ ____ ____
clock | |___| |___| |___| |___| |___| |___
 
F - BRD D - BRD E - BRD
F - ADD D - ADD E - ADD
F - AND S - AND S - AND
F - XOR D - XOR E - XOR
________
branch_taken ___________________| |_____________________
_______
branch_cnt ___________________________| |________________
_______
stall_decode _________________________| |________________
________________________________________________
instr_complete
________
delay_bit __________________| |_________________________
___
flush _____________________________| |____________________
 
 
Branch without Delay (S = Stall)
 
|--------|--------|--------|--------|--------|--------|
____ ____ ____ ____ ____ ____
clock | |___| |___| |___| |___| |___| |___
 
F - BRA D - BRA E - BRA
F - ADD D - ADD S - ADD
F - AND S - AND S - AND
F - XOR D - XOR E - XOR
________
branch_taken ___________________| |_____________________
_______
branch_cnt ___________________________| |________________
_______
stall_decode _________________________| |________________
________________________________________________
instr_complete
 
*/
/trunk/openfire_top_syn/hdl/verilog/openfire_define.v
0,0 → 1,182
/*
 
MODULE: openfire_define
 
DESCRIPTION: Contains define statements used for readability.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
/***********************************
* User-modified Processor Options *
***********************************/
 
// Choose polarity of reset signal. Comment next line to make reset active high.
`define RESET_ACTIVE_LOW
 
// Enable FSL link & FSL debug port (currently only outputs PC)
// Comment out following line to disable FSL support
`define FSL_LINK
 
// Optional CMPU instruction requires a 32-bit comparator
// To enable CMPU support, leave only one of the following two options uncommented
// To disable CMPU support (for faster, smaller core) comment out both options
`define FAST_CMP // use fast, but larger comparator for CMPU instr
//`define CMP // include comparator for CMPU instr
 
// Specify address space size
// If using a unified memory (data and instr in same memory) both memory sizes must be the same
`define IM_SIZE 30 // width of instruction memory space; 12 => 2^12 words = 16kB
`define DM_SIZE 30 // width of data memory space; 12 => 2^12 words = 16kB
`define BRAM_SIZE 12 // size of the BRAM (if using unified memory)
 
// Specify datapath width
// Currently only 32-bit and 16-bit datapath widths are supported
// NOTE: datapath width affects maximum program size as the Prog Counter uses datapath
// max program length of 16-bit datapath = 16,384 instructions
// To enable 16-bit datapath, uncomment following line
//`define DATAPATH_16 // default datapath width is 32 bits
 
// Specify addressible space -- easiest just to set to max of IM_SIZE and DM_SIZE
`define A_SPACE 32 // width of addressible space, used for PC (must be =< D_WIDTH)
// Note: this controls max program size. It also may
// conflict with D_WIDTH when A_SPACE is set to 30.
 
// Optional HW multiplier uses 3 Xilinx Block MULTS for 32-bit multiply
`define MUL // include HW multiplier
 
// End User-modified Processor Options
 
 
// Sets define statements for datapath -- DO NOT TOUCH ANYTHING BELOW THIS LINE (UNLESS ADDING INSTRUCTIONS)
`ifdef DATAPATH_16
`define D_WIDTH 16 // width of datapath -- ONLY 32 & 16 supported
`else
`define D_WIDTH 32
`define DATAPATH_32
`endif
 
// Instruction Fields
`define opcode instruction[31:26]
`define regD_sel instruction[25:21]
`define regA_sel instruction[20:16]
`define regB_sel instruction[15:11]
`define imm_value instruction[15:0]
`define branch_compare instruction[23:21]
`define word_size instruction[27:26]
`define fsl_get_put instruction[15]
// Special opcode bits
`define CMP_bit instruction[0] // CMP/CMPU instr
`define C_bit instruction[27] // Use Carry bit
`define K_bit instruction[28] // if 1, do not update Carry bit in MSR
`define D_bit_uncond instruction[20] // Delay bit for unconditional branchs
`define D_bit_cond instruction[25] // Delay bit for conditional branchs
`define A_bit instruction[19] // Absolute addressing for branch
`define L_bit instruction[18] // Link bit, stores PC in rD for branchs
`define U_bit instruction[1] // Unsigned bit for Compare instructions
`define IMM_bit instruction[29] // IMMediate
`define uncond_branch (({instruction[31], instruction[30], instruction[28], instruction[27], instruction[26]} == 5'b10110 ) | ({instruction[31], instruction[30], instruction[28], instruction[27], instruction[26]} == 5'b10101 ))
`define cond_branch ({instruction[31], instruction[30], instruction[28], instruction[27], instruction[26]} == 5'b10111 )
`define FSL_nblock instruction[14]
`define FSL_control instruction[13]
`define FSL_number instruction[2:0]
 
// Instructions
`define ADD 6'b00???0
`define SUBTRACT 6'b00???1
`define LOGIC_OR 6'b10?000
`define LOGIC_AND 6'b10?001
`define LOGIC_XOR 6'b10?010
`define LOGIC_ANDN 6'b10?011
`define LOGIC_BIT 6'b100100
`define BRANCH_UNCON 6'b10?110 // Break is actually BRAL
`define BRANCH_CON 6'b10?111
`define IMMEDIATE 6'b101100
`define RETURN 6'b101101
`define BREAK 6'b10?110 // Not needed, same opcode as BRAL
`define LOAD 6'b11?0??
`define STORE 6'b11?1??
`define FSL 6'b011011
`define MULTIPLY 6'b01?000
 
// ALU Functions
`define ALU_add 4'd0
`define ALU_compare_uns 4'd1 // CMPU (unsigned Compare)
`define ALU_logic_or 4'd2
`define ALU_logic_and 4'd3
`define ALU_logic_xor 4'd4
`define ALU_sex8 4'd5
`define ALU_sex16 4'd6
`define ALU_shiftR_arth 4'd7
`define ALU_shiftR_log 4'd8
`define ALU_shiftR_c 4'd9
`define ALU_compare 4'd10 // CMP
`define ALU_multiply 4'd11
 
// ALU inputs
`define aluA_ra 2'd0
`define aluA_ra_bar 2'd1
`define aluA_pc 2'd2
`define aluA_zero 2'd3
`define aluB_rb 2'd0
`define aluB_imm 2'd1
`define aluB_rb_bar 2'd2
`define aluB_imm_bar 2'd3
`define aluC_zero 2'd0
`define aluC_one 2'd1
`define aluC_carry 2'd2
 
// Comparator Functions
`define CMP_equal 3'd0
`define CMP_not_equal 3'd1
`define CMP_lessthan 3'd2
`define CMP_lt_equal 3'd3
`define CMP_greaterthan 3'd4
`define CMP_gt_equal 3'd5
`define CMP_one 3'd6
`define CMP_dual_inputs 3'd7 // compare regA and regB for CMPU instr
 
// RegFile Input Select
`define RF_dmem_byte 3'd0
`define RF_dmem_halfword 3'd1
`define RF_dmem_wholeword 3'd2
`define RF_alu_result 3'd3
`define RF_pc 3'd4
`define RF_zero 3'd5
`define RF_fsl 3'd6
 
// DMEM Input Select
`define DM_byte 2'd0
`define DM_halfword 2'd1
`define DM_wholeword 2'd2
 
/trunk/openfire_top_syn/hdl/verilog/openfire_top_sim.v
0,0 → 1,203
/*
 
MODULE: openfire_top
 
DESCRIPTION: This is the top level module for simulation.
Debugging statements produce statements on all register and memory writes as
well as opcode and unaligned memory write exceptions.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
 
 
// BREAKPOINT stops simulation and displays register contents.
// Set to unreachable address to disable.
`define BREAKPOINT 32'hc0
 
// TIMEOUT stops the simulation after TIMEOUT/2 number of clock
// cycles.
`define TIMEOUT 1000000
 
`include "openfire_define.v"
`include "openfire_cpu.v"
`include "openfire_primitives.v"
`include "openfire_regfile.v"
`include "openfire_execute.v"
`include "openfire_decode.v"
`include "openfire_fetch.v"
`include "openfire_pipeline_ctrl.v"
 
module openfire_top_single ();
wire [31:0] imem_data;
wire [31:0] imem_addr;
wire [31:0] dmem_data2mem;
wire [31:0] dmem_data2cpu;
wire [31:0] dmem_addr;
wire dmem_we;
 
reg [31:0] fsl_s_data;
wire [31:0] fsl_m_data;
wire [31:0] pc_wire;
 
reg fsl_s_exists;
reg fsl_m_full;
reg fsl_s_control;
 
reg clock;
reg reset;
reg stall;
reg [31:0] counter; // counter used soley for debugging
 
`ifdef FSL_LINK
openfire_cpu OPENFIRE0 (
.clock(clock), .reset(reset), .stall(stall),
.dmem_data_in(dmem_data2cpu), .imem_data_in(imem_data),
.dmem_addr(dmem_addr), .imem_addr(imem_addr), // outputs
.fsl_s_data(fsl_s_data), .fsl_s_control(fsl_s_control),
.fsl_s_exists(fsl_s_exists), .fsl_m_full(fsl_m_full), // FSL
.fsl_m_data(fsl_m_data), .fsl_m_control(fsl_m_control),
.fsl_m_write(fsl_m_write), .fsl_s_read(fsl_s_read),
.dmem_data_out(dmem_data2mem), .dmem_we(dmem_we), .pc(pc_wire));
`else
openfire_cpu OPENFIRE0 (.clock(clock), .reset(reset), .stall(stall),
.dmem_data_in(dmem_data2cpu), .imem_data_in(imem_data),
.dmem_addr(dmem_addr), .imem_addr(imem_addr),
.dmem_data_out(dmem_data2mem), .dmem_we(dmem_we));
`endif
// Instruction SRAM contains $initial statement for simulation
// Note inverted clock inverted. Needed for single-cycle FETCH with sync memories.
 
openfire_dual_sram MEM ( .clock(~clock), .wr_clock(clock), .enable(!stall), // invert clock
.read_addr(imem_addr[`IM_SIZE - 1:0]), .write_addr(dmem_addr[`DM_SIZE - 1:0]), .data_in(dmem_data2mem), .we(dmem_we),
.data_out(imem_data), .wr_data_out(dmem_data2cpu));
 
integer j;
initial begin
clock = 1;
reset = 1; // reset the processor (active high)
stall = 0; // external stall signal (active high)
`ifdef FSL_LINK
fsl_s_data = 32'h666;
fsl_s_exists = 1;
fsl_s_control = 1;
fsl_m_full = 0;
`endif
// Dump all variables
//$dumpfile("dump.vcd");
//$dumpvars;
#5 reset = 0;
#`TIMEOUT reset = 0;
$finish; // finish after TIMEOUT
end
 
// Toggle clock every time unit
always clock= #1 ~clock;
 
// Define clock counter for debugging
integer i;
initial begin
counter = 32'b0;
for (i = 0; i >= 0; i = i + 1)
@(posedge clock) if (~reset) counter <= counter + 1;
end
 
// Debug Statements
always@(negedge clock)
begin
if(OPENFIRE0.branch_taken)
// Branch instructions
begin
$display("*** PC: %x Branching to %x", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe},
{{(30 - `A_SPACE) {1'b0}},OPENFIRE0.pc_branch});
end
if (OPENFIRE0.REGFILE.write_en)
// Register File writes
`ifdef DATAPATH_16
begin
if(OPENFIRE0.EXECUTE.we_load_dly)
$display("*** PC: %x Writing %x to Register %d from DMEM addr 0x%x", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe},
{{(32 - `D_WIDTH) {1'b0}}, OPENFIRE0.REGFILE.input_data}, OPENFIRE0.REGFILE.regD_addr, {{(30 - `DM_SIZE){1'b0}}, MEM.write_addr, 2'b0});
else
$display("*** PC: %x Writing %x to Register %d", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe},
{{(32 - `D_WIDTH) {1'b0}}, OPENFIRE0.REGFILE.input_data}, OPENFIRE0.REGFILE.regD_addr);
end
`else
begin
if(OPENFIRE0.EXECUTE.we_load_dly)
$display("*** PC: %x Writing %x to Register %d from DMEM addr 0x%x", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe},
{OPENFIRE0.REGFILE.input_data}, OPENFIRE0.REGFILE.regD_addr, {{(30 - `DM_SIZE){1'b0}}, MEM.write_addr, 2'b0});
else
$display("*** PC: %x Writing %x to Register %d", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe},
{OPENFIRE0.REGFILE.input_data}, OPENFIRE0.REGFILE.regD_addr);
end
`endif
if (MEM.we)
// Memory writes
begin
$display("*** PC: %x Writing %x to DMem location %x", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe},
MEM.data_in, {{(30 - `DM_SIZE) {1'b0}}, MEM.write_addr, 2'b0});
end
 
`ifdef FSL_LINK
// Debug FSL Reads and Writes
if (fsl_m_write)
$display("*** PC: %x Writing %x to FSL0", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe}, fsl_m_data);
else if (fsl_s_read)
$display("*** PC: %x Reading %x from FSL0", {{(30 - `A_SPACE) {1'b0}},OPENFIRE0.EXECUTE.pc_exe}, fsl_s_data);
`endif
 
end
 
 
// Stop at Breakpoint
always@(posedge clock)
begin
if(OPENFIRE0.DECODE.pc_exe == `BREAKPOINT)
begin
// Uncomment to display register file contents at breakpoint
/* $display(" PC is %x", OPENFIRE0.EXECUTE.pc_exe);
$display(" Clock Counter is %d", counter);
for(j = 0; j < 8; j = j + 1)
$display(" %d: %x %d %x %d: %x %d %x", j, OPENFIRE0.REGFILE.RF_BANK0.MEM[j], j + 8,
OPENFIRE0.REGFILE.RF_BANK0.MEM[j + 8],j+16, OPENFIRE0.REGFILE.RF_BANK0.MEM[j+16],j+24,
OPENFIRE0.REGFILE.RF_BANK0.MEM[j+24]);
*/
$finish;
end
end
 
endmodule
/trunk/openfire_top_syn/hdl/verilog/openfire_primitives.v
0,0 → 1,533
/*
 
MODULE: openfire_primitives
 
DESCRIPTION: Contains all submodules called by the design.
 
CONTENTS:
openfire_compare comparator for conditional branchs & CMPU instr
openfire_alu
openfire_rf_sram registerfile
openfire_sram synchronous SRAM for memories -- synthesizes to BRAMs
openfire_instr_sram same as above except includes INITIAL statement to load
instructions for simulation
TO DO:
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed Register File zeroing function for simulation
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
 
/**********************************
* Comparator for Branches & CMPU *
**********************************/
module openfire_compare (
in0, in1, fns, // inputs
out); // outputs
 
input [`D_WIDTH-1:0] in0;
input [`D_WIDTH-1:0] in1;
input [2:0] fns;
 
output out;
 
reg out;
 
wire cmp_out;
 
`ifdef FAST_CMP
wire cmp_dual_out;
 
// A single comparator could be used, but timing is tight.
// A single comparator can reach 100 MHz in a 2vp-7 part, but not in a -6 speed grade.
assign cmp_dual_out = (in0 > in1);
assign cmp_out = (in0[`D_WIDTH-2:0] > 0);
 
always@(in0 or in1 or cmp_out or fns or cmp_dual_out)
begin
 
// Verilog treats all signals as unsigned
case(fns)
`CMP_equal: out <= (in0 == 0);
`CMP_not_equal: out <= (in0 != 0);
`CMP_lessthan: out <= (in0[`D_WIDTH-1] == 1); // negative number
`CMP_lt_equal: out <= (in0 == 0) | (in0[`D_WIDTH-1] == 1);
`CMP_greaterthan: out <= cmp_out & (in0[`D_WIDTH-1] == 0);
`CMP_gt_equal: out <= (cmp_out | (in0[`D_WIDTH-2:0] == 0)) & (in0[`D_WIDTH-1] == 0);
`CMP_one: out <= 1'b1; // used for unconditional branchs
`CMP_dual_inputs: out <= cmp_dual_out; // used only for CMPU instruction
default:
begin
out <= 1'b0;
$display("ERROR! Comparator set to illegal function!");
end
endcase
end // always@
`else
`ifdef CMP
// Force tools to synthesize only a single 32-bit comparator... cannot reach 100 MHz in a 2vp speed grade 6 part
reg [`D_WIDTH-1:0] cmp_in_a;
reg [`D_WIDTH-1:0] cmp_in_b;
 
assign cmp_out = (cmp_in_a > cmp_in_b);
 
always@(in0 or in1 or cmp_out or fns)
begin
cmp_in_a <= {1'b0, in0[`D_WIDTH-2:0]};
cmp_in_b <= 0;
// Verilog treats all signals as unsigned
case(fns)
`CMP_equal: out <= (in0 == 0);
`CMP_not_equal: out <= (in0 != 0);
`CMP_lessthan: out <= (in0[`D_WIDTH-1] == 1); // negative number
`CMP_lt_equal: out <= (in0 == 0) | (in0[`D_WIDTH-1] == 1);
`CMP_greaterthan: out <= cmp_out & (in0[`D_WIDTH-1] == 0);
`CMP_gt_equal: out <= (cmp_out | (in0[`D_WIDTH-2:0] == 0)) & (in0[`D_WIDTH-1] == 0);
`CMP_one: out <= 1'b1; // used for unconditional branchs
`CMP_dual_inputs:
begin // used only for CMPU instruction
cmp_in_a <= in0;
cmp_in_b <= in1;
out <= cmp_out;
end
default:
begin
out <= 1'b0;
$display("ERROR! Comparator set to illegal function!");
end
endcase
end // always@
`else // Do not allow CMPU instruction
 
reg [`D_WIDTH-2:0] cmp_in_a;
 
assign cmp_out = (cmp_in_a > 0);
 
always@(in0, in1, cmp_out, fns)
begin
cmp_in_a <= in0[`D_WIDTH-2:0];
// Verilog treats all signals as unsigned
case(fns)
`CMP_equal: out <= (in0 == 0);
`CMP_not_equal: out <= (in0 != 0);
`CMP_lessthan: out <= (in0[`D_WIDTH-1] == 1); // negative number
`CMP_lt_equal: out <= (in0 == 0) | (in0[`D_WIDTH-1] == 1);
`CMP_greaterthan: out <= cmp_out & (in0[`D_WIDTH-1] == 0);
`CMP_gt_equal: out <= (cmp_out | (in0[`D_WIDTH-2:0] == 0)) & (in0[`D_WIDTH-1] == 0);
`CMP_one: out <= 1'b1; // used for unconditional branchs
default:
begin
out <= 1'b0;
$display("ERROR! Comparator set to illegal function!");
end
endcase
end // always@
`endif
`endif
 
endmodule
 
/**************
* Custom ALU *
**************/
module openfire_alu (
a, b, c_in, fns, clock, reset, stall, // inputs
alu_result, c_out, dmem_addr, // output
alu_multicycle_instr, alu_multicycle_instr_complete);
input [`D_WIDTH-1:0] a;
input [`D_WIDTH-1:0] b;
input c_in;
input [3:0] fns;
input clock;
input reset;
input stall;
 
output [`D_WIDTH-1:0] alu_result;
output [31:0] dmem_addr;
output c_out;
output alu_multicycle_instr;
output alu_multicycle_instr_complete;
 
reg [`D_WIDTH-1:0] alu_result;
reg [`D_WIDTH-1:0] adder_out;
reg c_out;
reg alu_multicycle_instr;
reg [2:0] mul_counter;
 
reg [`D_WIDTH-1:0] mul_result;
reg [`D_WIDTH-1:0] mul_tmp1;
reg [`D_WIDTH-1:0] a_in;
reg [`D_WIDTH-1:0] b_in;
 
`ifdef MUL
// Force tools to infer pipelined Mult - allows use of code on devices other than Xilinx FPGAs
// Mult takes 5 execute cycles to complete at 32-bits
`ifdef DATAPATH_32
assign alu_multicycle_instr_complete = (mul_counter == 3'b011);
 
always@(posedge clock)
begin
if(reset)
begin
a_in <= 0;
b_in <= 0;
mul_tmp1 <= 0;
mul_result <= 0;
mul_counter <= 0;
end
else if (~stall)
begin // infer pipelined multiplier
a_in <= a;
b_in <= b;
mul_tmp1 <= a_in * b_in;
mul_result <= mul_tmp1;
if (mul_counter == 3)
mul_counter <= 0;
else if(alu_multicycle_instr)
mul_counter <= mul_counter + 1;
end
end
`else // 16-bit datapath completes in single cycle
assign alu_multicycle_instr_complete = 0;
 
always@(a or b)
mul_result <= a * b;
`endif
`endif
 
// dmem_addr comes straight from adder to by-pass ALU output MUX for timing
`ifdef DATAPATH_32
assign dmem_addr = adder_out;
`else // 16-bit case
assign dmem_addr = {16'b0, adder_out};
`endif
 
// --> need stall prevention in ALU below?
 
// ALU result selection
`ifdef MUL
always@(a or b or c_in or fns or mul_result)
`else
always@(a or b or c_in or fns)
`endif
begin
if(~stall) begin
 
{c_out, adder_out} <= a + b + c_in;
alu_multicycle_instr <= 0;
case(fns)
//`ALU_add: {c_out, alu_result} <= a + b + c_in;
`ALU_logic_or:
begin
alu_result <= a | b;
c_out <= 0;
end
`ALU_logic_and:
begin
alu_result <= a & b;
c_out <= 0;
end
`ALU_logic_xor:
begin
alu_result <= a ^ b;
c_out <= 0;
end
`ALU_sex8:
begin
alu_result <= {{(`D_WIDTH-8){a[7]}}, a[7:0]};
c_out <= 0;
end
`ALU_sex16:
begin
alu_result <= {{(`D_WIDTH-16){a[15]}}, a[15:0]};
c_out <= 0;
end
`ALU_shiftR_arth:
begin
alu_result <= {a[`D_WIDTH-1], a[`D_WIDTH-1:1]};
c_out <= a[0];
end
`ALU_shiftR_log:
begin
alu_result <= {1'b0, a[`D_WIDTH-1:1]};
c_out <= a[0];
end
`ALU_shiftR_c:
begin
alu_result <= {c_in, a[`D_WIDTH-1:1]};
c_out <= a[0];
end
`ALU_compare: {c_out, alu_result} <= a + b + c_in;
`ALU_compare_uns: {c_out, alu_result} <= a + b + c_in; // comparator determines MSB
`ifdef MUL
`ALU_multiply:
begin
`ifdef DATAPATH_32
alu_multicycle_instr <= 1;
`endif
alu_result <= mul_result;
c_out <= 0;
end
`endif
default: //`ALU_add -- moved to default for speed considerations
begin
{c_out, alu_result} <= a + b + c_in;
if(fns != `ALU_add) $display("ERROR! ALU set to illegal or unimplemented function!");
end
endcase
end // end if(~stall)
end // end always@
 
endmodule
 
/*********************************************
* Register File SRAM *
* Created from 2, 2-bank SRAMs *
* Async Reads, Sync Writes *
* Targets dual-port distributed Select RAM *
*********************************************/
module openfire_rf_sram(
clock,
read_addr, write_addr, data_in, we, // inputs
read_data_out, write_data_out); // outputs
 
parameter addr_width = 5; // 32 registers
 
input clock;
input [addr_width-1:0] read_addr;
input [addr_width-1:0] write_addr;
input [`D_WIDTH-1:0] data_in;
input we;
 
output [`D_WIDTH-1:0] read_data_out;
output [`D_WIDTH-1:0] write_data_out;
 
reg [`D_WIDTH-1:0] MEM [(1 << addr_width) - 1:0];
 
integer i;
initial
begin
for(i=0; i < ( 1 << addr_width); i=i+1)
MEM[i] <= 0;
end
 
always@(posedge clock)
begin
if (we)
MEM[write_addr] <= data_in;
end
 
assign read_data_out = MEM[read_addr];
assign write_data_out = MEM[write_addr];
 
endmodule
 
/******************************
* Dual Port Synchronious RAM *
* 1 write port, 1 read port *
* sync writes, sync reads *
******************************/
module openfire_data_sram(
clock, enable, // inputs
read_addr, write_addr, data_in, we,
data_out); // outputs
 
input clock;
input enable;
input [`DM_SIZE-1:0] read_addr;
input [`DM_SIZE-1:0] write_addr;
input [31:0] data_in;
input we;
 
output [31:0] data_out;
 
reg [31:0] MEM [(1 << `DM_SIZE) - 1:0];
reg [31:0] data_out;
 
initial $readmemh("data.rom", MEM);
 
always@(posedge clock)
begin
if (enable)
begin
if (we)
MEM[write_addr] <= data_in;
data_out <= MEM[read_addr];
end
end // end always@
 
endmodule
 
 
/******************************
* Dual Port Sync RAM *
* 1 write port, 1 read port *
* LOADS INSTR into MEM *
******************************/
module openfire_instr_sram(
clock, enable, // inputs
read_addr, write_addr, data_in, we,
data_out); // outputs
 
input clock;
input enable;
input [`IM_SIZE-1:0] read_addr;
input [`IM_SIZE-1:0] write_addr;
input [31:0] data_in;
input we;
 
output [31:0] data_out;
 
reg [31:0] MEM [(1 << `IM_SIZE) - 1:0];
reg [31:0] data_out;
 
// initial statement for loading instructions in simulation
// initial $readmemh("instr.rom", MEM);
 
always@(posedge clock)
begin
if (enable)
begin
if (we)
MEM[write_addr] <= data_in;
data_out <= MEM[read_addr];
end
end // end always@
 
endmodule
 
 
/******************************
* Dual Port Sync RAM *
* 1 write port, 1 read port *
* LOADS INSTR into MEM *
******************************/
// Used for combined Data and Instr mem
module openfire_dual_sram(
clock, enable, wr_clock, // inputs
read_addr, write_addr, data_in, we,
data_out, wr_data_out); // outputs
 
input clock;
input wr_clock;
input enable;
input [`IM_SIZE-1:0] read_addr;
input [`IM_SIZE-1:0] write_addr;
input [31:0] data_in;
input we;
 
output [31:0] data_out;
output [31:0] wr_data_out;
 
reg [31:0] MEM [(1 << `BRAM_SIZE) - 1:0];
reg [31:0] data_out;
reg [31:0] wr_data_out;
 
// initial statement for loading instructions in simulation
// initial $readmemh("instr.rom", MEM);
 
always@(posedge wr_clock)
begin
if (enable)
begin
if (we)
MEM[write_addr] <= data_in;
wr_data_out <= MEM[write_addr];
end
end // end always@
 
always@(posedge clock)
begin
if(enable)
data_out <= MEM[read_addr];
end
 
endmodule
 
/*****************************************************************************/
 
module openfire_named_sram_16k (
dmem_clk,
dmem_en,
dmem_we,
dmem_addr,
dmem_data_i,
dmem_data_o,
 
imem_clk,
imem_en,
imem_addr,
imem_data_o
);
 
input wire dmem_clk;
input wire dmem_en;
input wire dmem_we;
input wire [11:0] dmem_addr;
input wire [31:0] dmem_data_i;
output wire [31:0] dmem_data_o;
 
input wire imem_clk;
input wire imem_en;
input wire [11:0] imem_addr;
output wire [31:0] imem_data_o;
 
RAMB16_S4_S4 bus0_ram0(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[3:0]), .DOA(dmem_data_o[3:0]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[3:0]));
RAMB16_S4_S4 bus0_ram1(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[7:4]), .DOA(dmem_data_o[7:4]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[7:4]));
RAMB16_S4_S4 bus0_ram2(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[11:8]), .DOA(dmem_data_o[11:8]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[11:8]));
RAMB16_S4_S4 bus0_ram3(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[15:12]), .DOA(dmem_data_o[15:12]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[15:12]));
RAMB16_S4_S4 bus0_ram4(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[19:16]), .DOA(dmem_data_o[19:16]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[19:16]));
RAMB16_S4_S4 bus0_ram5(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[23:20]), .DOA(dmem_data_o[23:20]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[23:20]));
RAMB16_S4_S4 bus0_ram6(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[27:24]), .DOA(dmem_data_o[27:24]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[27:24]));
RAMB16_S4_S4 bus0_ram7(
.CLKA(dmem_clk), .ENA(dmem_en), .WEA(dmem_we), .ADDRA(dmem_addr), .DIA(dmem_data_i[31:28]), .DOA(dmem_data_o[31:28]),
.CLKB(imem_clk), .ENB(imem_en), .ADDRB(imem_addr), .DOB(imem_data_o[31:28]));
 
endmodule
/trunk/openfire_top_syn/hdl/verilog/openfire_top_syn.v
0,0 → 1,604
/*
 
MODULE: openfire_top_syn
 
DESCRIPTION: This is the top level module for synthesis. A single, joint
memory is used for both instructions and data. This memory is a Xilinx
coregen generated BRAM component. However, any synchronous dual-port memory
would work.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
 
module openfire_top_syn (
// DEFINE IOPB LINK PORTS
IOPB_DBus, IOPB_errAck, IOPB_MGrant, IOPB_retry, IOPB_timeout, IOPB_xferAck,
IM_BE, IM_ABus, IM_busLock, IM_DBus, IM_request, IM_RNW, IM_select, IM_seqAddr,
// END IOPB LINK PORTS
// DEFINE DOPB LINK PORTS
DOPB_DBus, DOPB_errAck, DOPB_MGrant, DOPB_retry, DOPB_timeout, DOPB_xferAck,
DM_BE, DM_ABus, DM_busLock, DM_DBus, DM_request, DM_RNW, DM_select, DM_seqAddr,
// END DOPB LINK PORTS
// DEFINE FSL0 LINK PORTS
// FSL0_Clk, FSL0_Rst,
FSL0_S_DATA, FSL0_S_CONTROL, FSL0_S_READ, FSL0_S_EXISTS, FSL0_S_CLK,
FSL0_M_DATA, FSL0_M_CONTROL, FSL0_M_WRITE, FSL0_M_FULL, FSL0_M_CLK,
FSL1_S_DATA, FSL1_S_CONTROL, FSL1_S_READ, FSL1_S_EXISTS, FSL1_S_CLK,
FSL1_M_DATA, FSL1_M_CONTROL, FSL1_M_WRITE, FSL1_M_FULL, FSL1_M_CLK,
FSL2_S_DATA, FSL2_S_CONTROL, FSL2_S_READ, FSL2_S_EXISTS, FSL2_S_CLK,
FSL2_M_DATA, FSL2_M_CONTROL, FSL2_M_WRITE, FSL2_M_FULL, FSL2_M_CLK,
FSL3_S_DATA, FSL3_S_CONTROL, FSL3_S_READ, FSL3_S_EXISTS, FSL3_S_CLK,
FSL3_M_DATA, FSL3_M_CONTROL, FSL3_M_WRITE, FSL3_M_FULL, FSL3_M_CLK,
FSL4_S_DATA, FSL4_S_CONTROL, FSL4_S_READ, FSL4_S_EXISTS, FSL4_S_CLK,
FSL4_M_DATA, FSL4_M_CONTROL, FSL4_M_WRITE, FSL4_M_FULL, FSL4_M_CLK,
FSL5_S_DATA, FSL5_S_CONTROL, FSL5_S_READ, FSL5_S_EXISTS, FSL5_S_CLK,
FSL5_M_DATA, FSL5_M_CONTROL, FSL5_M_WRITE, FSL5_M_FULL, FSL5_M_CLK,
FSL6_S_DATA, FSL6_S_CONTROL, FSL6_S_READ, FSL6_S_EXISTS, FSL6_S_CLK,
FSL6_M_DATA, FSL6_M_CONTROL, FSL6_M_WRITE, FSL6_M_FULL, FSL6_M_CLK,
FSL7_S_DATA, FSL7_S_CONTROL, FSL7_S_READ, FSL7_S_EXISTS, FSL7_S_CLK,
FSL7_M_DATA, FSL7_M_CONTROL, FSL7_M_WRITE, FSL7_M_FULL, FSL7_M_CLK,
FSL_M_DATA_DBG, FSL_M_CONTROL_DBG, FSL_M_WRITE_DBG, FSL_M_FULL_DBG, FSL_M_CLK_DBG,
// END FSL0 LINK PORTS
clock, reset
);
 
parameter C_EXT_RESET_HIGH = 0;
parameter C_DOPB_ADDR_LO = 32'h30000000;
parameter C_DOPB_ADDR_HI = 32'h50000000;
parameter C_IOPB_ENABLE = 1;
parameter C_DOPB_ENABLE = 1;
parameter C_IOPB_CSCOPE = 0;
parameter C_DOPB_CSCOPE = 0;
parameter C_FSL_LINKS = 8;
parameter C_FSL_DEBUG = 0;
parameter C_OF_CSCOPE = 0;
 
input clock;
input reset;
 
//input FSL0_Clk;
//input FSL0_Rst;
 
`ifdef FSL_LINK
input wire FSL0_S_CONTROL;
input wire FSL0_S_EXISTS;
input wire FSL0_M_FULL;
output wire FSL0_M_CONTROL;
output wire FSL0_M_WRITE;
output wire FSL0_S_READ;
 
input wire FSL1_S_CONTROL;
input wire FSL1_S_EXISTS;
input wire FSL1_M_FULL;
output wire FSL1_M_CONTROL;
output wire FSL1_M_WRITE;
output wire FSL1_S_READ;
 
input wire FSL2_S_CONTROL;
input wire FSL2_S_EXISTS;
input wire FSL2_M_FULL;
output wire FSL2_M_CONTROL;
output wire FSL2_M_WRITE;
output wire FSL2_S_READ;
 
input wire FSL3_S_CONTROL;
input wire FSL3_S_EXISTS;
input wire FSL3_M_FULL;
output wire FSL3_M_CONTROL;
output wire FSL3_M_WRITE;
output wire FSL3_S_READ;
 
input wire FSL4_S_CONTROL;
input wire FSL4_S_EXISTS;
input wire FSL4_M_FULL;
output wire FSL4_M_CONTROL;
output wire FSL4_M_WRITE;
output wire FSL4_S_READ;
 
input wire FSL5_S_CONTROL;
input wire FSL5_S_EXISTS;
input wire FSL5_M_FULL;
output wire FSL5_M_CONTROL;
output wire FSL5_M_WRITE;
output wire FSL5_S_READ;
 
input wire FSL6_S_CONTROL;
input wire FSL6_S_EXISTS;
input wire FSL6_M_FULL;
output wire FSL6_M_CONTROL;
output wire FSL6_M_WRITE;
output wire FSL6_S_READ;
 
input wire FSL7_S_CONTROL;
input wire FSL7_S_EXISTS;
input wire FSL7_M_FULL;
output wire FSL7_M_CONTROL;
output wire FSL7_M_WRITE;
output wire FSL7_S_READ;
 
input wire [31:0] FSL0_S_DATA;
input wire [31:0] FSL1_S_DATA;
input wire [31:0] FSL2_S_DATA;
input wire [31:0] FSL3_S_DATA;
input wire [31:0] FSL4_S_DATA;
input wire [31:0] FSL5_S_DATA;
input wire [31:0] FSL6_S_DATA;
input wire [31:0] FSL7_S_DATA;
output wire [31:0] FSL0_M_DATA;
output wire [31:0] FSL1_M_DATA;
output wire [31:0] FSL2_M_DATA;
output wire [31:0] FSL3_M_DATA;
output wire [31:0] FSL4_M_DATA;
output wire [31:0] FSL5_M_DATA;
output wire [31:0] FSL6_M_DATA;
output wire [31:0] FSL7_M_DATA;
 
output wire FSL0_M_CLK;
output wire FSL0_S_CLK;
output wire FSL1_M_CLK;
output wire FSL1_S_CLK;
output wire FSL2_M_CLK;
output wire FSL2_S_CLK;
output wire FSL3_M_CLK;
output wire FSL3_S_CLK;
output wire FSL4_M_CLK;
output wire FSL4_S_CLK;
output wire FSL5_M_CLK;
output wire FSL5_S_CLK;
output wire FSL6_M_CLK;
output wire FSL6_S_CLK;
output wire FSL7_M_CLK;
output wire FSL7_S_CLK;
 
// Debug Outputs
input wire FSL_M_FULL_DBG;
output wire [31:0] FSL_M_DATA_DBG;
output wire FSL_M_CONTROL_DBG;
output wire FSL_M_WRITE_DBG;
output wire FSL_M_CLK_DBG;
 
`endif
 
// DEFINE IOPB LINK PORTS/WIRES
input wire [0:31] IOPB_DBus; // incoming data from OPB
input wire IOPB_errAck; // incoming error acknowledge from OPB (ignored)
input wire IOPB_MGrant; // incoming master grant from OPB
input wire IOPB_retry; // incoming retry request from OPB (ignored)
input wire IOPB_timeout; // incoming timeout signal from opb (ignored)
input wire IOPB_xferAck; // incoming txfer acknowledgement from OPB
 
output wire [0:31] IM_ABus; // output address bus to OPB
output wire [0:3] IM_BE; // output byte enable to OPB
output wire IM_busLock; // output bus lock to OPB (ignored)
output wire [0:31] IM_DBus; // output data bus to OPB
output wire IM_request; // output request for access to OPB
output wire IM_RNW; // read not write
output wire IM_select; // output access control to OPB
output wire IM_seqAddr; // are output addresses sequential? (ignored)
// END IOPB LINK PORTS/WIRES
 
// DEFINE DOPB LINK PORTS/WIRES
input wire [0:31] DOPB_DBus; // incoming data from OPB
input wire DOPB_errAck; // incoming error acknowledge from OPB (ignored)
input wire DOPB_MGrant; // incoming master grant from OPB
input wire DOPB_retry; // incoming retry request from OPB (ignored)
input wire DOPB_timeout; // incoming timeout signal from opb (ignored)
input wire DOPB_xferAck; // incoming txfer acknowledgement from OPB
 
output wire [0:31] DM_ABus; // output address bus to OPB
output wire [0:3] DM_BE; // output byte enable to OPB
output wire DM_busLock; // output bus lock to OPB (ignored)
output wire [0:31] DM_DBus; // output data bus to OPB
output wire DM_request; // output request for access to OPB
output wire DM_RNW; // read not write
output wire DM_select; // output access control to OPB
output wire DM_seqAddr; // are output addresses sequential? (ignored)
// END DOPB LINK PORTS/WIRES
 
wire [31:0] imem_data_rd;
wire [31:0] imem_data2cpu;
wire [31:0] imem_addr;
 
wire [31:0] dmem_data_wr;
wire [31:0] dmem_data_rd;
wire [31:0] dmem_data2mem;
wire [31:0] dmem_data2cpu;
wire [31:0] dmem_addr;
wire dmem_we;
wire dmem_en;
wire PROC_stall;
 
wire reset_correct_polarity;
 
// IOPB WIRES/REGS
wire IOPB_PROC_stall;
wire IOPB_Address;
wire IOPB_Access;
wire [31:0] IOPB_data2PROC;
wire IOPB_ack;
wire IOPB_busy;
// END IOPB WIRES
 
// DOPB WIRES/REGS
wire DOPB_PROC_stall;
wire DOPB_Address;
reg DOPB_Address_dly;
wire DOPB_Access;
wire [31:0] DOPB_data2PROC;
wire DOPB_ack;
wire DOPB_busy;
// END DOPB WIRES
 
always @ (posedge clock) begin
if(reset_correct_polarity) DOPB_Address_dly <= 1'b0;
else DOPB_Address_dly <= (!PROC_stall) ? DOPB_Address : DOPB_Address_dly;
end
 
assign PROC_stall = DOPB_PROC_stall | IOPB_PROC_stall;
 
// IOPB ASSIGNS
assign IOPB_Address = (imem_addr[31] | imem_addr[30] | imem_addr[29] | imem_addr[28]);
assign IOPB_Access = IOPB_Address;
assign imem_data_rd = IOPB_Access ? IOPB_data2PROC : imem_data2cpu;
// END IOPB ASSIGNS
 
// DOPB ASSIGNS
assign DOPB_Address = (dmem_addr[31] | dmem_addr[30] | dmem_addr[29] | dmem_addr[28]);
assign DOPB_Access = DOPB_Address & dmem_en;
assign dmem_data_rd = (DOPB_Address || DOPB_Address_dly) ? DOPB_data2PROC : dmem_data2cpu;
assign dmem_data2mem = dmem_data_wr;
// END DOPB ASSIGNS
 
// Determine polarity (active high or low) or core reset
generate
if(C_EXT_RESET_HIGH) begin : RESET_ACTIVE_HI
assign reset_correct_polarity = reset;
end else begin : RESET_ACTIVE_LOW
assign reset_correct_polarity = ~reset;
end
endgenerate
 
`ifdef FSL_LINK
 
assign FSL0_S_CLK = clock;
assign FSL0_M_CLK = clock;
assign FSL1_S_CLK = clock;
assign FSL1_M_CLK = clock;
assign FSL2_S_CLK = clock;
assign FSL2_M_CLK = clock;
assign FSL3_S_CLK = clock;
assign FSL3_M_CLK = clock;
assign FSL4_S_CLK = clock;
assign FSL4_M_CLK = clock;
assign FSL5_S_CLK = clock;
assign FSL5_M_CLK = clock;
assign FSL6_S_CLK = clock;
assign FSL6_M_CLK = clock;
assign FSL7_S_CLK = clock;
assign FSL7_M_CLK = clock;
assign FSL_M_CLK_DBG = clock;
 
assign FSL_M_CONTROL_DBG = 1'b0;
 
// debugging only... force PC outside
assign FSL_M_WRITE_DBG = ~FSL_M_FULL_DBG;
 
openfire_cpu OPENFIRE0 (
.clock(clock),
.reset(reset_correct_polarity),
.stall(PROC_stall),
.dmem_data_in(dmem_data_rd),
.dmem_data_out(dmem_data_wr),
.dmem_addr(dmem_addr),
.dmem_we(dmem_we),
.dmem_en(dmem_en),
.imem_data_in(imem_data_rd),
.imem_addr(imem_addr),
.pc(FSL_M_DATA_DBG), // PC added for debugging
.fsl0_s_control (FSL0_S_CONTROL),
.fsl0_s_exists (FSL0_S_EXISTS),
.fsl0_m_full (FSL0_M_FULL),
.fsl0_m_control (FSL0_M_CONTROL),
.fsl0_m_write (FSL0_M_WRITE),
.fsl0_s_read (FSL0_S_READ),
.fsl1_s_control (FSL1_S_CONTROL),
.fsl1_s_exists (FSL1_S_EXISTS),
.fsl1_m_full (FSL1_M_FULL),
.fsl1_m_control (FSL1_M_CONTROL),
.fsl1_m_write (FSL1_M_WRITE),
.fsl1_s_read (FSL1_S_READ),
.fsl2_s_control (FSL2_S_CONTROL),
.fsl2_s_exists (FSL2_S_EXISTS),
.fsl2_m_full (FSL2_M_FULL),
.fsl2_m_control (FSL2_M_CONTROL),
.fsl2_m_write (FSL2_M_WRITE),
.fsl2_s_read (FSL2_S_READ),
.fsl3_s_control (FSL3_S_CONTROL),
.fsl3_s_exists (FSL3_S_EXISTS),
.fsl3_m_full (FSL3_M_FULL),
.fsl3_m_control (FSL3_M_CONTROL),
.fsl3_m_write (FSL3_M_WRITE),
.fsl3_s_read (FSL3_S_READ),
.fsl4_s_control (FSL4_S_CONTROL),
.fsl4_s_exists (FSL4_S_EXISTS),
.fsl4_m_full (FSL4_M_FULL),
.fsl4_m_control (FSL4_M_CONTROL),
.fsl4_m_write (FSL4_M_WRITE),
.fsl4_s_read (FSL4_S_READ),
.fsl5_s_control (FSL5_S_CONTROL),
.fsl5_s_exists (FSL5_S_EXISTS),
.fsl5_m_full (FSL5_M_FULL),
.fsl5_m_control (FSL5_M_CONTROL),
.fsl5_m_write (FSL5_M_WRITE),
.fsl5_s_read (FSL5_S_READ),
.fsl6_s_control (FSL6_S_CONTROL),
.fsl6_s_exists (FSL6_S_EXISTS),
.fsl6_m_full (FSL6_M_FULL),
.fsl6_m_control (FSL6_M_CONTROL),
.fsl6_m_write (FSL6_M_WRITE),
.fsl6_s_read (FSL6_S_READ),
.fsl7_s_control (FSL7_S_CONTROL),
.fsl7_s_exists (FSL7_S_EXISTS),
.fsl7_m_full (FSL7_M_FULL),
.fsl7_m_control (FSL7_M_CONTROL),
.fsl7_m_write (FSL7_M_WRITE),
.fsl7_s_read (FSL7_S_READ),
.fsl0_s_data (FSL0_S_DATA),
.fsl1_s_data (FSL1_S_DATA),
.fsl2_s_data (FSL2_S_DATA),
.fsl3_s_data (FSL3_S_DATA),
.fsl4_s_data (FSL4_S_DATA),
.fsl5_s_data (FSL5_S_DATA),
.fsl6_s_data (FSL6_S_DATA),
.fsl7_s_data (FSL7_S_DATA),
.fsl0_m_data (FSL0_M_DATA),
.fsl1_m_data (FSL1_M_DATA),
.fsl2_m_data (FSL2_M_DATA),
.fsl3_m_data (FSL3_M_DATA),
.fsl4_m_data (FSL4_M_DATA),
.fsl5_m_data (FSL5_M_DATA),
.fsl6_m_data (FSL6_M_DATA),
.fsl7_m_data (FSL7_M_DATA) );
`else
openfire_cpu OPENFIRE0 (
.clock(clock),
.reset(reset_correct_polarity),
.stall(PROC_stall),
.dmem_data_in(dmem_data_rd),
.imem_data_in(imem_data_rd),
.dmem_addr(dmem_addr),
.imem_addr(imem_addr),
.dmem_data_out(dmem_data_wr),
.dmem_we(dmem_we),
.dmem_en(dmem_en));
`endif
 
openfire_named_sram_16k MEM(
.dmem_clk(clock),
.dmem_addr((dmem_addr >> 2)),
.dmem_data_i(dmem_data2mem),
.dmem_data_o(dmem_data2cpu),
.dmem_en(1'b1),
.dmem_we(dmem_we & !DOPB_Access),
 
.imem_clk(~clock),
.imem_addr((imem_addr >> 2)),
.imem_data_o(imem_data2cpu),
.imem_en(1'b1)
);
 
// In order to complete instruction Fetch in a single cycle, the read clock
// on the instruction port is inverted. During the first phase of the Fetch
// stage, the PC is supplied to the memory address bus. At the falling edge
// of the clock, this address is clocked into the instruction memory. During
// the second Fetch stage phase the memory fetchs the instruction and places
// it on the data bus. On the next rising edge, the instruction word is
// clocked in and decoded.
 
generate if(C_DOPB_ENABLE) begin: DOPB_MODULE
openfire_opb #(
.C_ENABLE_CSCOPE(C_DOPB_CSCOPE)
) opb0(
.OPB_DBus (DOPB_DBus),
.OPB_errAck (DOPB_errAck),
.OPB_MGrant (DOPB_MGrant),
.OPB_retry (DOPB_retry),
.OPB_timeout (DOPB_timeout),
.OPB_xferAck (DOPB_xferAck),
.M_BE (DM_BE),
.M_ABus (DM_ABus),
.M_busLock (DM_busLock),
.M_DBus (DM_DBus),
.M_request (DM_request),
.M_RNW (DM_RNW),
.M_select (DM_select),
.M_seqAddr (DM_seqAddr),
.PROC_enable (DOPB_Access),
.PROC_we (dmem_we),
.PROC_ABus (dmem_addr),
.PROC_DBus (dmem_data2mem),
.PROC_stall (DOPB_PROC_stall),
.PROC_ack (DOPB_ack),
.OPB_WAIT_ON_OTHERS(IOPB_busy),
.OPB_busy (DOPB_busy),
.OPB_data2PROC (DOPB_data2PROC),
.clock (clock),
.reset (reset_correct_polarity)
);
end endgenerate
 
generate if(C_IOPB_ENABLE) begin: IOPB_MODULE
openfire_opb #(
.C_ENABLE_CSCOPE(C_IOPB_CSCOPE)
) opb1 (
.OPB_DBus (IOPB_DBus),
.OPB_errAck (IOPB_errAck),
.OPB_MGrant (IOPB_MGrant),
.OPB_retry (IOPB_retry),
.OPB_timeout (IOPB_timeout),
.OPB_xferAck (IOPB_xferAck),
.M_BE (IM_BE),
.M_ABus (IM_ABus),
.M_busLock (IM_busLock),
.M_DBus (IM_DBus),
.M_request (IM_request),
.M_RNW (IM_RNW),
.M_select (IM_select),
.M_seqAddr (IM_seqAddr),
.PROC_enable (IOPB_Access),
.PROC_we (1'b0),
.PROC_ABus (imem_addr),
.PROC_DBus (32'h00000000),
.PROC_stall (IOPB_PROC_stall),
.PROC_ack (IOPB_ack),
.OPB_WAIT_ON_OTHERS(1'b0),
.OPB_busy (IOPB_busy),
.OPB_data2PROC (IOPB_data2PROC),
.clock (clock),
.reset (reset_correct_polarity)
);
end endgenerate
 
///////////////////////////////////////////////////////////////////////////////
//
// Chipscope instantiation.
//
 
generate if(C_OF_CSCOPE == 1) begin : OPENFIRE_CHIPSCOPE
 
wire [35:0] control;
wire [31:0] trig0;
wire [31:0] trig1;
wire [31:0] trig2;
wire [31:0] trig3;
wire [31:0] trig4;
wire [31:0] trig5;
wire [31:0] trig6;
wire [31:0] trig7;
assign trig0 = IOPB_DBus;
assign trig1 = imem_addr;
assign trig2 = DOPB_DBus;
assign trig3 = dmem_addr;
assign trig4 = dmem_data2mem;
assign trig5 = DOPB_data2PROC;
assign trig6 = 32'b0;
assign trig7 = {7'b0,
reset_correct_polarity,
dmem_en,
dmem_we,
PROC_stall,
DOPB_MGrant,
DOPB_xferAck,
DM_request,
DM_RNW,
DM_select,
DOPB_Access,
DOPB_Address,
DOPB_Address_dly,
DOPB_PROC_stall,
DOPB_ack,
DOPB_busy,
IOPB_MGrant,
IOPB_xferAck,
IM_request,
IM_RNW,
IM_select,
IOPB_Access,
IOPB_Address,
IOPB_PROC_stall,
IOPB_ack,
IOPB_busy
};
 
ila i_ila
(
.control(control),
.clk(clock),
.trig0(trig0),
.trig1(trig1),
.trig2(trig2),
.trig3(trig3),
.trig4(trig4),
.trig5(trig5),
.trig6(trig6),
.trig7(trig7)
);
icon i_icon
(
.control0(control)
);
end endgenerate
 
endmodule
 
///////////////////////////////////////////////////////////////////////////////
//
// Black box definitions for chipscope modules, if needed.
//
 
module ila
(
control,
clk,
trig0,
trig1,
trig2,
trig3,
trig4,
trig5,
trig6,
trig7
);
input [35:0] control;
input clk;
input [31:0] trig0;
input [31:0] trig1;
input [31:0] trig2;
input [31:0] trig3;
input [31:0] trig4;
input [31:0] trig5;
input [31:0] trig6;
input [31:0] trig7;
endmodule
 
module icon
(
control0
);
output [35:0] control0;
endmodule
 
/trunk/openfire_top_syn/hdl/verilog/openfire_fsl_bus.v
0,0 → 1,97
/*
 
MODULE: openfire_fsl_bus
 
DESCRIPTION: This is a one-way Fast Simplex Link (FSL) bus implementation.
See MicroBlaze documentation for detailed information. This implementation
is 32-bits wide, uses an active high reset, and has a FIFO depth of 1.
 
When creating an OpenFire system using the EDK, this module is not needed.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
module openfire_fsl_bus (
clock, reset,
fsl_s_data, fsl_s_control, fsl_s_exists, fsl_m_full,
fsl_m_data, fsl_m_control, fsl_m_write, fsl_s_read);
 
input clock;
input reset;
 
input [31:0] fsl_m_data;
input fsl_m_control;
input fsl_m_write;
input fsl_s_read;
 
output [31:0] fsl_s_data;
output fsl_s_control;
output fsl_m_full;
output fsl_s_exists;
 
reg fsl_m_full;
reg fsl_s_exists;
 
reg [32:0] fsl_data; // includes control bit
 
assign fsl_s_data = fsl_data[31:0];
assign fsl_s_control = fsl_data[32];
 
always@(posedge clock)
begin
if (reset)
begin
fsl_data <= 0;
fsl_m_full <= 0;
fsl_s_exists <= 0;
end
else
begin
if (fsl_m_write)
begin
fsl_m_full <= 1;
fsl_s_exists <= 1;
fsl_data <= {fsl_m_control, fsl_m_data};
end
if (fsl_s_read)
begin
fsl_s_exists <= 0;
fsl_m_full <= 0;
end
end
end
 
endmodule
/trunk/openfire_top_syn/hdl/verilog/openfire_regfile.v
0,0 → 1,232
/*
 
MODULE: openfire_regfile
 
DESCRIPTION: This module instantiates two, dual-port aynchronous memories. In
Xilinx parts this synthesizes to Select (LUT-based) RAM. To handle half-word
and byte loads, MUXes and a feedback loop are used such that only the desired
portions of the previous word are modified.
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
 
`ifdef FSL_LINK
module openfire_regfile (
reset, clock, // top level
regA_addr, regB_addr, regD_addr, result, pc_regfile, // inputs
dmem_data, regfile_input_sel, we_load_dly, dmem_addr_lsb,
we_alu_branch, fsl_number,
fsl0_s_data, fsl1_s_data, fsl2_s_data, fsl3_s_data,
fsl4_s_data, fsl5_s_data, fsl6_s_data, fsl7_s_data,
regA, regB, regD, enable); // outputs
`else
module openfire_regfile (
reset, clock, // top level
regA_addr, regB_addr, regD_addr, result, pc_regfile, // inputs
dmem_data, regfile_input_sel, we_load_dly, dmem_addr_lsb,
we_alu_branch,
regA, regB, regD, enable); // outputs
`endif
 
// From top level
input reset;
input clock;
 
// From DECODE
input [4:0] regA_addr;
input [4:0] regB_addr;
input [4:0] regD_addr;
input [2:0] regfile_input_sel;
input we_alu_branch;
 
// From EXECUTE
input [`D_WIDTH-1:0] result;
input [`D_WIDTH-1:0] pc_regfile;
input we_load_dly;
input enable;
input [1:0] dmem_addr_lsb;
 
`ifdef FSL_LINK
// From FSL
input [31:0] fsl0_s_data;
input [31:0] fsl1_s_data;
input [31:0] fsl2_s_data;
input [31:0] fsl3_s_data;
input [31:0] fsl4_s_data;
input [31:0] fsl5_s_data;
input [31:0] fsl6_s_data;
input [31:0] fsl7_s_data;
input [2:0] fsl_number;
`endif
 
// From DMEM
input [31:0] dmem_data;
 
output [`D_WIDTH-1:0] regA;
output [`D_WIDTH-1:0] regB;
output [`D_WIDTH-1:0] regD;
 
reg [`D_WIDTH-1:0] input_data;
 
wire write_en;
wire [`D_WIDTH-1:0] extended_pc;
 
// Write to registers on we_alu_branch OR we_load_dly
// UNLESS r0 is the target. r0 MUST always be zero. (|regD_addr) isolates R0
// Allow write on reset to load r0 with zero.
assign write_en = reset ? 1'b1 : (we_alu_branch | we_load_dly) & (|regD_addr) & enable;
 
// extended PC to datapath width
assign extended_pc = pc_regfile;
 
// Input select into REGFILE
`ifdef FSL_LINK
always@(dmem_data or extended_pc or result or regfile_input_sel or dmem_addr_lsb or write_en or clock or
fsl0_s_data or fsl1_s_data or fsl2_s_data or fsl3_s_data or
fsl4_s_data or fsl5_s_data or fsl6_s_data or fsl7_s_data or fsl_number )
`else
always@(dmem_data or extended_pc or result or regfile_input_sel or dmem_addr_lsb or write_en or clock)
`endif
`ifdef DATAPATH_32
begin
case(regfile_input_sel)
`RF_dmem_byte:
case(dmem_addr_lsb) // selects which Byte to update in registers
2'b00: input_data <= {24'b0, dmem_data[31:24]};
2'b01: input_data <= {24'b0, dmem_data[23:16]};
2'b10: input_data <= {24'b0, dmem_data[15:8]};
2'b11: input_data <= {24'b0, dmem_data[7:0]};
endcase
`RF_dmem_halfword:
case(dmem_addr_lsb) // selects which half-word to update
2'b00: input_data <= {16'b0, dmem_data[31:16]};
default: // unaligned access!
begin
input_data <= {16'b0, dmem_data[15:0]};
if(write_en & ~clock & (dmem_addr_lsb ==2'b10)) $display("ERROR! Unaligned HalfWord Load at PC %x", pc_regfile);
end
endcase
`RF_dmem_wholeword: input_data <= dmem_data;
`RF_alu_result: input_data <= result;
`RF_pc: input_data <= extended_pc;
`RF_zero: input_data <= 0;
`ifdef FSL_LINK
`RF_fsl: begin
case (fsl_number)
0 : input_data <= fsl0_s_data;
1 : input_data <= fsl1_s_data;
2 : input_data <= fsl2_s_data;
3 : input_data <= fsl3_s_data;
4 : input_data <= fsl4_s_data;
5 : input_data <= fsl5_s_data;
6 : input_data <= fsl6_s_data;
7 : input_data <= fsl7_s_data;
default : input_data <= 32'hDEADBEEF;
endcase
end
`endif
default:
begin
input_data <= 0; // for simulation
if(write_en & ~clock) $display("ERROR! REGFILE input selector set to illegal value %d at PC %x", regfile_input_sel, pc_regfile);
end
endcase
end
`else // 16-bit datapath!
begin
case(regfile_input_sel)
`RF_dmem_byte:
case(dmem_addr_lsb) // selects which Byte to update in registers
2'b00: input_data <= {8'b0, dmem_data[31:24]};
2'b01: input_data <= {8'b0, dmem_data[23:16]};
2'b10: input_data <= {8'b0, dmem_data[15:8]};
2'b11: input_data <= {8'b0, dmem_data[7:0]};
endcase
`RF_dmem_halfword:
case(dmem_addr_lsb) // selects which half-word to update
2'b00: input_data <= dmem_data[31:16];
2'b10: input_data <= dmem_data[15:0];
default: // unaligned access!
begin
input_data <= dmem_data[31:16];
if(write_en & ~clock) $display("ERROR! Unaligned HalfWord Load at PC %x", pc_regfile);
end
endcase
`RF_dmem_wholeword:
case(dmem_addr_lsb)
2'b00: input_data <= dmem_data[15:0];
default: // unaligned access!
begin
input_data <= dmem_data;
if(write_en & ~clock) $display("ERROR! Unaligned Word Load at PC %x", pc_regfile);
end
endcase
`RF_alu_result: input_data <= result;
`RF_pc: input_data <= extended_pc;
`RF_zero: input_data <= 0;
`ifdef FSL_LINK
`RF_fsl:
case (fsl_number)
0 : input_data <= fsl0_s_data[15:0];
1 : input_data <= fsl1_s_data[15:0];
2 : input_data <= fsl2_s_data[15:0];
3 : input_data <= fsl3_s_data[15:0];
4 : input_data <= fsl4_s_data[15:0];
5 : input_data <= fsl5_s_data[15:0];
6 : input_data <= fsl6_s_data[15:0];
7 : input_data <= fsl7_s_data[15:0];
default : input_data <= 16'hBEEF;
endcase
end
`endif
default:
begin
input_data <= 0;
if(write_en & ~clock) $display("ERROR! REGFILE input selector set to illegal value %d at PC %x", regfile_input_sel, pc_regfile);
end
endcase
end
`endif
 
// We need a 3-port register file -- create from 2, 2-port SRAMs
// Tie write ports together
openfire_rf_sram RF_BANK0 (.clock(clock), .read_addr(regA_addr),
.write_addr(regD_addr), .data_in(input_data),
.we(write_en), .read_data_out(regA), .write_data_out(regD));
 
openfire_rf_sram RF_BANK1 (.clock(clock), .read_addr(regB_addr),
.write_addr(regD_addr), .data_in(input_data),
.we(write_en), .read_data_out(regB));
endmodule
/trunk/openfire_top_syn/hdl/verilog/openfire_opb.v
0,0 → 1,240
 
`timescale 1 ns / 100 ps
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
module openfire_opb (
OPB_DBus, OPB_errAck, OPB_MGrant, OPB_retry, OPB_timeout, OPB_xferAck,
M_BE, M_ABus, M_busLock, M_DBus, M_request, M_RNW, M_select, M_seqAddr,
PROC_enable, PROC_we, PROC_ABus, PROC_DBus, PROC_stall, OPB_data2PROC,
PROC_ack, OPB_busy, OPB_WAIT_ON_OTHERS, clock, reset
);
 
parameter C_ENABLE_CSCOPE = 0;
 
////////// Incoming from OPB //////////
input wire [31:0] OPB_DBus; // incoming data from OPB
input wire OPB_errAck; // incoming error acknowledge from OPB (ignored)
input wire OPB_MGrant; // incoming master grant from OPB
input wire OPB_retry; // incoming retry request from OPB (ignored)
input wire OPB_timeout; // incoming timeout signal from opb (ignored)
input wire OPB_xferAck; // incoming txfer acknowledgement from OPB
 
////////// Outgoing to OPB //////////
output wire [0:3] M_BE; // output byte enable to OPB
output wire [0:31] M_ABus; // output address bus to OPB - registered
output wire M_busLock; // output bus lock to OPB (ignored)
output wire [0:31] M_DBus; // output data bus to OPB
output wire M_request; // output request for access to OPB
output wire M_RNW; // read not write
output wire M_select; // output access control to OPB
output wire M_seqAddr; // are output addresses sequential? (ignored)
 
////////// Incoming from OpenFire //////////
input wire PROC_enable; // incoming request from processor
input wire PROC_we; // write enable
input wire [31:0] PROC_ABus; // incoming address bus from processor
input wire [31:0] PROC_DBus; // incoming data from processor
input wire OPB_WAIT_ON_OTHERS;
 
////////// Outgoing to OpenFire //////////
output wire OPB_busy; // OPB bus is busy (Request, TX, Timeout, Retry)
output wire PROC_stall; // stall out to processor during OPB r/w
output wire PROC_ack; // ackknowledge transaction back to OpenFire
output reg [31:0] OPB_data2PROC; // data out to processor
 
////////// Internals //////////
input wire clock, reset;
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
 
localparam STATE_WAIT_EN = 16'b0000_0000_0000_0001;
localparam STATE_REQ_ACS = 16'b0000_0000_0000_0010;
localparam STATE_TXRX = 16'b0000_0000_0000_0100;
localparam STATE_DONE = 16'b0000_0000_0000_1000;
//localparam STATE_TIMEOUT = 16'b0000_0000_0001_0000;
localparam STATE_RETRY = 16'b0000_0000_0010_0000;
 
reg [15:0] currstate, nextstate;
reg [31:0] PROC_ABus_latch, PROC_DBus_latch;
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
wire stall_states = ((currstate == STATE_REQ_ACS) ||
(currstate == STATE_TXRX) ||
(currstate == STATE_RETRY));
wire nostall_states = (currstate == STATE_DONE);
//wire nostall_states = ((currstate == STATE_DONE) ||
// (currstate == STATE_TIMEOUT));
assign PROC_stall = (stall_states || PROC_enable) && !(nostall_states);
 
assign PROC_ack = (currstate == STATE_DONE);
assign M_BE = (currstate == STATE_TXRX) ? 4'b1111 : 4'b0000;
assign M_busLock = 1'b0;
assign M_request = currstate == STATE_REQ_ACS;
assign M_RNW = (currstate == STATE_TXRX) ? !PROC_we : 1'b0;
assign M_select = currstate == STATE_TXRX;
assign M_seqAddr = 1'b0;
assign OPB_busy = (currstate == STATE_REQ_ACS) || (currstate == STATE_TXRX) || (currstate == STATE_RETRY);
 
assign M_ABus = M_select ? PROC_ABus_latch : 32'b0;
assign M_DBus = M_select & PROC_we ? PROC_DBus_latch : 32'b0;
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
 
always @ (posedge clock or posedge reset) begin
if(reset) begin
currstate <= STATE_WAIT_EN;
OPB_data2PROC <= 32'h0;
end else begin
currstate <= nextstate;
 
OPB_data2PROC <= (OPB_xferAck & M_RNW) ? OPB_DBus : OPB_data2PROC; // might want to set this to zero
end
end
 
always @ (posedge clock or posedge reset) begin
if(reset) begin
PROC_ABus_latch <= 32'h0;
PROC_DBus_latch <= 32'h0;
end else begin
if(currstate == STATE_WAIT_EN) begin
PROC_ABus_latch <= PROC_ABus;
PROC_DBus_latch <= PROC_DBus;
end
end
end
 
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
 
wire bus_timeout, bus_retry;
assign bus_timeout = OPB_timeout & !(OPB_xferAck | OPB_retry);
assign bus_retry = OPB_retry;
 
always @ (currstate or nextstate or PROC_enable or PROC_we or PROC_ABus
or PROC_DBus or OPB_DBus or OPB_errAck or OPB_MGrant or OPB_retry
or OPB_timeout or OPB_xferAck or bus_timeout or bus_retry) begin
 
if(currstate & STATE_WAIT_EN) nextstate = PROC_enable ? STATE_REQ_ACS : STATE_WAIT_EN;
else if(currstate & STATE_REQ_ACS) nextstate = OPB_MGrant ? STATE_TXRX : STATE_REQ_ACS;
else if(currstate & STATE_TXRX) begin
if(OPB_xferAck) nextstate = STATE_DONE;
else if(bus_timeout) nextstate = STATE_DONE;
// else if(bus_timeout) nextstate = STATE_TIMEOUT;
else if(bus_retry) nextstate = STATE_RETRY;
else nextstate = STATE_TXRX;
end
else if(currstate & STATE_DONE) nextstate = OPB_WAIT_ON_OTHERS ? STATE_DONE : STATE_WAIT_EN;
// else if(currstate & STATE_TIMEOUT) nextstate = OPB_WAIT_ON_OTHERS ? STATE_TIMEOUT : STATE_WAIT_EN;
else if(currstate & STATE_RETRY) nextstate = STATE_REQ_ACS;
else nextstate = STATE_WAIT_EN;
end
 
///////////////////////////////////////////////////////////////////////////////
//
// Chipscope instantiation.
//
 
generate if(C_ENABLE_CSCOPE == 1) begin : OPB_CHIPSCOPE
 
wire [35:0] control;
wire [31:0] trig0;
wire [31:0] trig1;
wire [31:0] trig2;
wire [31:0] trig3;
wire [31:0] trig4;
wire [31:0] trig5;
wire [31:0] trig6;
wire [31:0] trig7;
assign trig0 = OPB_DBus;
assign trig1 = M_ABus;
assign trig2 = M_DBus;
assign trig3 = PROC_ABus;
assign trig4 = PROC_DBus;
assign trig5 = OPB_data2PROC;
assign trig6 = {currstate,nextstate};
assign trig7 = {12'b0,
OPB_errAck,
OPB_MGrant,
OPB_retry,
OPB_timeout,
OPB_xferAck,
M_BE, // 4 bits
M_busLock,
M_request,
M_RNW,
M_select,
M_seqAddr,
PROC_enable,
PROC_we,
OPB_WAIT_ON_OTHERS,
OPB_busy,
PROC_stall,
PROC_ack
};
 
ila i_ila
(
.control(control),
.clk(clock),
.trig0(trig0),
.trig1(trig1),
.trig2(trig2),
.trig3(trig3),
.trig4(trig4),
.trig5(trig5),
.trig6(trig6),
.trig7(trig7)
);
icon i_icon
(
.control0(control)
);
end endgenerate
 
endmodule
 
///////////////////////////////////////////////////////////////////////////////
//
// Black box definitions for chipscope modules, if needed.
//
/*
module ila
(
control,
clk,
trig0,
trig1,
trig2,
trig3,
trig4,
trig5,
trig6,
trig7
);
input [35:0] control;
input clk;
input [31:0] trig0;
input [31:0] trig1;
input [31:0] trig2;
input [31:0] trig3;
input [31:0] trig4;
input [31:0] trig5;
input [31:0] trig6;
input [31:0] trig7;
endmodule
 
 
module icon
(
control0
);
output [35:0] control0;
endmodule*/
/trunk/openfire_top_syn/hdl/verilog/openfire_execute.v
0,0 → 1,602
/*
 
MODULE: openfire_execute
 
DESCRIPTION: The execute module instantiates the alu and comparator and
updates the Machine Status Register (MSR). This module produces a status
signal, instr_complete, when the currently executing instruction is finished.
 
TO DO:
- Add interrupt handling
- Add exception handling
- Complete MSR
- Add all other special registers: EAR, ESR, ESS
- Add OPB interface
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug and CMP bug for case when both rA and rB are negative.
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
`ifdef FSL_LINK
module openfire_execute (
clock, reset, stall, // top level
immediate, pc_exe, alu_inputA_sel, alu_inputB_sel, // inputs
alu_inputC_sel, alu_fns_sel, comparator_fns_sel,
we_load, we_store, regA, dmem_input_sel,
regB, regD, update_carry, dmem_data_in, branch_instr,
fsl_number, fsl_cmd_vld, fsl_get, fsl_blocking, fsl_control, //FSL
alu_result, pc_branch, branch_taken, // outputs
we_regfile, we_store_dly, dmem_addr,
dmem_data_out, instr_complete, byte_sel,
fsl0_s_control, fsl0_s_exists, fsl0_m_full, fsl0_m_control, fsl0_m_write, fsl0_s_read,
fsl1_s_control, fsl1_s_exists, fsl1_m_full, fsl1_m_control, fsl1_m_write, fsl1_s_read,
fsl2_s_control, fsl2_s_exists, fsl2_m_full, fsl2_m_control, fsl2_m_write, fsl2_s_read,
fsl3_s_control, fsl3_s_exists, fsl3_m_full, fsl3_m_control, fsl3_m_write, fsl3_s_read,
fsl4_s_control, fsl4_s_exists, fsl4_m_full, fsl4_m_control, fsl4_m_write, fsl4_s_read,
fsl5_s_control, fsl5_s_exists, fsl5_m_full, fsl5_m_control, fsl5_m_write, fsl5_s_read,
fsl6_s_control, fsl6_s_exists, fsl6_m_full, fsl6_m_control, fsl6_m_write, fsl6_s_read,
fsl7_s_control, fsl7_s_exists, fsl7_m_full, fsl7_m_control, fsl7_m_write, fsl7_s_read
);
`else
module openfire_execute (
clock, reset, stall, // top level
immediate, pc_exe, alu_inputA_sel, alu_inputB_sel, // inputs
alu_inputC_sel, alu_fns_sel, comparator_fns_sel,
we_load, we_store, regA, dmem_input_sel,
regB, regD, update_carry, dmem_data_in, branch_instr,
alu_result, pc_branch, branch_taken, // outputs
we_regfile, we_store_dly, dmem_addr,
dmem_data_out, instr_complete, byte_sel);
`endif
// From top level -- all active high unless otherwise noted
input stall;
input reset;
input clock;
 
// From DECODE module
input [`D_WIDTH-1:0] immediate;
input [`D_WIDTH-1:0] pc_exe; // pc for use by EXECUTE
input [1:0] alu_inputA_sel;
input [1:0] alu_inputB_sel;
input [1:0] alu_inputC_sel;
input [3:0] alu_fns_sel;
input [2:0] comparator_fns_sel;
input we_load; // write_en for regfile on Load
input we_store; // write_en for DMEM on Store
input update_carry;
input [1:0] dmem_input_sel;
input branch_instr;
 
`ifdef FSL_LINK
//From Decode Logic
input fsl_get;
input fsl_control;
input fsl_blocking;
input fsl_cmd_vld;
input [2:0] fsl_number;
 
//From FSL Ports
input wire fsl0_s_control;
input wire fsl0_s_exists;
input wire fsl0_m_full;
output reg fsl0_m_control;
output reg fsl0_m_write;
output reg fsl0_s_read;
 
input wire fsl1_s_control;
input wire fsl1_s_exists;
input wire fsl1_m_full;
output reg fsl1_m_control;
output reg fsl1_m_write;
output reg fsl1_s_read;
 
input wire fsl2_s_control;
input wire fsl2_s_exists;
input wire fsl2_m_full;
output reg fsl2_m_control;
output reg fsl2_m_write;
output reg fsl2_s_read;
 
input wire fsl3_s_control;
input wire fsl3_s_exists;
input wire fsl3_m_full;
output reg fsl3_m_control;
output reg fsl3_m_write;
output reg fsl3_s_read;
 
input wire fsl4_s_control;
input wire fsl4_s_exists;
input wire fsl4_m_full;
output reg fsl4_m_control;
output reg fsl4_m_write;
output reg fsl4_s_read;
 
input wire fsl5_s_control;
input wire fsl5_s_exists;
input wire fsl5_m_full;
output reg fsl5_m_control;
output reg fsl5_m_write;
output reg fsl5_s_read;
 
input wire fsl6_s_control;
input wire fsl6_s_exists;
input wire fsl6_m_full;
output reg fsl6_m_control;
output reg fsl6_m_write;
output reg fsl6_s_read;
 
input wire fsl7_s_control;
input wire fsl7_s_exists;
input wire fsl7_m_full;
output reg fsl7_m_control;
output reg fsl7_m_write;
output reg fsl7_s_read;
 
//Internal
reg fsl_complete;
 
//Internal, Assigned to fsl[fsl_number]
reg fsl_s_control;
reg fsl_s_exists;
reg fsl_m_full;
 
reg fsl_m_control;
reg fsl_m_write;
reg fsl_s_read;
 
always @ (fsl_number or fsl0_s_control or fsl0_s_exists or fsl0_m_full or
fsl1_s_control or fsl1_s_exists or fsl1_m_full or
fsl2_s_control or fsl2_s_exists or fsl2_m_full or
fsl3_s_control or fsl3_s_exists or fsl3_m_full or
fsl4_s_control or fsl4_s_exists or fsl4_m_full or
fsl5_s_control or fsl5_s_exists or fsl5_m_full or
fsl6_s_control or fsl6_s_exists or fsl6_m_full or
fsl7_s_control or fsl7_s_exists or fsl7_m_full ) begin
fsl0_m_control= 0;
fsl0_m_write = 0;
fsl0_s_read = 0;
fsl1_m_control= 0;
fsl1_m_write = 0;
fsl1_s_read = 0;
fsl2_m_control= 0;
fsl2_m_write = 0;
fsl2_s_read = 0;
fsl3_m_control= 0;
fsl3_m_write = 0;
fsl3_s_read = 0;
fsl4_m_control= 0;
fsl4_m_write = 0;
fsl4_s_read = 0;
fsl5_m_control= 0;
fsl5_m_write = 0;
fsl5_s_read = 0;
fsl6_m_control= 0;
fsl6_m_write = 0;
fsl6_s_read = 0;
fsl7_m_control= 0;
fsl7_m_write = 0;
fsl7_s_read = 0;
 
case (fsl_number)
0 : begin
fsl_s_control = fsl0_s_control;
fsl_s_exists = fsl0_s_exists;
fsl_m_full = fsl0_m_full;
fsl0_m_control= fsl_m_control;
fsl0_m_write = fsl_m_write;
fsl0_s_read = fsl_s_read;
end
1 : begin
fsl_s_control = fsl1_s_control;
fsl_s_exists = fsl1_s_exists;
fsl_m_full = fsl1_m_full;
fsl1_m_control= fsl_m_control;
fsl1_m_write = fsl_m_write;
fsl1_s_read = fsl_s_read;
end
2 : begin
fsl_s_control = fsl2_s_control;
fsl_s_exists = fsl2_s_exists;
fsl_m_full = fsl2_m_full;
fsl2_m_control= fsl_m_control;
fsl2_m_write = fsl_m_write;
fsl2_s_read = fsl_s_read;
end
3 : begin
fsl_s_control = fsl3_s_control;
fsl_s_exists = fsl3_s_exists;
fsl_m_full = fsl3_m_full;
fsl3_m_control= fsl_m_control;
fsl3_m_write = fsl_m_write;
fsl3_s_read = fsl_s_read;
end
4 : begin
fsl_s_control = fsl4_s_control;
fsl_s_exists = fsl4_s_exists;
fsl_m_full = fsl4_m_full;
fsl4_m_control= fsl_m_control;
fsl4_m_write = fsl_m_write;
fsl4_s_read = fsl_s_read;
end
5 : begin
fsl_s_control = fsl5_s_control;
fsl_s_exists = fsl5_s_exists;
fsl_m_full = fsl5_m_full;
fsl5_m_control= fsl_m_control;
fsl5_m_write = fsl_m_write;
fsl5_s_read = fsl_s_read;
end
6 : begin
fsl_s_control = fsl6_s_control;
fsl_s_exists = fsl6_s_exists;
fsl_m_full = fsl6_m_full;
fsl6_m_control= fsl_m_control;
fsl6_m_write = fsl_m_write;
fsl6_s_read = fsl_s_read;
end
7 : begin
fsl_s_control = fsl7_s_control;
fsl_s_exists = fsl7_s_exists;
fsl_m_full = fsl7_m_full;
fsl7_m_control= fsl_m_control;
fsl7_m_write = fsl_m_write;
fsl7_s_read = fsl_s_read;
end
default : begin // pointless b/c fsl_number only has 3 bits
fsl_s_control = 0;
fsl_s_exists = 0;
fsl_m_full = 0;
end
endcase
end
 
`endif
 
// From REGFILE
input [`D_WIDTH-1:0] regA;
input [`D_WIDTH-1:0] regB;
input [`D_WIDTH-1:0] regD;
 
// From Data MEM
input [31:0] dmem_data_in;
 
output [`D_WIDTH-1:0] alu_result;
output [`D_WIDTH-1:0] pc_branch;
output branch_taken;
output we_regfile; // delayed versions for we for loads & stores
output we_store_dly; // load/store is a 2-cycle operation
output [31:0] dmem_addr;
output [31:0] dmem_data_out;
output instr_complete; // status of execution, active high
output [1:0] byte_sel;
 
// register all outputs EXCEPT:
// - branch_taken and pc_branch -- registered in FETCH
// - alu_result -- REGFILE registers
// - dmem_addr -- DMEM registers
// - instr_complete -- needed before rise of clock by PIPLINE_CTRL
reg we_load_dly;
reg we_store_dly;
reg [31:0] dmem_data_out;
reg [1:0] byte_sel;
 
// internal registers
reg [31:0] MSR; // not implemented yet EXCEPT for C bit
reg [`D_WIDTH-1:0] alu_a_input;
reg [`D_WIDTH-1:0] alu_b_input;
reg alu_c_input;
reg MSB_signed_compare;
 
wire alu_multicycle_instr;
wire alu_multicycle_instr_complete;
wire multicycle_instr;
wire multicycle_instr_complete;
wire c_out;
wire compare_out;
wire [`D_WIDTH-1:0] alu_out_internal;
wire [`D_WIDTH-1:0] extended_pc; // PC with leading zeros addded
 
assign branch_taken = branch_instr ? compare_out : 0;
assign pc_branch = alu_out_internal; // ALU calculates next instr address
 
// instr_complete is always high EXCEPT for load / store instructions and optional MUL (alu_multicycle_instr)
// all other instructions currently implemented are single-cycle execution
 
// instr_complete is low when we_load / we_store is asserted UNLESS the delayed version
// is also high... this is because DECODE stalls during a load / store
// and therefore cannot lower we_load / we_store
`ifdef FSL_LINK
assign multicycle_instr = we_load | we_store | fsl_cmd_vld | alu_multicycle_instr;
assign multicycle_instr_complete = we_load_dly | we_store_dly | fsl_complete | alu_multicycle_instr_complete;
`else
assign multicycle_instr = we_load | we_store | alu_multicycle_instr;
assign multicycle_instr_complete = we_load_dly | we_store_dly | alu_multicycle_instr_complete;
`endif
assign instr_complete = ~multicycle_instr | multicycle_instr_complete;
 
assign we_regfile = we_load_dly | alu_multicycle_instr_complete;
 
// for CMP/CMPU
// use comparator output for CMPU
// use ALU output for CMP -- signed comparison result is a function of input signs and output sign
assign alu_result[`D_WIDTH-1] = (alu_fns_sel == `ALU_compare_uns) ? compare_out :
(alu_fns_sel == `ALU_compare) ? MSB_signed_compare :
alu_out_internal[`D_WIDTH-1];
assign alu_result[`D_WIDTH-2:0] = alu_out_internal[`D_WIDTH-2:0];
 
always@(regA[`D_WIDTH-1] or regB[`D_WIDTH-1] or alu_out_internal[`D_WIDTH-1])
begin
case ({regB[`D_WIDTH-1], regA[`D_WIDTH-1]}) // look at signs of input numbers
2'b00: MSB_signed_compare <= alu_out_internal[`D_WIDTH-1]; // both inputs positive
2'b01: MSB_signed_compare <= 0; // A is negative, B is positive => B is greater
2'b10: MSB_signed_compare <= 1; // B is negative, A is positive => A is greater
2'b11: MSB_signed_compare <= alu_out_internal[`D_WIDTH-1]; // both inputs negative
endcase
end
 
// extend PC to datapath width to store in Reg File (extension no longer
// required - ARM).
assign extended_pc = pc_exe;
 
 
// Stateful logic to handle multi-cycle instructions
always@(posedge clock)
begin
if(reset)
begin
byte_sel <= 0;
we_load_dly <= 0;
we_store_dly <= 0;
MSR <= 0;
`ifdef FSL_LINK
fsl_complete <= 0;
fsl_m_write <= 0;
fsl_s_read <= 0;
`endif
end
else if (~stall)
begin
byte_sel <= dmem_addr[1:0];
// Update Carry Bit in Status Register
if ((alu_fns_sel == `ALU_add) & update_carry)
MSR[2] <= c_out;
if ((alu_fns_sel == `ALU_shiftR_arth) | (alu_fns_sel == `ALU_shiftR_log) |
(alu_fns_sel == `ALU_shiftR_c))
MSR[2] <= regA[0];
// TBD - SHOULD THIS REALLY STILL BE 2 STATEMENTS?
// WAS ONE STATEMENT ORIGINALLY!
if (we_load & we_load_dly)
we_load_dly <= 0;
else
we_load_dly <= we_load;
 
if (we_store & we_store_dly)
we_store_dly <= 0;
else
we_store_dly <= we_store;
 
// We have completed a Load / Store Instruction and been issued another one
/* if ((we_load & we_load_dly) | (we_store & we_store_dly))
begin
we_load_dly <= 0;
we_store_dly <= 0;
end
else
begin
we_store_dly <= we_store;
we_load_dly <= we_load;
end*/
`ifdef FSL_LINK
// FSL get & put commands
// Reset control signals after write / read
if ((fsl_cmd_vld & fsl_complete) | ~fsl_cmd_vld)
begin
fsl_s_read <= 0;
fsl_complete <= 0;
fsl_m_write <= 0;
end
else if (fsl_cmd_vld & ~fsl_get & ~fsl_blocking) // nonblocking put
begin
fsl_complete <= 1;
MSR[2] <= fsl_m_full;
if (~fsl_m_full)
begin
fsl_m_write <= 1;
fsl_m_control <= fsl_control;
end
end
else if (fsl_cmd_vld & fsl_get & ~fsl_blocking) // nonblocking get
begin
fsl_complete <= 1;
fsl_s_read <= 1;
MSR[2] <= ~fsl_s_exists;
if (fsl_s_exists)
we_load_dly <= 1;
if (fsl_s_control == fsl_control)
MSR[4] <= 0; // MSR[4] = FSL_Error bit
else
MSR[4] <= 1;
end
else if (fsl_cmd_vld & ~fsl_get & ~fsl_m_full & fsl_blocking) // blocking put
begin
fsl_complete <= 1;
fsl_m_write <= 1;
fsl_m_control <= fsl_control;
end
else if (fsl_cmd_vld & fsl_get & fsl_s_exists & fsl_blocking) // blocking get
begin
fsl_complete <= 1;
we_load_dly <= 1;
fsl_s_read <= 1;
if (fsl_s_control == fsl_control)
MSR[4] <= 0;
else
MSR[4] <= 1;
end
`endif // End FSL extensions
end // end elseif (~stall)
end // always@
 
/**************************
* Module input selectors *
**************************/
always@(alu_inputA_sel or extended_pc or regA)
begin
case(alu_inputA_sel)
`aluA_ra: alu_a_input <= regA;
`aluA_ra_bar: alu_a_input <= ~regA;
`aluA_pc: alu_a_input <= extended_pc;
`aluA_zero: alu_a_input <= 0;
endcase
end // always @ ALU_input_A
 
always@(alu_inputB_sel or immediate or regB)
begin
case(alu_inputB_sel)
`aluB_rb: alu_b_input <= regB;
`aluB_imm: alu_b_input <= immediate;
`aluB_rb_bar: alu_b_input <= ~regB;
`aluB_imm_bar: alu_b_input <= ~immediate;
endcase
end // always @ ALU_input_B
 
always@(alu_inputC_sel or MSR)
begin
case(alu_inputC_sel)
`aluC_zero: alu_c_input <= 1'b0;
`aluC_one: alu_c_input <= 1'b1;
`aluC_carry: alu_c_input <= MSR[2];
default:
begin // for simulation
$display("ERROR! Illegal ALU Input Selection! PC %x", pc_exe);
alu_c_input <= 1'b0;
end
endcase
end // always @ ALU_input_C
 
// Data MEM input selection
`ifdef DATAPATH_32
always@(dmem_data_in or dmem_input_sel or regD or dmem_addr[1:0] or we_store_dly)
begin
case(dmem_input_sel)
2'b00: // Byte Store
case(dmem_addr[1:0])
2'b00: dmem_data_out <= {regD[7:0], dmem_data_in[23:0]};
2'b01: dmem_data_out <= {dmem_data_in[31:24], regD[7:0], dmem_data_in[15:0]};
2'b10: dmem_data_out <= {dmem_data_in[31:16], regD[7:0], dmem_data_in[7:0]};
2'b11: dmem_data_out <= {dmem_data_in[31:8], regD[7:0]};
endcase
2'b01: // Halfword Store
case(dmem_addr[1:0])
2'b00: dmem_data_out <= {regD[15:0], dmem_data_in[15:0]};
2'b10: dmem_data_out <= {dmem_data_in[31:16], regD[15:0]};
default:
begin
dmem_data_out <= {regD[15:0], dmem_data_in[15:0]};
if(we_store_dly) $display("ERROR! Unaligned Halfword Store at pc %x", pc_exe);
end
endcase
2'b10: // Word Store
case(dmem_addr[1:0])
2'b00: dmem_data_out <= regD;
default:
begin
dmem_data_out <= regD;
if(we_store_dly) $display("ERROR! Unaligned Word Store at pc %x", pc_exe);
end
endcase
default:
begin
if(we_store_dly) $display("ERROR! Illegal Word Size Selection! PC %x", pc_exe);
dmem_data_out <= 0;
end
endcase
end
`else // 16-bit datapath
// Currently 16-bit datapath interfaces with a 32-bit memory
always@(dmem_data_in or dmem_input_sel or regD or dmem_addr[1:0] or we_store_dly)
begin
case(dmem_input_sel)
2'b00: // Byte Store
case(dmem_addr[1:0])
2'b00: dmem_data_out <= {regD[7:0], dmem_data_in[23:0]};
2'b01: dmem_data_out <= {dmem_data_in[31:24], regD[7:0], dmem_data_in[15:0]};
2'b10: dmem_data_out <= {dmem_data_in[31:16], regD[7:0], dmem_data_in[7:0]};
2'b11: dmem_data_out <= {dmem_data_in[31:8], regD[7:0]};
endcase
2'b01: // Halfword Store
case(dmem_addr[1:0])
2'b00: dmem_data_out <= {regD[15:0], dmem_data_in[15:0]};
2'b10: dmem_data_out <= {dmem_data_in[31:16], regD[15:0]};
default:
begin
dmem_data_out <= {regD[15:0], dmem_data_in[15:0]};
if(we_store_dly) $display("ERROR! Unaligned Halfword Store at pc %x", pc_exe);
end
endcase
2'b10: // Word Store
case(dmem_addr[1:0])
2'b00: dmem_data_out <= {16'b0, regD[15:0]};
default:
begin
dmem_data_out <= regD;
if(we_store_dly) $display("ERROR! Unaligned Word Store at pc %x", pc_exe);
end
endcase
default:
begin
if(we_store_dly) $display("ERROR! Illegal Word Size Selection! PC %x", pc_exe);
dmem_data_out <= 0;
end
endcase
end
`endif
 
// Instantiate ALU and comparator
openfire_alu ALU0 (.clock(clock), .reset(reset), .stall(stall),
.a(alu_a_input), .b(alu_b_input), .c_in(alu_c_input), .fns(alu_fns_sel),
.alu_result(alu_out_internal), .c_out(c_out),
.alu_multicycle_instr(alu_multicycle_instr), .dmem_addr(dmem_addr),
.alu_multicycle_instr_complete(alu_multicycle_instr_complete));
// comparator used only for branches (and optional CMPU instruction)
// DECODE unit forces COMPARE output high for unconditional branchs by selecting a 1 output
// with comparator_fns_sel
openfire_compare CMP0 (.in0(regA), .in1(regB), .out(compare_out), .fns(comparator_fns_sel));
 
endmodule
/trunk/openfire_top_syn/hdl/verilog/openfire_decode.v
0,0 → 1,342
/*
 
MODULE: openfire_decode
 
DESCRIPTION: The decode module received the instruction from the fetch module
and produces all control signals needed by the execute stage and the register
file. In the case of IMM instructions, the decode module will stall the
execute module by issuing a NoOp instruction.
 
The COMPARE module is used for calculating if a branch is taken and CMPU
ops if support is selected. The DECODE module commands the comparator to output
a 1 for unconditional branchs and a 0 for all other non-branch instructions (other
than CMPU)..
 
While FSL instructions are optionally implemented (if FSL_LINK is defined),
only one link (FSL0) is currently supported.
 
MISSING INSTRUCTIONS:
- all special register instruction: MFS, MSRCLR, MSRSET, MTS
- all instructions requiring extra hardware, except for optional multiply: IDIV, BS
- cache-related instruction: WDC, WIC
 
TO DO:
- Complete instruction set
- Simplify instruction extension
 
AUTHOR:
Stephen Douglas Craven
Configurable Computing Lab
Virginia Tech
scraven@vt.edu
 
REVISION HISTORY:
Revision 0.2, 8/10/2005 SDC
Initial release
 
Revision 0.3, 12/17/2005 SDC
Fixed PC size bug
 
COPYRIGHT:
Copyright (c) 2005 Stephen Douglas Craven
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 
*/
 
`ifdef FSL_LINK
module openfire_decode(
clock, stall, reset, // top level
pc_decode, instruction, flush, // inputs
regA_addr, regB_addr, regD_addr, immediate, // outputs
alu_inputA_sel, alu_inputB_sel, alu_inputC_sel,
alu_fns_sel, comparator_fns_sel, branch_instr,
we_alu_branch, we_load, we_store, regfile_input_sel,
dmem_input_sel, delay_bit, update_carry, pc_exe,
fsl_get, fsl_control, fsl_blocking, fsl_cmd_vld, fsl_number);// fsl signals
`else
module openfire_decode(
clock, stall, reset, // top level
pc_decode, instruction, flush, // inputs
regA_addr, regB_addr, regD_addr, immediate, // outputs
alu_inputA_sel, alu_inputB_sel, alu_inputC_sel,
alu_fns_sel, comparator_fns_sel, branch_instr,
we_alu_branch, we_load, we_store, regfile_input_sel,
dmem_input_sel, delay_bit, update_carry, pc_exe);
`endif
 
// From top level -- all active high unless otherwise noted
input stall;
input reset;
input clock;
 
// From DECODE module
input [`D_WIDTH-1:0] pc_decode;
input [31:0] instruction;
 
// From Pipeline Controller
input flush; // a branch was taken... flush the pipeline
 
output [4:0] regA_addr;
output [4:0] regB_addr;
output [4:0] regD_addr;
output [`D_WIDTH-1:0] immediate;
output [`D_WIDTH-1:0] pc_exe; // pc for use by EXECUTE
output [1:0] alu_inputA_sel;
output [1:0] alu_inputB_sel;
output [1:0] alu_inputC_sel;
output [3:0] alu_fns_sel;
output [2:0] comparator_fns_sel;
output we_load; // write_en for regfile on Load
output we_store; // write_en for DMEM
output we_alu_branch; // write_en for regfile on ALU / Branch instr
output [2:0] regfile_input_sel; // selects input to regfile
output [1:0] dmem_input_sel; // selects input to DMEM
output delay_bit;
output update_carry; // tells EXECUTE to update carry bit in MSR
output branch_instr; // tells EXECUTE to use comparator for branching
 
`ifdef FSL_LINK
output fsl_get;
output fsl_control;
output fsl_blocking;
output fsl_cmd_vld;
output [2:0] fsl_number;
`endif
 
// Register All Outputs
reg [`D_WIDTH-1:0] immediate;
reg [`D_WIDTH-1:0] pc_exe; // Prog Cnter of instr being executed
reg [1:0] alu_inputA_sel;
reg [1:0] alu_inputB_sel;
reg [1:0] alu_inputC_sel;
reg [3:0] alu_fns_sel; // selects ALU function
reg [2:0] comparator_fns_sel;
reg we_load; // reg file write enable for load operations
reg we_store;
reg we_alu_branch; // reg file write enable for ALU or branch ops
reg [2:0] regfile_input_sel;
reg [1:0] dmem_input_sel;
reg [4:0] regA_addr; // 5-bit addresses into Reg File
reg [4:0] regB_addr;
reg [4:0] regD_addr;
reg update_carry; // update the Carry bit in the status reg for ADDs
reg delay_bit; // Use delay slot in Branches
reg branch_instr;
 
`ifdef FSL_LINK
reg fsl_get;
reg fsl_control;
reg fsl_blocking;
reg fsl_cmd_vld;
reg [2:0] fsl_number;
`endif
 
// Internal registers
reg [15:0] imm; // contains imm value from IMM instr
reg imm_valid; // indicates imm value is valid (aka previous instr was IMM)
 
always@(posedge clock)
begin
if (reset | (flush & !stall)) // FIX - ADDED the "!stall"
begin
if (reset)
pc_exe <= 0;
else
pc_exe <= pc_decode;
update_carry <= 0;
regA_addr <= 0;
regB_addr <= 0;
regD_addr <= 0;
immediate <= 0;
alu_inputA_sel <= 0;
alu_inputB_sel <= 0;
alu_inputC_sel <= 0;
delay_bit <= 0;
branch_instr <= 0;
// EXECUTE NoOp on Reset / Flush. NoOp is OR r0, r0, r0
alu_fns_sel <= `ALU_logic_or;
comparator_fns_sel <= 0;
we_load <= 0;
we_store <= 0;
we_alu_branch <= 0;
regfile_input_sel <= `RF_zero; // write zero to r0 on reset -- R0 always zero
dmem_input_sel <= 0;
imm <= 0;
imm_valid <= 0;
`ifdef FSL_LINK
fsl_control <= 0;
fsl_get <= 0;
fsl_blocking <= 0;
fsl_cmd_vld <= 0;
fsl_number <= 0;
`endif
end
else if (!stall)
begin
// defaults for most instructions
branch_instr <= 0;
pc_exe <= pc_decode;
// Delay bit is tricky as each type of branch has a different location
delay_bit <= `uncond_branch ? ((`opcode == `RETURN) ? 1 : `D_bit_uncond) : `cond_branch ? `D_bit_cond : 0;
we_load <= 0;
we_store <= 0;
update_carry <= 0;
regA_addr <= `regA_sel;
regB_addr <= `regB_sel;
regD_addr <= `regD_sel;
`ifdef DATAPATH_32
immediate <= imm_valid ? {imm, `imm_value} : {{16{instruction[15]}}, `imm_value}; // 32-bit datapath
`else // 16-bit datapath -- ignore Immediate instructions
immediate <= `imm_value;
`endif
we_alu_branch <= 1'b1; // most instrs write to reg file
regfile_input_sel <= `RF_alu_result;
alu_inputA_sel <= `aluA_ra;
alu_inputB_sel <= `IMM_bit ? `aluB_imm : `aluB_rb;
alu_inputC_sel <= `aluC_zero;
alu_fns_sel <= `ALU_add;
comparator_fns_sel <= 0; // Not using comparator
imm_valid <= 0;
`ifdef FSL_LINK
fsl_control <= 0;
fsl_get <= 0;
fsl_blocking <= 0;
fsl_cmd_vld <= 0;
fsl_number <= 0;
`endif
// BIG Case statement here
// see openfire_define.v for definitions
casez (`opcode)
`ADD:
begin
alu_inputC_sel <= `C_bit ? `aluC_carry : `aluC_zero;
update_carry <= ~`K_bit;
end
`SUBTRACT:
begin
update_carry <= ~`K_bit;
// Added reference to IMM_bit to the following if/else to make
// sure the RSUBI is not decoded as CMPU. Bug detected by
// scraven, patched by amarschn.
if (`U_bit & `CMP_bit & !`IMM_bit) // CMPU
begin
alu_fns_sel <= `ALU_compare_uns;
comparator_fns_sel <= `CMP_dual_inputs;
end
else if (`CMP_bit & !`IMM_bit) // CMP
alu_fns_sel <= `ALU_compare;
else
alu_fns_sel <= `ALU_add;
alu_inputA_sel <= `aluA_ra_bar;
alu_inputC_sel <= `C_bit ? `aluC_carry : `aluC_one;
end
`LOGIC_OR: alu_fns_sel <= `ALU_logic_or;
`LOGIC_AND: alu_fns_sel <= `ALU_logic_and;
`LOGIC_XOR: alu_fns_sel <= `ALU_logic_xor;
`LOGIC_ANDN:
begin
alu_fns_sel <= `ALU_logic_and;
alu_inputB_sel <= `IMM_bit ? `aluB_imm_bar : `aluB_rb_bar;
end
`LOGIC_BIT:
begin
alu_inputC_sel <= `aluC_carry;
update_carry <= 1;
casez (`imm_value)
16'b1: alu_fns_sel <= `ALU_shiftR_arth;
16'b100001: alu_fns_sel <= `ALU_shiftR_c;
16'b1000001: alu_fns_sel <= `ALU_shiftR_log;
16'b1100000: alu_fns_sel <= `ALU_sex8;
16'b1100001: alu_fns_sel <= `ALU_sex16;
endcase
end
`BRANCH_UNCON: // Handles BREAKs as well
begin
branch_instr <= 1;
alu_inputA_sel <= `A_bit ? `aluA_zero : `aluA_pc;
alu_inputB_sel <= `IMM_bit ? `aluB_imm : `aluB_rb;
comparator_fns_sel <= `CMP_one; // force a branch
regfile_input_sel <= `RF_pc;
//if (~`D_bit & `A_bit & `L_bit) // executing a BREAK, must update MSR
// NOT implemented yet
end
`BRANCH_CON:
begin
branch_instr <= 1;
alu_inputA_sel <= `aluA_pc;
comparator_fns_sel <= `branch_compare;
we_alu_branch <= 1'b0;
end
`IMMEDIATE:
begin
we_alu_branch <= 1'b0; // have EXE do nothing
imm_valid <= 1;
imm <= `imm_value;
end
`RETURN: // ignores MSR, exceptions, and interrupts
begin
branch_instr <= 1;
alu_inputB_sel <= `aluB_imm;
comparator_fns_sel <= `CMP_one; // force a branch
we_alu_branch <= 1'b0;
end
`LOAD:
begin
we_alu_branch <= 1'b0;
we_load <= 1'b1;
regfile_input_sel <= `word_size;
end
`STORE:
begin
we_alu_branch <= 1'b0;
we_store <= 1'b1;
dmem_input_sel <= `word_size;
end
`ifdef FSL_LINK
`FSL:
begin
fsl_control <= `FSL_control;
fsl_get <= ~`fsl_get_put;
fsl_blocking <= ~`FSL_nblock;
fsl_cmd_vld <= 1;
fsl_number <= `FSL_number;
we_alu_branch <= 0;
regfile_input_sel <= `RF_fsl;
end
`endif
`ifdef MUL
`MULTIPLY:
begin
alu_fns_sel <= `ALU_multiply;
`ifdef DATAPATH_32
// 32-bit mult takes several cycles -- do not write to Reg File until complete
we_alu_branch <= 1'b0;
`endif
end
`endif
// for simulation
default: $display("ERROR! Malformed OpCode! 0x%x", `opcode);
endcase
end
 
end // end of always@
endmodule

powered by: WebSVN 2.1.0

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