File: spi.v

package info (click to toggle)
simulavr 1.0.0%2Bgit20160221.e53413b-1
  • links: PTS
  • area: main
  • in suites: buster
  • size: 5,748 kB
  • sloc: cpp: 35,491; python: 6,991; ansic: 3,567; makefile: 1,072; sh: 653; asm: 414; tcl: 320
file content (139 lines) | stat: -rw-r--r-- 3,149 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
** Copyright (C) 2009 Onno Kortmann <onno@gmx.net>
**  
** 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 2 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, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
**  
*/
/* SPI slave Verilog example code. */
`timescale 1ns / 1ns

module SPIfrontend(nCS, CLK, MOSI, MISO, 
		   inbyte, outbyte, out_valid);
   input nCS;
   input CLK;
   input MOSI;
   output MISO;
   
   reg 	  MISO;
   input [7:0] inbyte;
   output [7:0] outbyte;
   reg [7:0] 	outbyte;
   output 	out_valid;
   reg [2:0] 	bitcnt;

   assign 	out_valid = bitcnt==0;

   always @(posedge nCS) begin // 'reset' condition
      bitcnt<=0;
      outbyte<=0;
   end
   
   always @(posedge CLK) if (!nCS) begin
      MISO<=inbyte[bitcnt];
   end // always @ (posedge CLK)
   
   always @(negedge CLK) if (!nCS) begin
      if (bitcnt)
	outbyte[bitcnt]<=MOSI;
      else
	outbyte<=MOSI;
      bitcnt<=bitcnt+1;
   end
endmodule // SPIfrontend

module SPIslave(nCS, CLK, MOSI, MISO);
   input nCS;
   input CLK;
   input MOSI;
   
   output MISO;

   reg [7:0] inbyte;
   wire [7:0] outbyte;
   wire       out_valid;
   reg [7:0]  mem[0:65535];
   reg [3:0]  state;
   reg [15:0] adr;
   
   SPIfrontend front(nCS, CLK, MOSI, MISO, 
		     inbyte, outbyte, out_valid);

   always @(posedge nCS) begin
      state<=0;
   end
   
   always @(posedge out_valid) if (!nCS) begin
      $display("Received %d", outbyte);
      case (state)
	0: begin
	   adr[7:0]<=outbyte; state<=1;
	end
	1: begin
	   adr[15:8]<=outbyte; state<=2;
	end
	2: begin
	   if (outbyte) begin
	      state<=3;
	   end else begin
	      $display("Reading location 0x%x, which contains 0x%x", adr, mem[adr]);
	      inbyte<=mem[adr];
	      state<=4;
	   end
	end
	3: begin
	   mem[adr]<=outbyte;
	   $display("Writing location 0x%x with 0x%x", adr, outbyte);
	   state<=0;
	end
	4: begin
	   state<=0; // dummy state, this could be interleaved for more performance when reading
	end
      endcase // case(state)
   end
endmodule


module test;
   reg CLK;
   wire nCS, SCK, MOSI;
   wire MISO;

   SPIslave sl(nCS, SCK, MOSI, MISO);

   wire [7:0] pb;
   wire [7:0] pc;
   wire [7:0] pd;

   assign    MISO=pb[4];
   assign    MOSI=pb[3];
   assign    SCK=pb[5];
   assign    nCS=pb[2];
   
   defparam  avr.progfile="spi.elf";
   ATmega8 avr(CLK, pb, pc, pd);
   
   initial begin
      $avr_trace("avr.trace");
      $dumpfile("spi.vcd");
      $dumpvars(0, test);
      # 1000000 $finish;
   end // initial begin
   
   always begin
      #100 CLK<=0; 
      #100 CLK<=1;
   end   
endmodule