📄 nios_0.v
字号:
// The address of the register that should be written to is stored in the o_x
// pipeline registers (s4_reg_write_address_out)
assign current_reg_write_address_in = s4_reg_write_address_out;
// Byteenable defines which bytes should be stored to the memory when store instruction
// commits, depending on the type of the instruction. Byte is stored for ST8S, ST8D, and
// STS8S instruction, halfword for ST16S, ST16D, and STS16S instruction, and word for
// all other store instructions. Which byte (or halfword) is read is encoded in the
// instruction word for ST8S, ST16S, STS8S, and STS16S instruction, and in register A
// for ST8D and ST16D instruction.
assign d_byteenable =
//ST8S
(ir[15:7] == 9'b011101100) ? {(ir[6] & ir[5]), (ir[6] & ~ir[5]), (~ir[6] & ir[5]), (~ir[6] & ~ir[5])} :
//ST16S
(ir[15:7] == 9'b011101101) ? {ir[6], ir[6], ~ir[6], ~ir[6]} :
//STS8S
(ir[15:10] == 6'b011000) ? {(ir[1] & ir[0]), (ir[1] & ~ir[0]), (~ir[1] & ir[0]), (~ir[1] & ~ir[0])} :
//STS16S
(ir[15:10] == 6'b011001) ? {ir[1], ir[1], ~ir[1], ~ir[1]} :
//ST8D
(ir[15:5] == 11'b01111110000) ? {(RA[1] & RA[0]), (RA[1] & ~RA[0]), (~RA[1] & RA[0]), (~RA[1] & ~RA[0])} :
//ST16D
(ir[15:5] == 11'b01111110001) ? {RA[1], RA[1], ~RA[1], ~RA[1]} :
//any other instruction
4'b1111;
// Instructions STS8S, STS16S, ST8S, ST16S, ST8D, ST16D write the contents of the register %r0
// to memory, which is read as reg_b from the register file. Other instructions write reg_a.
assign d_writedata = (s4_decoded_instr[3:2] == 2'b11) ? s4_reg_b_data_out : s4_reg_a_data_out;
assign decoded_instr = s4_decoded_instr;
assign ir = s4_ir;
// force_read is equivalent to force_interrupt | force_trap_1 | force_trap_2
// Therefore, last stage of the pipeline will be flushed when overflow/underflow, or interrupt happens
// It will also be flushed on TRET instruction, since it doesn't have a delay slot
assign flush_o_x = force_read | s4_tret | pending_interrupt;
// Next is ctrl. flow instr. also for the TRET instruction
assign next_is_ctrl_flow_instr = s3_ctrl_flow_instr | next_is_tret;
// Refer to the instruction decoder for the explanation of the following set of signals
assign next_is_restore = s3_decoded_instr[10] & ~s3_decoded_instr[9];
assign next_is_save = ~s3_decoded_instr[10] & s3_decoded_instr[9];
assign next_is_trap = ~s3_decoded_instr[14] & ~s3_decoded_instr[13] & s3_decoded_instr[11];
assign next_is_tret = ~s3_decoded_instr[14] & ~s3_decoded_instr[13] & s3_decoded_instr[12] & ~s3_decoded_instr[11];
assign next_is_wrctl = (s3_decoded_instr[17:15] == 3'b101);
assign RA = s4_reg_a_data_out;
assign s4_trap = ~s4_decoded_instr[14] & ~s4_decoded_instr[13] & s4_decoded_instr[11];
assign s4_tret = ~s4_decoded_instr[14] & ~s4_decoded_instr[13] & s4_decoded_instr[12] & ~s4_decoded_instr[11];
prefetch_unit the_pipeline_stage_1 (
// inputs
.clk (clk),
.cpu_s_read_address (branch_logic_pc),
.cpu_wants_to_read (read_next),
.d_irqnumber (d_irqnumber),
.data_in_from_memory (i_readdata),
.data_is_valid_from_memory (i_datavalid),
.flush_fifo (flush_fifo),
.flush_pipeline (flush_pipeline),
.force_interrupt (force_interrupt),
.force_trap_1 (force_trap_1),
.force_trap_2 (force_trap_2),
.load_nops (load_nops),
.memory_requests_wait (i_wait),
.reset_n (reset_n),
// outputs
.data_out_to_cpu (i_from_fifo),
.flush_memory (i_flush),
.memory_address_to_read (i_address),
.prefetch_unit_has_valid_data (fifo_datavalid),
.read_memory (i_read)
);
defparam the_pipeline_stage_1.START_ADDRESS = START_ADDRESS;
defparam the_pipeline_stage_1.FIFO_SIZE = FIFO_SIZE;
pipeline_stage_2 the_pipeline_stage_2(
// inputs
.clk (clk),
.cpu_continue_running (cpu_continue_running),
.cwp (cwp),
.cwp_minus_1 (cwp_minus_1),
.d_irqnumber (d_irqnumber),
.fifo_datavalid (fifo_datavalid),
.flush_fifo (flush_fifo),
.flush_pipeline (flush_pipeline),
.force_read (force_read),
.i_from_fifo (i_from_fifo),
.load_nops (load_nops),
.read_next (read_next),
.reg_data_in (current_reg_data_in),
.reg_write_address_in (current_reg_write_address_in),
.reg_write_en (current_reg_write_en),
.reset_n (reset_n),
.s3_tret (next_is_tret),
// outputs
.ctrl_en (ctrl_en),
.ctrl_flow_instr (s2_ctrl_flow_instr),
.decoded_instr (s2_decoded_instr),
.ir (s2_ir),
.reg_a_address (s2_reg_a_address),
.reg_a_data_out (s2_reg_a_data_out),
.reg_b_address (s2_reg_b_address),
.reg_b_data_out (s2_reg_b_data_out),
.reg_write_address_out (s2_reg_write_address_out)
);
defparam the_pipeline_stage_2.LOG_REGISTER_FILE_SIZE = LOG_REGISTER_FILE_SIZE;
d_o_registers the_d_o_registers(
// inputs
.clk (clk),
.cpu_continue_running (cpu_continue_running),
.flush_pipeline (flush_pipeline),
.reset_n (reset_n),
.s2_ctrl_flow_instr (s2_ctrl_flow_instr),
.s2_decoded_instr (s2_decoded_instr),
.s2_ir (s2_ir),
.s2_reg_a_address (s2_reg_a_address),
.s2_reg_b_address (s2_reg_b_address),
.s2_reg_write_address_out (s2_reg_write_address_out),
// outputs
.s3_ctrl_flow_instr (s3_ctrl_flow_instr),
.s3_decoded_instr (s3_decoded_instr),
.s3_ir (s3_ir),
.s3_reg_a_address (s3_reg_a_address),
.s3_reg_b_address (s3_reg_b_address),
.s3_reg_write_address_out (s3_reg_write_address_out)
);
pipeline_stage_3 the_pipeline_stage_3(
// inputs
.clk (clk),
.cpu_continue_running (cpu_continue_running),
.ctrl_en (ctrl_en),
.ctrl_flow_instr (next_is_ctrl_flow_instr),
.d_readdata (d_readdata),
.decoded_instr (s3_decoded_instr),
.fifo_datavalid (fifo_datavalid),
.flush_fifo (flush_fifo),
.ir (s3_ir),
.keep_pc (keep_pc),
.reg_a_address (s3_reg_a_address),
.reg_a_data_out (s2_reg_a_data_out),
.reg_b_address (s3_reg_b_address),
.reg_b_data_out (s2_reg_b_data_out),
.reg_write_address (current_reg_write_address_in),
.reg_write_data (current_reg_data_in),
.reg_write_en (current_reg_write_en),
.reset_n (reset_n),
.s4_trap (s4_trap),
.tret (next_is_tret),
// outputs
.branch_logic_out (branch_logic_pc),
.ctrl_reg_address (s3_ctrl_reg_address),
.K (K),
.mux_a_data_out (s3_mux_a_data_out),
.mux_b_data_out (s3_mux_b_data_out),
.npc (s3_npc),
.pc (s3_pc),
.pc_plus_4 (s3_pc_plus_4),
.s3_reg_a_data_out (s3_reg_a_data_out),
.s3_reg_b_data_out (s3_reg_b_data_out)
);
defparam the_pipeline_stage_3.VECTOR_TABLE_ADDRESS = VECTOR_TABLE_ADDRESS;
defparam the_pipeline_stage_3.START_ADDRESS = START_ADDRESS;
o_x_registers the_o_x_registers(
// inputs
.clk (clk),
.cpu_continue_running (cpu_continue_running),
.cwp (cwp_for_check),
.flush_pipeline (flush_o_x),
.hi_limit (wvalid_for_check[9:5]),
.lo_limit (wvalid_for_check[4:0]),
.reset_n (reset_n),
.s3_ctrl_reg_address (s3_ctrl_reg_address),
.s3_decoded_instr (s3_decoded_instr),
.s3_ir (s3_ir),
.s3_mux_a_data_out (s3_mux_a_data_out),
.s3_mux_b_data_out (s3_mux_b_data_out),
.s3_npc (s3_npc),
.s3_pc (s3_pc),
.s3_pc_plus_4 (s3_pc_plus_4),
.s3_reg_a_data_out (s3_reg_a_data_out),
.s3_reg_b_data_out (s3_reg_b_data_out),
.s3_reg_write_address_out (s3_reg_write_address_out),
// outputs
.s4_ctrl_reg_address (s4_ctrl_reg_address),
.s4_cwp_is_hi_limit (cwp_is_hi_limit),
.s4_cwp_is_lo_limit (cwp_is_lo_limit),
.s4_decoded_instr (s4_decoded_instr),
.s4_ir (s4_ir),
.s4_ld (ld),
.s4_mux_a_data_out (s4_mux_a_data_out),
.s4_mux_b_data_out (s4_mux_b_data_out),
.s4_npc (s4_npc),
.s4_pc (s4_pc),
.s4_pc_plus_4 (s4_pc_plus_4),
.s4_pfx (pfx),
.s4_reg_a_data_out (s4_reg_a_data_out),
.s4_reg_b_data_out (s4_reg_b_data_out),
.s4_reg_write_address_out (s4_reg_write_address_out),
.s4_restore (restore),
.s4_save (save),
.s4_skp0 (skp0),
.s4_skp1 (skp1),
.s4_skprnz (skprnz),
.s4_skprz (skprz),
.s4_skps (skps),
.s4_st (st),
.s4_trap (trap),
.s4_tret (tret)
);
pipeline_stage_4 the_pipeline_stage_4(
// inputs
.clk (clk),
.cpu_continue_running (cpu_continue_running),
.ctrl_en (ctrl_en),
.ctrl_reg_address (s4_ctrl_reg_address),
.ctrl_reg_sync_address (s3_ctrl_reg_address),
.d_irqnumber (d_irqnumber),
.d_readdata (d_readdata),
.decoded_instr (s4_decoded_instr),
.decrement_cwp (decrement_cwp),
.disable_interrupts (disable_interrupts),
.force_interrupt (force_interrupt),
.in_to_ctrl_regs (s4_reg_a_data_out),
.increment_cwp (increment_cwp),
.interrupt (interrupt),
.ir (s4_ir),
.mux_a_data_out (s4_mux_a_data_out),
.mux_b_data_out (s4_mux_b_data_out),
.next_is_restore (next_is_restore),
.next_is_save (next_is_save),
.next_is_trap (next_is_trap),
.npc (s4_npc),
.pc (s4_pc),
.pc_plus_4 (s4_pc_plus_4),
.reset_n (reset_n),
.restore (restore),
.s4_trap (trap),
.s4_tret (tret),
.save (save),
.save_status (save_status),
.skip (skip),
// outputs
.cwp (cwp),
.cwp_for_check (cwp_for_check),
.cwp_minus_1 (cwp_minus_1),
.d_address (d_address),
.reg_data_in (current_reg_data_in),
.status_reg (status_reg),
.wvalid_for_check (wvalid_for_check)
);
defparam the_pipeline_stage_4.LOG_REGISTER_FILE_SIZE = LOG_REGISTER_FILE_SIZE;
endmodule
//datapath*******************************************************************
//***************************************************************************
// Stage 1 (Fetch) Modules
//***************************************************************************
//***************************************************************************
// prefetch_unit
//
// Module prefetch_unit implements the prefetch unit
//
module prefetch_unit (
// inputs
clk,
cpu_s_read_address,
cpu_wants_to_read,
d_irqnumber,
data_in_from_memory,
data_is_valid_from_memory,
flush_fifo,
flush_pipeline,
force_interrupt,
force_trap_1,
force_trap_2,
load_nops,
memory_requests_wait,
reset_n,
// outputs
data_out_to_cpu,
flush_memory,
memory_address_to_read,
prefetch_unit_has_valid_data,
read_memory
);
parameter START_ADDRESS = 32'b0;
parameter FIFO_SIZE = 2;
input clk;
input [31:0] cpu_s_read_address;
input cpu_wants_to_read;
input [5:0] d_irqnumber;
input [15:0] data_in_from_memory;
input data_is_valid_from_memory;
input flush_fifo;
input flush_pipeline;
input force_interrupt;
input force_trap_1;
input force_trap_2;
input load_nops;
input memory_requests_wait;
input reset_n;
output [15:0] data_out_to_cpu;
output flush_memory;
output [31:0] memory_address_to_read;
output prefetch_unit_has_valid_data;
output read_memory;
wire [15:0] data_from_fifo;
wire flush_memory;
wire [15:0] instruction;
wire is_empty;
wire is_almost_full;
wire is_full;
wire read_fifo;
wire write_fifo;
reg [31:0] prefetch_pc;
// Instruction to be forwarded to the decode stage is one of the TRAP instructions,
// NOP, or the actual instruction coming from memory
assign data_out_to_cpu = force_interrupt ? {10'b0111100100, d_irqnumber} : //TRAP d_irqnumber
force_trap_1 ? 16'b0111100100000001 : //TRAP 1
force_trap_2 ? 16'b0111100100000010 : //TRAP 2
(flush_pipeline | load_nops) ? 16'h3000 : //NOP
instruction;
// Flush any pending reads when the FIFO is flushed
assign flush_memory = flush_fifo | ~reset_n;
// If the FIFO buffer is empty, the instruction being fetched from the instruction memory
// is forwarded immediately to the decode stage. Otherwise, the instruction from FIFO is
// forwarded. The decode stage is referred to as the CPU
assign instruction = (is_empty) ? data_in_from_memory : data_from_fifo;
assign memory_address_to_read = prefetch_pc;
// Prefetch unit has valid data (instruction) ready if the FIFO buffer is not empty,
// or the memory has the data ready.
assign prefetch_unit_has_valid_data = ~is_empty | data_is_valid_from_memory;
// Memory reads shouldn't be issued when the FIFO is being flushed, because the t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -