/* Wishbone_driver.v - Implements a classic wishbone master This file is part of the 9086 project. Copyright (c) 2024 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_IO_driver ( input wire clock, input wire reset_n, input wire [2:0] address, input wire [15:0] data_bus_in, output reg [15:0] data_bus_out, input read_n, input write_n, input chip_select_n, input wire wb_ctrl_ack, output wire [29:0] wb_ctrl_adr, output wire [1:0] wb_ctrl_bte, output wire [2:0] wb_ctrl_cti, output wire wb_ctrl_cyc, input wire [31:0] wb_ctrl_dat_r, output wire [31:0] wb_ctrl_dat_w, input wire wb_ctrl_err, output wire [3:0] wb_ctrl_sel, output wire wb_ctrl_stb, output wire wb_ctrl_we ); reg [13:0]WISHBONE_ADDR=14'd0; reg WISHBONE_ACTIVE_CYCLE=1'b0; wire WISHBONE_ERROR_IN; 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 [31:0]WISHBONE_DATA_WRITE; assign WISHBONE_ACK_IN=wb_ctrl_ack; assign wb_ctrl_adr={16'd0,WISHBONE_ADDR}; assign WISHBONE_ERROR_IN=wb_ctrl_err; assign wb_ctrl_sel=WISHBONE_SELECT; assign wb_ctrl_stb=WISHBONE_VALID_TRANSFER; assign wb_ctrl_cyc=WISHBONE_ACTIVE_CYCLE; assign wb_ctrl_we=WISHBONE_WRITE; assign wb_ctrl_bte=2'b00; // Burst Type Extension 00:Linear burst assign wb_ctrl_cti=3'b000; // Cycle Type Idenfier 000:Classic cycle assign WISHBONE_DATA_WRITE=wb_ctrl_dat_r; assign wb_ctrl_dat_w=WISHBONE_DATA_READ; reg [31:0]WISHBONE_READ_BUFFER; reg [1:0]just_transacted; reg [1:0]WISHBONE_STATUS; wire CYCLE_END=(WISHBONE_ACK_IN==1'b1);//||WISHBONE_ERROR_IN==1'b1); always @( posedge clock )begin if(reset_n==0)begin just_transacted<=2'b0; end if(just_transacted==2'd1&&CYCLE_END==1'b1)begin WISHBONE_READ_BUFFER<=WISHBONE_DATA_WRITE; end if(chip_select_n==0 && write_n==0 )begin case (address) 3'h0: WISHBONE_DATA_READ[15:0] <=data_bus_in; 3'h1: WISHBONE_DATA_READ[31:16]<=data_bus_in; 3'h2: WISHBONE_ADDR[13:0]<=data_bus_in[13:0]; 3'h3: begin end default: begin end endcase case (address) 3'h3: begin WISHBONE_ACTIVE_CYCLE<=1; WISHBONE_VALID_TRANSFER<=1; WISHBONE_SELECT<=4'hF; end default: begin end endcase if(address==3'h3)begin WISHBONE_WRITE<=1'b1;//data_bus_in[0:0]; if(data_bus_in[0:0]==1'b1)begin //write req just_transacted<=2'd2; end else begin just_transacted<=2'd1; end end end else if(just_transacted!=2'd0&&CYCLE_END==1'b1)begin // In the unlikely scenario that the CPU wants to write without having checked for the previous write WISHBONE_STATUS[0:0]<=WISHBONE_ACK_IN; WISHBONE_STATUS[1:1]<=WISHBONE_ERROR_IN; WISHBONE_ACTIVE_CYCLE<=0; WISHBONE_VALID_TRANSFER<=0; just_transacted<=2'b0; end if ( chip_select_n==0 && read_n==0 )begin case (address) /* verilator lint_off BLKSEQ */ /* Makes icarus verilog work as expected, not too sure if it helps real hardware yet*/ 3'h0: data_bus_out = WISHBONE_READ_BUFFER[15:0]; 3'h1: data_bus_out = WISHBONE_READ_BUFFER[31:16]; 3'h2: data_bus_out = {13'd0,WISHBONE_STATUS,just_transacted==2'd0||CYCLE_END==1'b1}; //1:NOT BUSY 0:BUSY default: data_bus_out = 16'h0; /* verilator lint_on BLKSEQ */ endcase end end endmodule