/***************************************************************************** NIOS Custom Instruction Wrapper =============================== Simon Moore, Feb 2010 This package provides an wrapper for a two-operand NIOS custom instruction with one (optional) result. client.request.get() - provides the two operands client.response.put() - returns the result as a Maybe type (tagged Invalid if no data to be returned) *****************************************************************************/ package CustomInstructionNIOS; import FIFO::*; import GetPut::*; import ClientServer::*; import SpecialFIFOs::*; typedef Int#(32) NIOSwordT; typedef struct { NIOSwordT opA; NIOSwordT opB; } NIOS_Two_OperandsT deriving (Bits,Eq); (* always_ready, always_enabled *) interface NIOS_Two_Operand_Physical_Ifc; method Action instruction_slave(Bool start, Bool clk_en, NIOSwordT dataa, NIOSwordT datab); method Bool instruction_slave_done; // done flag method NIOSwordT instruction_slave_result; // result output endinterface interface NIOS_Two_Operand_Physical_Embedded_Ifc; interface NIOS_Two_Operand_Physical_Ifc nios_custom; endinterface interface NIOS_Two_Operand_Instruction_Ifc; interface NIOS_Two_Operand_Physical_Ifc nios_custom; interface Client#(NIOS_Two_OperandsT, Maybe#(NIOSwordT)) client; endinterface module mkNIOS_Two_Operand_Custom_Instruction(NIOS_Two_Operand_Instruction_Ifc); Wire#(NIOS_Two_OperandsT) ops_bw <- mkBypassWire; Wire#(Bool) start_trigger <- mkBypassWire; Wire#(Bool) pipeline_enable <- mkBypassWire; PulseWire start_handled <- mkPulseWire; Reg#(Bool) start_saved <- mkReg(False); FIFO#(Maybe#(NIOSwordT)) result_fifo <- mkLFIFO; Wire#(NIOSwordT) result_dw <- mkDWire(0); PulseWire done_pw <- mkPulseWire; // save the start signal in case the abstract "request" interface // isn't read to "get" rule save_start_signals; if(start_trigger && !start_handled) start_saved <= True; if(start_handled) start_saved <= False; endrule // send the result to the NIOS if the custom instruction hasn't // been stalled by the NIOS pipeline rule deq_result (pipeline_enable); result_dw <= fromMaybe(0,result_fifo.first); done_pw.send(); result_fifo.deq; endrule // wire up the physical interface interface NIOS_Two_Operand_Physical_Ifc nios_custom; method Action instruction_slave(start, clk_en, dataa, datab); ops_bw <= NIOS_Two_OperandsT{opA: dataa, opB: datab}; start_trigger <= start; pipeline_enable <= clk_en; endmethod method Bool instruction_slave_done; return done_pw; endmethod method NIOSwordT instruction_slave_result; return result_dw; endmethod endinterface // provide the abstract interface interface Client client; interface Get request; method ActionValue#(NIOS_Two_OperandsT) get if (start_trigger || start_saved); start_handled.send(); return ops_bw; endmethod endinterface method response = toPut(result_fifo); endinterface endmodule /***************************************************************************** NIOS Custom Instruction with all Operands (i.e. supports internal memory) *****************************************************************************/ typedef UInt#(5) Custom_RegT; typedef struct { NIOSwordT opA; NIOSwordT opB; Bool readOpA; // True=use opA, False=use internal register Bool readOpB; Bool result2nios; Custom_RegT rA; Custom_RegT rB; Custom_RegT rC; } NIOS_All_OperandsT deriving (Bits,Eq); (* always_ready, always_enabled *) interface NIOS_All_Operands_Physical_Ifc; method Action instruction_slave(Bool start, Bool clk_en, NIOSwordT dataa, NIOSwordT datab, Bool readra, Bool readrb, Bool writerc, Custom_RegT a, Custom_RegT b, Custom_RegT c); method Bool instruction_slave_done; // done flag method NIOSwordT instruction_slave_result; // result output endinterface interface NIOS_All_Operands_Physical_Embedded_Ifc; interface NIOS_All_Operands_Physical_Ifc nios_custom; endinterface interface NIOS_All_Operands_Instruction_Ifc; interface NIOS_All_Operands_Physical_Ifc nios_custom; interface Client#(NIOS_All_OperandsT, Maybe#(NIOSwordT)) client; endinterface module mkNIOS_All_Operands_Custom_Instruction(NIOS_All_Operands_Instruction_Ifc); Wire#(NIOS_All_OperandsT) ops_bw <- mkBypassWire; Wire#(Bool) start_trigger <- mkBypassWire; Wire#(Bool) pipeline_enable <- mkBypassWire; PulseWire start_handled <- mkPulseWire; Reg#(Bool) start_saved <- mkReg(False); FIFO#(Maybe#(NIOSwordT)) result_fifo <- mkLFIFO; Wire#(NIOSwordT) result_dw <- mkDWire(0); PulseWire done_pw <- mkPulseWire; // save the start signal in case the abstract "request" interface // isn't read to "get" rule save_start_signals; if(start_trigger && !start_handled) start_saved <= True; if(start_handled) start_saved <= False; endrule // send the result to the NIOS if the custom instruction hasn't // been stalled by the NIOS pipeline rule deq_result (pipeline_enable); result_dw <= fromMaybe(0,result_fifo.first); done_pw.send(); result_fifo.deq; endrule // wire up the physical interface interface NIOS_All_Operands_Physical_Ifc nios_custom; method Action instruction_slave(start, clk_en, dataa, datab, readra, readrb, writerc, a, b, c); ops_bw <= NIOS_All_OperandsT{opA: dataa, opB: datab, readOpA: readra, readOpB: readrb, result2nios: writerc, rA: a, rB: b, rC: c}; start_trigger <= start; pipeline_enable <= clk_en; endmethod method Bool instruction_slave_done; return done_pw; endmethod method NIOSwordT instruction_slave_result; return result_dw; endmethod endinterface // provide the abstract interface interface Client client; interface Get request; method ActionValue#(NIOS_All_OperandsT) get if (start_trigger || start_saved); start_handled.send(); return ops_bw; endmethod endinterface method response = toPut(result_fifo); endinterface endmodule endpackage: CustomInstructionNIOS