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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [boards/] [actel/] [ordb1a3pe1500/] [bench/] [verilog/] [spi_slave.v] - Blame information for rev 592

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 408 julius
/* Simple SPI slave code from http://www.fpga4fun.com/SPI2.html */
2
/* Reading the module increments a counter. */
3
/* LSbit of written data shows on the LED port */
4
 
5
module spi_slave(clk, SCK, MOSI, MISO, SSEL, LED);
6
   input clk;
7
 
8
   input SCK, SSEL, MOSI;
9
   output MISO;
10
 
11
   output LED;
12
 
13
 
14
   // sync SCK to the FPGA clock using a 3-bits shift register
15
   reg [2:0] SCKr = 0;  always @(posedge clk) SCKr <= {SCKr[1:0], SCK};
16
   // now we can detect SCK rising edges
17
   wire      SCK_risingedge = (SCKr[2:1]==2'b01);
18
   // and falling edges 
19
   wire      SCK_fallingedge = (SCKr[2:1]==2'b10);
20
 
21
   // same thing for SSEL
22
   reg [2:0] SSELr = 3'b111;  always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
23
   wire      SSEL_active = ~SSELr[1];  // SSEL is active low
24
   // message starts at falling edge
25
   wire      SSEL_startmessage = (SSELr[2:1]==2'b10);
26
   // message stops at rising edge
27
   wire      SSEL_endmessage = (SSELr[2:1]==2'b01);
28
 
29
   // and for MOSI
30
   reg [1:0] MOSIr = 0;
31
   always @(posedge clk)
32
     MOSIr <= {MOSIr[0], MOSI};
33
 
34
   wire      MOSI_data = MOSIr[1];
35
 
36
   // we handle SPI in 8-bits format, so we need a 3 bits counter to
37
   //  count the bits as they come in
38
   reg [2:0] bitcnt = 0;
39
 
40
   reg       byte_received= 0;  // high when a byte has been received
41
   reg [7:0] byte_data_received = 0;
42
 
43
   always @(posedge clk)
44
     begin
45
        if(~SSEL_active)
46
          bitcnt <= 3'b000;
47
        else
48
          if(SCK_risingedge)
49
            begin
50
               bitcnt <= bitcnt + 3'b001;
51
 
52
               // implement a shift-left register (since we receive the data 
53
               // MSB first)
54
               byte_data_received <= {byte_data_received[6:0], MOSI_data};
55
            end
56
     end
57
 
58
   always @(posedge clk)
59
     byte_received <= SSEL_active && SCK_risingedge && (bitcnt==3'b111);
60
 
61
   // we use the LSB of the data received to control an LED
62
   reg LED = 0;
63
   always @(posedge clk) if(byte_received) LED <= byte_data_received[0];
64
 
65
   reg [7:0] byte_data_sent = 0;
66
 
67
   reg [7:0] cnt = 0;
68
   always @(posedge clk)
69
     if(SSEL_startmessage) cnt<=cnt+8'h1;  // count the messages
70
 
71
   always @(posedge clk)
72
     if(SSEL_active)
73
       begin
74
          if(SSEL_startmessage)
75
            // first byte sent in a message is the message count
76
            byte_data_sent <= cnt;
77
          else
78
            if(SCK_fallingedge)
79
              begin
80
                 if(bitcnt==3'b000)
81
                   byte_data_sent <= 8'h00;  // after that, we send 0s
82
                 else
83
                   byte_data_sent <= {byte_data_sent[6:0], 1'b0};
84
              end
85
       end
86
 
87
   assign MISO = (!SSEL) ? byte_data_sent[7] : 1'bZ;  // send MSB first
88
   // we assume that there is only one slave on the SPI bus
89
   // so we don't bother with a tri-state buffer for MISO
90
   // otherwise we would need to tri-state MISO when SSEL is inactive
91
 
92
endmodule

powered by: WebSVN 2.1.0

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