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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [rtl/] [ModRMDecode.sv] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see .
17
 
18
module ModRMDecode(input logic clk,
19
                   input logic reset,
20
                   // Control.
21
                   input logic start,
22
                   output logic busy,
23
                   output logic complete,
24
                   input logic clear,
25
                   // Results
26
                   output logic [15:0] effective_address,
27
                   output logic [2:0] regnum,
28
                   output logic rm_is_reg,
29
                   output logic [2:0] rm_regnum,
30
                   output logic bp_as_base,
31
                   // Registers.
32
                   output logic [2:0] reg_sel[2],
33
                   input logic [15:0] regs[2],
34
                   // Fifo Read Port.
35
                   output logic fifo_rd_en,
36
                   input logic [7:0] fifo_rd_data,
37
                   input logic fifo_empty,
38
                   // Immediates
39
                   output logic immed_start,
40
                   input logic immed_complete,
41
                   output logic immed_is_8bit,
42
                   input logic [15:0] immediate);
43
 
44
reg [7:0] _modrm;
45
reg _modrm_byte_read;
46
reg _started;
47
reg _registers_fetched;
48
reg [15:0] _cached_effective_address;
49
reg [15:0] _effective_address;
50
wire _has_address = _mod != 2'b11;
51
wire _fifo_valid = start & ~_modrm_byte_read & ~fifo_empty;
52
wire [1:0] _mod = _fifo_valid ? fifo_rd_data[7:6] : _modrm[7:6];
53
wire [2:0] _reg = _fifo_valid ? fifo_rd_data[5:3] : _modrm[5:3];
54
wire [2:0] _rm  = _fifo_valid ? fifo_rd_data[2:0] : _modrm[2:0];
55
wire _has_immediate = (_rm == 3'b110 && _mod == 2'b00) || ^_mod;
56
 
57
assign busy = (start | _started) & ~complete;
58
assign complete = reset ? 1'b0 :
59
    (_modrm_byte_read || _fifo_valid) &&
60
    (!_has_address || _registers_fetched) &&
61
    (!_has_immediate || immed_complete);
62
assign immed_start = _has_immediate && _modrm_byte_read;
63
assign immed_is_8bit = _mod == 2'b01;
64
assign effective_address = complete ? _effective_address : _cached_effective_address;
65
 
66
always_comb begin
67
    case (_mod)
68
    2'b00: bp_as_base = (_rm == 3'b010 || _rm == 3'b011);
69
    2'b01: bp_as_base = (_rm == 3'b010 || _rm == 3'b011 || _rm == 3'b110);
70
    2'b10: bp_as_base = (_rm == 3'b010 || _rm == 3'b011 || _rm == 3'b110);
71
    default: bp_as_base = 1'b0;
72
    endcase
73
end
74
 
75
always_ff @(posedge clk or posedge reset) begin
76
    if (reset)
77
        _started <= 1'b0;
78
    else if (complete)
79
        _started <= 1'b0;
80
    else if (start)
81
        _started <= 1'b1;
82
end
83
 
84
always_ff @(posedge clk or posedge reset)
85
    if (reset)
86
        _registers_fetched <= 1'b0;
87
    else if (complete)
88
        _registers_fetched <= 1'b0;
89
    else if (~fifo_empty & start & ~_modrm_byte_read)
90
        _registers_fetched <= 1'b1;
91
 
92
always_comb begin
93
    case (_rm)
94
    3'b000, 3'b001, 3'b111: reg_sel[0] = BX;
95
    3'b010, 3'b011, 3'b110: reg_sel[0] = BP;
96
    3'b100: reg_sel[0] = SI;
97
    3'b101: reg_sel[0] = DI;
98
    endcase
99
 
100
    case (_rm)
101
    3'b000, 3'b010: reg_sel[1] = SI;
102
    3'b001, 3'b011: reg_sel[1] = DI;
103
    default: reg_sel[1] = 0;
104
    endcase
105
end
106
 
107
always_comb begin
108
    regnum = _reg;
109
    rm_regnum = _rm;
110
    rm_is_reg = 1'b0;
111
    _effective_address = 16'b0;
112
 
113
    case (_mod)
114
    2'b00: begin
115
        case (_rm)
116
        3'b000, 3'b001, 3'b010, 3'b011: _effective_address = regs[0] + regs[1];
117
        3'b100, 3'b101, 3'b111: _effective_address = regs[0];
118
        3'b110: _effective_address = immediate;
119
        endcase
120
    end
121
    2'b01, 2'b10: begin
122
        case (_rm)
123
        3'b000, 3'b001, 3'b010, 3'b011: _effective_address = regs[0] + regs[1] + immediate;
124
        3'b100, 3'b101, 3'b110, 3'b111: _effective_address = regs[0] + immediate;
125
        endcase
126
    end
127
    2'b11: begin
128
        rm_regnum = _rm;
129
        rm_is_reg = 1'b1;
130
    end
131
    endcase
132
end
133
 
134
always_ff @(posedge clk)
135
    if (complete)
136
        _cached_effective_address <= _effective_address;
137
 
138
always_ff @(posedge clk or posedge reset)
139
    if (reset)
140
        _modrm_byte_read <= 1'b0;
141
    else if (complete)
142
        _modrm_byte_read <= 1'b0;
143
    else if (fifo_rd_en)
144
        _modrm_byte_read <= 1;
145
 
146
assign fifo_rd_en = ~fifo_empty & start & ~_modrm_byte_read;
147
 
148
always_ff @(posedge clk or posedge reset)
149
    if (reset)
150
        _modrm <= 8'b0;
151
    else if (clear)
152
        _modrm <= 8'b0;
153
    else if (~fifo_empty & start & ~_modrm_byte_read)
154
        _modrm <= fifo_rd_data;
155
 
156
endmodule

powered by: WebSVN 2.1.0

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