URL
https://opencores.org/ocsvn/s80186/s80186/trunk
Subversion Repositories s80186
[/] [s80186/] [trunk/] [rtl/] [microcode/] [Microcode.sv.templ] - Rev 2
Compare with Previous | Blame | View Log
// Copyright Jamie Iles, 2017//// This file is part of s80x86.//// s80x86 is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// s80x86 is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with s80x86. If not, see <http://www.gnu.org/licenses/>.// vi: ft=systemverilog`ifndef MICROCODE_ROM_PATH`define MICROCODE_ROM_PATH "."`endifmodule Microcode(input logic clk,input logic reset,input logic nmi_pulse,input logic intr,output logic inta,output logic irq_to_mdr,output logic start_interrupt,output logic do_escape_fault,input logic stall,input logic divide_error,input logic rm_is_reg,input logic [2:0] modrm_reg,input logic int_enabled,input logic zf,input logic tf,output logic [15:0] microcode_immediate,output logic [8:0] update_flags,output logic use_microcode_immediate,output logic segment_override,output logic [7:0] opcode,input logic jump_taken,input logic rb_zero,output logic lock,output logic multibit_shift,output logic is_hlt,output logic next_microinstruction,// Microinstruction fields.<%#exported_fields%>output logic <%type%><%name%>,<%/exported_fields%>output logic width,output logic reg_wr_en,// Fifo Read Port.output logic fifo_rd_en,input logic [7:0] fifo_rd_data,input logic fifo_empty,input logic fifo_resetting,output logic loop_next,input logic loop_done,// Debugoutput logic debug_stopped,input logic debug_seize,input logic [7:0] debug_addr,input logic debug_run);localparam num_instructions = <%num_instructions%>;localparam addr_bits = <%addr_bits%>;localparam reset_address = <%addr_bits%>'h129;localparam nmi_address = <%addr_bits%>'h12a;localparam irq_address = <%addr_bits%>'h12b;localparam single_step_address = <%addr_bits%>'h12c;localparam divide_error_address = <%addr_bits%>'h101;localparam next_instruction_address = <%addr_bits%>'h100;localparam debug_wait_address = <%addr_bits%>'h102;localparam do_int_address = <%addr_bits%>'h12d;typedef struct packed {<%#fields%>logic <%type%><%name%>;<%/fields%>} microcode_instruction;microcode_instruction mem[num_instructions] /* synthesis ram_init_file = "microcode.mif" */;microcode_instruction current;reg [addr_bits-1:0] addr;wire [addr_bits-1:0] next_addr;assign segment_override = current.prefix_type == PrefixType_SEGMENT_OVERRIDE;assign use_microcode_immediate = |current.immediate;always_comb begincase (current.immediate)<%#immediates%><%idx%>: microcode_immediate = 16'h<%val%>;<%/immediates%>default: microcode_immediate = 16'h0;endcaseendalways_comb begincase (current.update_flags)<%#flags%><%idx%>: update_flags = 9'h<%val%>;<%/flags%>default: update_flags = 9'h0;endcaseend<%#exported_fields%>assign <%name%> = current.<%name%>;<%/exported_fields%>assign fifo_rd_en = !stall && next_addr == {{addr_bits-8{1'b0}}, fifo_rd_data};reg [1:0] rep_prefix_type;wire has_rep_prefix = (rep_prefix_type == PrefixType_REPE ||rep_prefix_type == PrefixType_REPNE);reg rep_complete;assign debug_stopped = addr == debug_wait_address;assign multibit_shift = opcode == 8'hd2 ||opcode == 8'hd3 ||opcode == 8'hc0 ||opcode == 8'hc1;assign do_escape_fault = opcode[7:3] == 5'b11011 && next_addr == do_int_address;reg nmi_pending;reg ext_int_inhibit;wire take_nmi = (nmi_pending | nmi_pulse) & !ext_int_inhibit;wire take_irq = intr & int_enabled & !ext_int_inhibit;wire do_single_step = current.next_instruction & !ext_int_inhibit &(trap_flag_set | (start_instruction & tf)) ¤t.next != debug_wait_address;assign start_interrupt = next_addr == nmi_address ||next_addr == irq_address;assign irq_to_mdr = next_addr == irq_address;reg trap_flag_set;assign is_hlt = opcode == 8'hf4;reg seized;wire seizing = debug_seize & ~seized;reg start_instruction;assign loop_next = !stall && current.jump_type == JumpType_LOOP_DONE;assign reg_wr_en = current.rd_sel_source != RDSelSource_NONE & ~segment_wr_en;assign next_microinstruction = addr != next_addr;always_comb begincase (current.width)WidthType_W8: width = 1'b1;WidthType_W16: width = 1'b0;WidthType_WAUTO: width = ~opcode[0];default: width = 1'b0;endcaseendalways_ff @(posedge clk)inta <= next_addr == irq_address && addr != irq_address;always_ff @(posedge clk or posedge reset)if (reset)start_instruction <= 1'b0;elsestart_instruction <= fifo_rd_en;always_ff @(posedge clk or posedge reset)if (reset)trap_flag_set <= 1'b0;else if (next_addr == single_step_address)trap_flag_set <= 1'b0;else if (start_instruction)trap_flag_set <= tf;always_ff @(posedge clk or posedge reset)if (reset)ext_int_inhibit <= 1'b0;else if (current.ext_int_inhibit && current.next != debug_wait_address)ext_int_inhibit <= 1'b1;else if (fifo_rd_en && !stall)ext_int_inhibit <= 1'b0;`ifdef verilatorinitial $readmemb({{`MICROCODE_ROM_PATH, "/microcode.bin"}}, mem);`endifalways_comb begincase (rep_prefix_type)PrefixType_REPE: rep_complete = ~zf;PrefixType_REPNE: rep_complete = zf;default: rep_complete = 1'b0;endcaseendalways_ff @(posedge clk or posedge reset)if (reset)nmi_pending <= 1'b0;else if (next_addr == nmi_address)nmi_pending <= 1'b0;else if (nmi_pulse)nmi_pending <= 1'b1;always_ff @(posedge clk or posedge reset)if (reset)opcode <= 8'b0;else if (fifo_rd_en)opcode <= fifo_rd_data;always_ff @(posedge clk or posedge reset)if (reset)rep_prefix_type <= 2'b0;else if (next_instruction)rep_prefix_type <= 2'b0;else if (current.prefix_type == PrefixType_REPNE ||current.prefix_type == PrefixType_REPE)rep_prefix_type <= current.prefix_type;always_ff @(posedge clk or posedge reset)if (reset)seized <= 1'b0;else if (debug_stopped)seized <= 1'b1;else if (!debug_seize)seized <= 1'b0;always_comb beginif (reset)next_addr = reset_address;else if (stall)next_addr = addr;else if (debug_stopped && debug_run)next_addr = {{addr_bits - 9{1'b0}}, 1'b1, debug_addr};else if (current.ext_int_yield && seizing)next_addr = debug_wait_address;else if (current.ext_int_yield && take_nmi)next_addr = nmi_address;else if (current.ext_int_yield && take_irq)next_addr = irq_address;else if (current.jump_type == JumpType_JUMP_TAKEN)next_addr = jump_taken ? current.next : addr + 1'b1;else if (current.jump_type == JumpType_ZERO)next_addr = zf ? current.next : addr + 1'b1;else if (current.jump_type == JumpType_HAS_NO_REP_PREFIX)next_addr = ~has_rep_prefix ? current.next : addr + 1'b1;else if (current.jump_type == JumpType_REP_NOT_COMPLETE)next_addr = !rep_complete ? current.next : addr + 1'b1;else if (current.jump_type == JumpType_DISPATCH_REG)next_addr = current.next + {{addr_bits-3{1'b0}}, modrm_reg};else if (current.jump_type == JumpType_RM_REG_MEM)next_addr = current.next + {{addr_bits-1{1'b0}}, ~rm_is_reg};else if (current.jump_type == JumpType_OPCODE)next_addr = !fifo_empty ? {{addr_bits-8{1'b0}}, fifo_rd_data} : addr;else if (current.jump_type == JumpType_RB_ZERO)next_addr = rb_zero ? current.next : addr + 1'b1;else if (current.jump_type == JumpType_LOOP_DONE)next_addr = loop_done ? current.next : addr + 1'b1;else if (divide_error)next_addr = divide_error_address;else if (current.next_instruction && take_nmi)next_addr = nmi_address;else if (current.next_instruction && take_irq)next_addr = irq_address;else if (current.next_instruction && do_single_step)next_addr = single_step_address;else if (current.next_instruction && debug_seize)next_addr = debug_wait_address;else if (current.next_instruction)next_addr = !fifo_empty && !fifo_resetting ?{{addr_bits-8{1'b0}}, fifo_rd_data} : next_instruction_address;elsenext_addr = current.next;endalways @(posedge clk)addr <= next_addr;always @(posedge clk)current <= mem[next_addr];always_ff @(posedge clk or posedge reset)if (reset)lock <= 1'b0;else if (!stall && current.next_instruction)lock <= 1'b0;else if (opcode == 8'hf0)lock <= 1'b1;`ifdef verilatorexport "DPI-C" function get_microcode_address;function [addr_bits-1:0] get_microcode_address;get_microcode_address = addr;endfunctionexport "DPI-C" function get_ext_int_yield;function logic get_ext_int_yield;get_ext_int_yield = current.ext_int_yield;endfunctionint microcode_coverage[num_instructions];always_ff @(posedge clk)microcode_coverage[addr] <= microcode_coverage[addr] + 1;export "DPI-C" function get_microcode_num_instructions;function int get_microcode_num_instructions;get_microcode_num_instructions = num_instructions;endfunctionexport "DPI-C" function get_microcode_coverage_bin;function int get_microcode_coverage_bin;input int bin;get_microcode_coverage_bin = microcode_coverage[bin];endfunction`endifendmodule
