/* 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 . */ 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