9086/system/peripherals/Wishbone_memory_driver.v

150 lines
3.5 KiB
Verilog

/* Wishbone_driver.v - Implements a classic wishbone master that maps directly in memory space
This file is part of the 9086 project.
Copyright (c) 2023 Efthymios Kritikos
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
module Wishbone_memory_driver (
input wire clock,
input wire reset_n,
input wire [19:0] address,
input wire [15:0] data_bus_in,
output reg [15:0] data_bus_out,
output reg wait_state,
input read_n,
input write_n,
input chip_select_n,
input wire wb_mem_ack,
output wire [24:0] wb_mem_adr,
output wire wb_mem_cyc,
/* verilator lint_off UNUSEDSIGNAL */
// I don't yet use the upper word
input wire [31:0] wb_mem_data_r,
/* verilator lint_on UNUSEDSIGNAL */
output wire [31:0] wb_mem_data_w,
input wire wb_mem_err,
output wire [3:0] wb_mem_sel,
output wire wb_mem_stb,
output wire wb_mem_we
);
reg WISHBONE_ACTIVE_CYCLE=1'b0;
/* verilator lint_off UNUSEDSIGNAL */
wire WISHBONE_ERROR_IN;
/* verilator lint_on UNUSEDSIGNAL */
reg [3:0]WISHBONE_SELECT=4'd0;
reg WISHBONE_VALID_TRANSFER=1'b0;
reg WISHBONE_WRITE=1'b1;
wire WISHBONE_ACK_IN;
reg [31:0]WISHBONE_DATA_READ=32'd0;
wire [15:0]WISHBONE_DATA_WRITE;
assign WISHBONE_ACK_IN=wb_mem_ack;
assign wb_mem_adr={5'd0,address};
assign WISHBONE_ERROR_IN=wb_mem_err;
assign wb_mem_sel=WISHBONE_SELECT;
assign wb_mem_stb=WISHBONE_VALID_TRANSFER;
assign wb_mem_cyc=WISHBONE_ACTIVE_CYCLE;
assign wb_mem_we=WISHBONE_WRITE;
assign WISHBONE_DATA_WRITE=wb_mem_data_r[15:0];
assign wb_mem_data_w=WISHBONE_DATA_READ;
wire CYCLE_END=(WISHBONE_ACK_IN==1'b1);//||WISHBONE_ERROR_IN==1'b1);
reg [3:0] state;
always @(*) begin
wait_state=0;
if(reset_n==1) begin
case(state)
4'd0:begin
if( chip_select_n && ((!read_n)||(!write_n)) )begin
wait_state=1;
end else begin
wait_state=0;
end
end
4'd1:begin
wait_state=1;
end
4'd2:begin
wait_state=1;
end
4'd3:begin
wait_state=1;
end
4'd4:begin
wait_state=0;
end
default:begin
end
endcase
end else begin
wait_state=0;
end
end
always @(posedge clock)begin
if(reset_n==0)
state<=0;
else begin
case(state)
4'd0:begin
if( chip_select_n && ((!read_n)||(!write_n)) )begin
state<=4'd1;
end
end
4'd1:begin
WISHBONE_ACTIVE_CYCLE<=1;
WISHBONE_VALID_TRANSFER<=1;
WISHBONE_SELECT<=4'hF;
WISHBONE_WRITE<=read_n;
if(read_n)begin
state<=4'd2;
WISHBONE_DATA_READ<={16'h0,data_bus_in};
end else
state<=4'd3;
end
4'd2:begin
if(CYCLE_END==1'b1)begin
state<=4'd4;
WISHBONE_ACTIVE_CYCLE<=0;
WISHBONE_VALID_TRANSFER<=0;
end
end
4'd3:begin
if(CYCLE_END==1'b1)begin
data_bus_out<=WISHBONE_DATA_WRITE[15:0];
state<=4'd4;
WISHBONE_ACTIVE_CYCLE<=0;
WISHBONE_VALID_TRANSFER<=0;
end
end
4'd4:begin
if(read_n&&write_n)
state<=4'd0;
end
default:begin
state<=4'd0;
end
endcase
end
end
endmodule