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 |