ms_dma.v
5.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/************************************************************************\
* *
* Copyright (C) 1994, Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
\************************************************************************/
// $Id: ms_dma.v,v 1.1.1.1 2002/05/17 06:07:47 blythe Exp $
// cbus module for memspan dma requests, from jlsmith
// this module takes memspan rdram dma requests (c/z r/w)
// of up to 128 bytes (64 for writes) per request and acts
// as interface between io and memspan; the actual request
// line is wired directly (as are grant, start, done) and are
// not appearing here. this module includes tristate cbus i/f.
//
// a number of ports here are for diag use, as indicated; the
// widths and nature of these functions are still to be worked out.
//mod 11-15-94 read/write delay params updated (read_delay to be verified)
module ms_dma(clock, reset_l,
cbus_read_enable, cbus_write_enable, cbus_select, cbus_command,
read_grant, dma_read, dma_down, dma_address, dma_length, reg_read_data,
read_request, reg_write_data, reg_address, reg_write_enable,
cbus_data);
`include "ms.vh"
parameter READ_DELAY = 8'd2;
parameter WRITE_DELAY = -8'd2;
input clock; // system clock
input reset_l; // system reset_l
input cbus_read_enable; // enable cbus read mux
input cbus_write_enable; // enable cbus tristate drivers
input [CBUS_SELECT_SIZE-1:0] cbus_select; // cbus data select
input [CBUS_COMMAND_SIZE-1:0] cbus_command; // cbus data type
input read_grant; // read response granted
input dma_read; // DMA read/write select
input dma_down; // DMA up/down select
input [DRAM_ADDRESS_SIZE-1:0] dma_address; // DMA slave address
input [DMA_LENGTH_SIZE-1:0] dma_length; // DMA length in words
input [CBUS_DATA_SIZE-1:0] reg_read_data; // *diag* read data to cbus
output read_request; // dma read request cycle
output [CBUS_DATA_SIZE-1:0] reg_write_data; // *diag* register wrdata
output [DP_REG_ADDRESS_SIZE-1:0] reg_address;// *diag* reg r/w address
output reg_write_enable; // *diag* reg write enable
inout [CBUS_DATA_SIZE-1:0] cbus_data; // IO cbus
// input/output registers
reg read_request;
reg reg_write_enable;
reg [DP_REG_ADDRESS_SIZE-1:0] reg_address;
reg [CBUS_COMMAND_SIZE-1:0] cbus_command_reg;
reg [CBUS_DATA_SIZE-1:0] cbus_data_reg;
// cbus tristate drivers
cbus_driver cbus_driver_0(cbus_data_reg, cbus_write_enable, cbus_data);
assign reg_write_data = cbus_data_reg;
always @(posedge clock) begin : cbus_block
reg [CBUS_DATA_SIZE-1:0] cbus_data_out;
case (cbus_select)
CBUS_ADDRESS_SELECT : cbus_data_out = dma_address;
CBUS_LENGTH_SELECT : case ({dma_down, dma_read})
2'b00 : cbus_data_out = {DMA_BLOCK, DMA_MASKED, DMA_UP,
DMA_NSEQ, BUS_DEVICE_DP_SPAN, WRITE_DELAY, DMA_WRITE, dma_length};
2'b01 : cbus_data_out = {DMA_BLOCK, DMA_NON_MASKED, DMA_UP,
DMA_SEQ, BUS_DEVICE_DP_SPAN, READ_DELAY, DMA_READ, dma_length};
2'b10 : cbus_data_out = {DMA_BLOCK, DMA_MASKED, DMA_DOWN,
DMA_NSEQ, BUS_DEVICE_DP_SPAN, WRITE_DELAY, DMA_WRITE, dma_length};
2'b11 : cbus_data_out = {DMA_BLOCK, DMA_NON_MASKED, DMA_DOWN,
DMA_NSEQ, BUS_DEVICE_DP_SPAN, READ_DELAY, DMA_READ, dma_length};
endcase
CBUS_DATA_SELECT : cbus_data_out = reg_read_data;
default : cbus_data_out = 'bx;
endcase
cbus_command_reg <= cbus_command;
cbus_data_reg <= cbus_read_enable ? cbus_data : cbus_data_out;
end
always @(posedge clock or negedge reset_l) begin
if (!reset_l) begin
// resetable registers
read_request <= LOW;
reg_write_enable <= LOW;
reg_address <= 'bx;
end
else begin : main_block
reg next_read_request;
reg next_reg_write_enable;
reg [BUS_ID_SIZE-1:0] next_id;
reg next_select;
reg next_write_command;
reg next_read_command;
next_read_request = read_request;
next_reg_write_enable = LOW;
next_id = cbus_data_reg >> BUS_ID_OFFSET;
next_select = next_id == BUS_ID_SPAN;
next_write_command = cbus_command_reg == CBUS_WRITE_COMMAND;
next_read_command = cbus_command_reg == CBUS_READ_COMMAND;
if (next_select) begin
if (next_write_command) begin
next_reg_write_enable = HIGH;
reg_address <= cbus_data_reg >> 2;
end
else if (next_read_command) begin
next_read_request = HIGH;
reg_address <= cbus_data_reg >> 2;
end
end
if (read_request && read_grant) begin
next_read_request = LOW;
end
read_request <= next_read_request;
reg_write_enable <= next_reg_write_enable;
end
end
endmodule