SummerCart64/fw/rtl/memory/memory_dma.sv
Polprzewodnikowy ab9bd74e91 backup
2022-05-15 15:47:12 +02:00

168 lines
6.7 KiB
Systemverilog

interface dma_scb ();
logic start;
logic stop;
logic busy;
logic direction;
logic [26:0] starting_address;
logic [26:0] transfer_length;
modport controller (
output start,
output stop,
input busy,
output direction,
output starting_address,
output transfer_length
);
modport dma (
input start,
input stop,
output busy,
input direction,
input starting_address,
input transfer_length
);
endinterface
module memory_dma (
input clk,
input reset,
dma_scb.dma dma_scb,
fifo_bus.controller fifo_bus,
mem_bus.controller mem_bus
);
typedef enum bit [0:0] {
STATE_FETCH,
STATE_TRANSFER
} e_state;
// logic [31:0] remaining;
logic [26:0] end_address;
logic [15:0] data_buffer;
logic byte_counter;
e_state state;
logic rx_delay;
always_ff @(posedge clk) begin
fifo_bus.rx_read <= 1'b0;
fifo_bus.tx_write <= 1'b0;
rx_delay <= fifo_bus.rx_read;
if (rx_delay) begin
// if (dma.address[0] || (remaining == 32'd1)) begin
// dma.wdata <= {dma.rx_rdata, dma.rx_rdata};
// end else begin
mem_bus.wdata <= {mem_bus.wdata[7:0], fifo_bus.rx_rdata};
// end
end
if (reset) begin
dma_scb.busy <= 1'b0;
mem_bus.request <= 1'b0;
end else begin
if (!dma_scb.busy) begin
if (dma_scb.start) begin
dma_scb.busy <= 1'b1;
mem_bus.write <= dma_scb.direction;
mem_bus.address <= dma_scb.starting_address;
end_address <= dma_scb.starting_address + dma_scb.transfer_length;
// remaining <= dma.transfer_length;
byte_counter <= 1'd0;
state <= STATE_FETCH;
end
end else begin
if (dma_scb.stop) begin
dma_scb.busy <= 1'b0;
mem_bus.request <= 1'b0;
end else if (mem_bus.address != end_address/* remaining != 32'd0*/) begin
if (mem_bus.write) begin
case (state)
STATE_FETCH: begin
if (!fifo_bus.rx_empty && !(fifo_bus.rx_read && fifo_bus.rx_almost_empty)) begin
fifo_bus.rx_read <= 1'b1;
// if (dma.address[0]) begin
// dma.wmask <= 2'b01;
// state <= STATE_TRANSFER;
// end else if (dma.starting_address[0] remaining == 32'd1) begin
// dma.wmask <= 2'b10;
// state <= STATE_TRANSFER;
// end else begin
byte_counter <= byte_counter + 1'd1;
if (byte_counter) begin
mem_bus.wmask <= 2'b11;
state <= STATE_TRANSFER;
end
// end
end
end
STATE_TRANSFER: begin
if (!fifo_bus.rx_read) begin
mem_bus.request <= 1'b1;
end
if (mem_bus.ack) begin
mem_bus.request <= 1'b0;
// if (dma.wmask != 2'b11) begin
// dma.address <= dma.address + 1'd1;
// remaining <= remaining - 1'd1;
// end else begin
mem_bus.address <= mem_bus.address + 2'd2;
// remaining <= remaining - 2'd2;
// end
state <= STATE_FETCH;
end
end
endcase
end else begin
case (state)
STATE_FETCH: begin
mem_bus.request <= 1'b1;
if (mem_bus.ack) begin
mem_bus.request <= 1'b0;
data_buffer <= mem_bus.rdata;
state <= STATE_TRANSFER;
end
end
STATE_TRANSFER: begin
if (!fifo_bus.tx_full && !(fifo_bus.tx_write && fifo_bus.tx_almost_full)) begin
fifo_bus.tx_write <= 1'b1;
// if (dma.address[0]) begin
// dma.address <= dma.address + 1'd1;
// // remaining <= remaining - 1'd1;
// dma.dma_tx_wdata <= data_buffer[7:0];
// state <= STATE_FETCH;
// end else if (remaining == 32'd1) begin
// dma.address <= dma.address + 1'd1;
// // remaining <= remaining - 1'd1;
// dma.dma_tx_wdata <= data_buffer[15:8];
// state <= STATE_FETCH;
// end else begin
fifo_bus.tx_wdata <= byte_counter ? data_buffer[7:0] : data_buffer[15:8];
byte_counter <= byte_counter + 1'd1;
if (byte_counter) begin
mem_bus.address <= mem_bus.address + 2'd2;
// remaining <= remaining - 2'd2;
state <= STATE_FETCH;
end
// end
end
end
endcase
end
end else begin
dma_scb.busy <= 1'b0;
end
end
end
end
endmodule