OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [trunk/] [fpga/] [mc-vl/] [src/] [cpu/] [cpu_bus.v] - Rev 308

Compare with Previous | Blame | View Log

//
// cpu_bus.v -- the ECO32 CPU bus interface
//
 
 
`timescale 1ns/10ps
`default_nettype none
 
 
module cpu_bus(clk, rst,
               bus_stb, bus_we, bus_addr,
               bus_din, bus_dout, bus_ack, bus_irq,
               cpu_stb, cpu_we, cpu_size, cpu_addr,
               cpu_din, cpu_dout, cpu_ack, cpu_irq);
    // bus interface
    input clk;
    input rst;
    output reg bus_stb;
    output reg bus_we;
    output reg [31:2] bus_addr;
    input [31:0] bus_din;
    output reg [31:0] bus_dout;
    input bus_ack;
    input [15:0] bus_irq;
    // CPU interface
    input cpu_stb;
    input cpu_we;
    input [1:0] cpu_size;
    input [31:0] cpu_addr;
    output reg [31:0] cpu_din;
    input [31:0] cpu_dout;
    output reg cpu_ack;
    output [15:0] cpu_irq;
 
  reg state;
  reg next_state;
  reg [31:0] wbuf;
  reg wbuf_we;
  reg [31:0] wbuf_in;
 
  // ctrl
  always @(posedge clk) begin
    if (rst) begin
      state <= 0;
    end else begin
      state <= next_state;
    end
  end
 
  // output
  always @(*) begin
    case (state)
      1'b0:
        if (~cpu_stb) begin
          // no bus activity from cpu
          bus_stb = 1'b0;
          bus_we = 1'bx;
          bus_addr[31:2] = 30'bx;
          bus_dout[31:0] = 32'bx;
          cpu_din[31:0] = 32'bx;
          cpu_ack = 1'b0;
          next_state = 1'b0;
          wbuf_we = 1'b0;
          wbuf_in[31:0] = 32'bx;
        end else begin
          // bus activated by cpu
          if (~cpu_we) begin
            // cpu read cycle
            if (~cpu_size[1]) begin
              if (~cpu_size[0]) begin
                // cpu read byte
                bus_stb = 1'b1;
                bus_we = 1'b0;
                bus_addr[31:2] = cpu_addr[31:2];
                bus_dout[31:0] = 32'bx;
                if (~cpu_addr[1]) begin
                  if (~cpu_addr[0]) begin
                    cpu_din[31:0] = { 24'h0, bus_din[31:24] };
                  end else begin
                    cpu_din[31:0] = { 24'h0, bus_din[23:16] };
                  end
                end else begin
                  if (~cpu_addr[0]) begin
                    cpu_din[31:0] = { 24'h0, bus_din[15: 8] };
                  end else begin
                    cpu_din[31:0] = { 24'h0, bus_din[ 7: 0] };
                  end
                end
                cpu_ack = bus_ack;
                next_state = 1'b0;
                wbuf_we = 1'b0;
                wbuf_in[31:0] = 32'bx;
              end else begin
                // cpu read halfword
                bus_stb = 1'b1;
                bus_we = 1'b0;
                bus_addr[31:2] = cpu_addr[31:2];
                bus_dout[31:0] = 32'bx;
                if (~cpu_addr[1]) begin
                  cpu_din[31:0] = { 16'h0, bus_din[31:16] };
                end else begin
                  cpu_din[31:0] = { 16'h0, bus_din[15: 0] };
                end
                cpu_ack = bus_ack;
                next_state = 1'b0;
                wbuf_we = 1'b0;
                wbuf_in[31:0] = 32'bx;
              end
            end else begin
              // cpu read word
              bus_stb = 1'b1;
              bus_we = 1'b0;
              bus_addr[31:2] = cpu_addr[31:2];
              bus_dout[31:0] = 32'bx;
              cpu_din[31:0] = bus_din[31:0];
              cpu_ack = bus_ack;
              next_state = 1'b0;
              wbuf_we = 1'b0;
              wbuf_in[31:0] = 32'bx;
            end
          end else begin
            // cpu write cycle
            if (~cpu_size[1]) begin
              if (~cpu_size[0]) begin
                // cpu write byte
                // part 1: read word into word buffer
                bus_stb = 1'b1;
                bus_we = 1'b0;
                bus_addr[31:2] = cpu_addr[31:2];
                bus_dout[31:0] = 32'bx;
                cpu_din[31:0] = 32'bx;
                cpu_ack = 1'b0;
                if (~bus_ack) begin
                  next_state = 1'b0;
                end else begin
                  next_state = 1'b1;
                end
                wbuf_we = 1'b1;
                if (~cpu_addr[1]) begin
                  if (~cpu_addr[0]) begin
                    wbuf_in[31:0] = { cpu_dout[7:0], bus_din[23:16],
                                      bus_din[15:8], bus_din[7:0] };
                  end else begin
                    wbuf_in[31:0] = { bus_din[31:24], cpu_dout[7:0],
                                      bus_din[15:8], bus_din[7:0] };
                  end
                end else begin
                  if (~cpu_addr[0]) begin
                    wbuf_in[31:0] = { bus_din[31:24], bus_din[23:16],
                                      cpu_dout[7:0], bus_din[7:0] };
                  end else begin
                    wbuf_in[31:0] = { bus_din[31:24], bus_din[23:16],
                                      bus_din[15:8], cpu_dout[7:0] };
                  end
                end
              end else begin
                // cpu write halfword
                // part 1: read word into word buffer
                bus_stb = 1'b1;
                bus_we = 1'b0;
                bus_addr[31:2] = cpu_addr[31:2];
                bus_dout[31:0] = 32'bx;
                cpu_din[31:0] = 32'bx;
                cpu_ack = 1'b0;
                if (~bus_ack) begin
                  next_state = 1'b0;
                end else begin
                  next_state = 1'b1;
                end
                wbuf_we = 1'b1;
                if (~cpu_addr[1]) begin
                  wbuf_in[31:0] = { cpu_dout[15:0], bus_din[15:0] };
                end else begin
                  wbuf_in[31:0] = { bus_din[31:16], cpu_dout[15:0] };
                end
              end
            end else begin
              // cpu write word
              bus_stb = 1'b1;
              bus_we = 1'b1;
              bus_addr[31:2] = cpu_addr[31:2];
              bus_dout[31:0] = cpu_dout[31:0];
              cpu_din[31:0] = 32'bx;
              cpu_ack = bus_ack;
              next_state = 1'b0;
              wbuf_we = 1'b0;
              wbuf_in[31:0] = 32'bx;
            end
          end
        end
      1'b1:
        begin
          // cpu write halfword or byte
          // part 2: write word from word buffer
          bus_stb = 1'b1;
          bus_we = 1'b1;
          bus_addr[31:2] = cpu_addr[31:2];
          bus_dout[31:0] = wbuf[31:0];
          cpu_din[31:0] = 32'bx;
          cpu_ack = bus_ack;
          if (~bus_ack) begin
            next_state = 1'b1;
          end else begin
            next_state = 1'b0;
          end
          wbuf_we = 1'b0;
          wbuf_in[31:0] = 32'bx;
        end
    endcase
  end
 
  // word buffer
  always @(posedge clk) begin
    if (wbuf_we) begin
      wbuf[31:0] <= wbuf_in[31:0];
    end
  end
 
  // interrupt requests
  assign cpu_irq[15:0] = bus_irq[15:0];
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.