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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [fpga/] [spi/] [SPIMaster.sv] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamieiles
// Copyright Jamie Iles, 2017
2
//
3
// This file is part of s80x86.
4
//
5
// s80x86 is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
9
//
10
// s80x86 is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
// GNU General Public License for more details.
14
//
15
// You should have received a copy of the GNU General Public License
16
// along with s80x86.  If not, see .
17
 
18
module SPIMaster(input logic clk,
19
                 input logic reset,
20
                 input logic [8:0] divider,
21
                 input logic xfer_start,
22
                 output logic xfer_complete,
23
                 input logic [7:0] tx_data,
24
                 output logic [7:0] rx_data,
25
                 input logic miso,
26
                 output logic mosi,
27
                 output logic sclk);
28
 
29
reg [8:0] clk_counter = 9'b0;
30
reg [3:0] xfer_bit = 4'b0;
31
wire sclk_rising = ~sclk & ~|clk_counter;
32
wire sclk_falling = sclk & ~|clk_counter;
33
wire shift_complete = ~|clk_counter && xfer_bit[3] && sclk;
34
 
35
typedef enum logic [1:0] {
36
    STATE_IDLE,
37
    STATE_XFER,
38
    STATE_COMPLETE
39
} state_t;
40
 
41
state_t state, next_state;
42
 
43
always_comb begin
44
    case (state)
45
    STATE_IDLE: next_state = xfer_start ? STATE_XFER : STATE_IDLE;
46
    STATE_XFER: next_state = shift_complete ? STATE_COMPLETE : STATE_XFER;
47
    STATE_COMPLETE: next_state = STATE_IDLE;
48
    default: ;
49
    endcase
50
 
51
    if (reset)
52
        next_state = STATE_IDLE;
53
end
54
 
55
always_ff @(posedge clk or posedge reset) begin
56
    if (reset) begin
57
        xfer_complete <= 1'b0;
58
        rx_data <= 8'b0;
59
        mosi <= 1'b1;
60
    end else begin
61
        xfer_complete <= 1'b0;
62
 
63
        case (state)
64
        STATE_IDLE: begin
65
            mosi <= xfer_start ? tx_data[7] : 1'b1;
66
            xfer_bit <= 4'b0;
67
        end
68
        STATE_XFER: begin
69
            if (sclk_falling && ~xfer_bit[3])
70
                mosi <= tx_data[~xfer_bit[2:0]];
71
            else if (sclk_rising) begin
72
                xfer_bit <= xfer_bit + 1'b1;
73
                rx_data[~xfer_bit[2:0]] <= miso;
74
            end
75
        end
76
        STATE_COMPLETE: begin
77
            xfer_complete <= 1'b1;
78
            mosi <= 1'b1;
79
        end
80
        default: ;
81
        endcase
82
    end
83
end
84
 
85
always_ff @(posedge clk) begin
86
    case (state)
87
    STATE_IDLE: begin
88
        sclk <= 1'b0;
89
        clk_counter <= divider;
90
    end
91
    STATE_XFER: begin
92
        clk_counter <= clk_counter - 1'b1;
93
        if (~|clk_counter) begin
94
            clk_counter <= divider;
95
            sclk <= ~sclk;
96
        end
97
    end
98
    STATE_COMPLETE: begin
99
        sclk <= 1'b0;
100
    end
101
    default: ;
102
    endcase
103
end
104
 
105
always @(posedge clk)
106
    state <= next_state;
107
 
108
endmodule

powered by: WebSVN 2.1.0

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