├── .project ├── LICENSE.txt ├── Mojo-Base.xise ├── clk_divider.v ├── i2c_master.v ├── ipcore_dir └── .gitignore ├── iseconfig ├── Mojo-Base.projectmgr └── mojo_top.xreport ├── read_eeprom.v ├── read_i2c_eeprom.v ├── src ├── 24FC512.v ├── avr_interface.v ├── cclk_detector.v ├── mojo.ucf ├── mojo_top.v ├── serial_rx.v ├── serial_tx.v └── spi_slave.v ├── syn └── .gitignore ├── testbench.v ├── testbench_mojo_top.v └── timer.v /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mojo-Demo 4 | 5 | 6 | 7 | 8 | 9 | net.sourceforge.veditor.simulateBuilder 10 | 11 | 12 | net.sourceforge.veditor.simulateBuilder.00000000Default.CleanCommand 13 | echo 'Clean' 14 | 15 | 16 | net.sourceforge.veditor.simulateBuilder.00000000Default.buildOrder 17 | 0 18 | 19 | 20 | net.sourceforge.veditor.simulateBuilder.00000000Default.command 21 | echo 'No Build Configuration Specified' 22 | 23 | 24 | net.sourceforge.veditor.simulateBuilder.00000000Default.enable 25 | false 26 | 27 | 28 | net.sourceforge.veditor.simulateBuilder.00000000Default.name 29 | Default 30 | 31 | 32 | net.sourceforge.veditor.simulateBuilder.00000000Default.parser 33 | 34 | 35 | 36 | net.sourceforge.veditor.simulateBuilder.00000000Default.workFolder 37 | 38 | 39 | 40 | 41 | 42 | 43 | net.sourceforge.veditor.HdlNature 44 | 45 | 46 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Embedded Micro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Mojo-Base.xise: -------------------------------------------------------------------------------- 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 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 |
424 | -------------------------------------------------------------------------------- /clk_divider.v: -------------------------------------------------------------------------------- 1 | module clk_divider( 2 | input wire reset, 3 | input wire clk_in, 4 | output reg clk_out 5 | ); 6 | 7 | // ref clock = 50MHz 8 | //i2c_clk = 100kHz 9 | //divider = 500 10 | 11 | parameter DIVIDER = 500; 12 | 13 | reg [15:0] count = 0; 14 | 15 | 16 | always @(posedge clk_in) begin 17 | 18 | if (reset == 1) begin 19 | clk_out = 0; 20 | count = 0; 21 | end //if reset 22 | else begin 23 | if (count == ((DIVIDER/2)-1)) begin 24 | //if (count >= 244) begin 25 | clk_out = ~clk_out; 26 | count = 0; 27 | end else begin 28 | count = count + 1'b1; 29 | end //if count >= 244 30 | end // if reset (else) 31 | end //always 32 | 33 | endmodule 34 | -------------------------------------------------------------------------------- /i2c_master.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | /* 3 | 4 | References: 5 | https://eewiki.net/pages/viewpage.action?pageId=10125324 6 | http://faculty.lasierra.edu/~ehwang/digitaldesign/public/projects/DE2/I2C/I2C.pdf 7 | 8 | */ 9 | 10 | module i2c_master( 11 | input wire clk, 12 | input wire reset, 13 | input wire start, 14 | 15 | input wire [7:0] nbytes_in, 16 | input wire [6:0] addr_in, 17 | input wire rw_in, 18 | input wire [7:0] write_data, 19 | output reg [7:0] read_data, 20 | output reg tx_data_req, 21 | output reg rx_data_ready, 22 | 23 | inout wire sda_w, 24 | output wire scl 25 | ); 26 | 27 | //state parameters 28 | localparam STATE_IDLE = 0; 29 | localparam STATE_START = 1; 30 | localparam STATE_ADDR = 2; 31 | localparam STATE_RW = 3; 32 | localparam STATE_ACK = 4; 33 | localparam STATE_READ_ACK = 5; 34 | localparam STATE_TX_DATA = 6; 35 | localparam STATE_RX_DATA = 7; 36 | localparam STATE_STOP = 8; 37 | 38 | localparam READ = 1; 39 | localparam WRITE = 0; 40 | localparam ACK = 0; 41 | 42 | reg [5:0] state; 43 | reg [7:0] bit_count; //bit counter 44 | //local buffers 45 | reg [6:0] addr; 46 | reg [7:0] data; 47 | reg [7:0] nbytes; 48 | reg rw; 49 | reg scl_en = 0; 50 | reg sda; 51 | 52 | //i2c needs to float the sda line when it is high. 53 | //so here I define sda_w which is the wire actually connected to the 54 | // line to be z when sda (logical signal) is 1 55 | assign sda_w = ((sda)==0) ? 1'b0 : 1'bz; 56 | 57 | 58 | //clock 59 | //scl is enabled whenever we are sending or receiving data. 60 | // otherwise it is held at 1 61 | //Note that I also ned to do an ACK check here on the negedge so that I am 62 | // ready to respond on the next posedge below 63 | assign scl = (scl_en == 0) ? 1'b1 : ~clk; 64 | 65 | always @(negedge clk) begin 66 | if (reset == 1) begin 67 | scl_en <= 0; 68 | 69 | end else begin 70 | if ((state == STATE_IDLE) || (state == STATE_START) || (state == STATE_STOP)) begin 71 | scl_en <= 0; 72 | end 73 | else begin 74 | scl_en <= 1; 75 | end 76 | 77 | //I need to check the ack on the rising scl edge (which is the neg edge of clk) 78 | if (state == STATE_ACK) begin 79 | if (0) begin 80 | state <= STATE_IDLE; 81 | end 82 | end 83 | end 84 | 85 | end 86 | 87 | 88 | 89 | //FSM 90 | always @(posedge clk) begin 91 | if (reset == 1) begin 92 | state <= STATE_IDLE; 93 | sda <= 1; 94 | bit_count <= 8'd0; 95 | addr <= 0; 96 | data <= 0; 97 | nbytes <= 0; 98 | rw <= 0; 99 | tx_data_req <= 0; 100 | rx_data_ready <= 0; 101 | end //if reset 102 | 103 | else begin 104 | case(state) 105 | 106 | STATE_IDLE: begin //idle 107 | sda <= 1; 108 | if (start) begin 109 | state <= STATE_START; 110 | end //if start 111 | end 112 | 113 | 114 | STATE_START: begin //start 115 | state <= STATE_ADDR; 116 | sda <= 0; //send start condition 117 | //latch in all the values 118 | addr <= addr_in; 119 | nbytes <= nbytes_in; 120 | rw <= rw_in; 121 | if (rw_in == WRITE) begin 122 | tx_data_req <= 1; //request the first byte of data 123 | end 124 | bit_count <= 6; //addr is only 7 bits long, not 8 125 | end //state_start 126 | 127 | 128 | STATE_ADDR: begin //send slave address 129 | sda <= addr[bit_count]; 130 | if (bit_count == 0) begin 131 | state <= STATE_RW; 132 | end 133 | else begin 134 | bit_count <= bit_count - 1'b1; 135 | end 136 | end //state_addr 137 | 138 | 139 | STATE_RW: begin //send R/W bit 140 | sda <= rw; 141 | state <= STATE_ACK; 142 | end //state_rw 143 | 144 | 145 | STATE_ACK: begin 146 | //release the sda line and await ack 147 | sda <= 1; 148 | //Ack is checked on the next rising edge of scl (neg edge of clk) 149 | //So I just assume that it is all ok and set the next state here 150 | //if there is no ack then the state will be overwritten when it is checked 151 | 152 | tx_data_req <= 0; //time is up. if the data isn't in tx by now it is too late! 153 | 154 | //now we have to decide what to do next. 155 | if (nbytes == 0) begin 156 | //there is no data left to read/write 157 | if (start == 1) begin 158 | //repeat start condition 159 | sda <= 1; 160 | state <= STATE_START; 161 | end else begin 162 | //we are done 163 | sda <= 1; //idle state is high 164 | state <= STATE_STOP; 165 | end //if start == 1 166 | 167 | end else begin 168 | //we have more data to read/write 169 | if (rw == WRITE) begin 170 | data <= write_data; //latch in the new data byte 171 | bit_count <= 7; //8 data bits 172 | state <= STATE_TX_DATA; 173 | end else begin 174 | // Read data 175 | bit_count <= 7; //8 data bits 176 | state <= STATE_RX_DATA; 177 | end //if rw_buf == WRITE 178 | end //if nbytes_buf == 0 179 | 180 | 181 | end //state_ack 182 | 183 | 184 | 185 | STATE_TX_DATA: begin 186 | sda <= data[bit_count]; 187 | if (nbytes > 0) begin 188 | tx_data_req <= 1; //if there are more bytes to write, then request the next one 189 | end 190 | if (bit_count == 0) begin 191 | //byte transfer complete 192 | state <= STATE_ACK; 193 | nbytes <= nbytes - 1'b1; 194 | end 195 | else begin 196 | bit_count <= bit_count - 1'b1; 197 | end 198 | end //state_tx_data 199 | 200 | 201 | 202 | STATE_RX_DATA: begin 203 | data[bit_count] <= sda_w; 204 | if (bit_count == 0) begin 205 | //byte transfer complete 206 | state <= STATE_ACK; 207 | read_data[7:1] <= data[7:1]; 208 | read_data[0] <= sda_w; 209 | rx_data_ready <= 1; 210 | nbytes <= nbytes - 1'b1; 211 | end 212 | else begin 213 | bit_count <= bit_count - 1'b1; 214 | rx_data_ready <= 0; 215 | end 216 | end //state_rx_data 217 | 218 | 219 | 220 | STATE_STOP: begin 221 | sda <= 1; 222 | state <= STATE_IDLE; 223 | end //state_stop 224 | 225 | endcase 226 | end //if reset (else) 227 | end //always 228 | 229 | endmodule 230 | -------------------------------------------------------------------------------- /ipcore_dir/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mcgodfrey/i2c-eeprom/6044391ba0a221a04728c1c1cb80c1bbaded8179/ipcore_dir/.gitignore -------------------------------------------------------------------------------- /iseconfig/Mojo-Base.projectmgr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 2 10 | /avr_interface C:|Users|matt|Documents|projects|mojo|mojo-base-project-master|src|avr_interface.v 11 | /avr_interface |home|justin|workspace|Mojo-Tutorials|Mojo-Base|src|avr_interface.v 12 | /read_i2c_eeprom C:|Users|matt|Documents|projects|mojo|i2c-eeprom|read_i2c_eeprom.v 13 | 14 | 15 | instance_name - read_eeprom (C:/Users/matt/Documents/projects/mojo/i2c-eeprom/read_eeprom.v) 16 | 17 | 0 18 | 0 19 | 000000ff00000000000000010000000100000000000000000000000000000000020200000001000000010000006400000150000000020000000000000000000000000200000064ffffffff000000810000000300000002000001500000000100000003000000000000000100000003 20 | true 21 | instance_name - read_eeprom (C:/Users/matt/Documents/projects/mojo/i2c-eeprom/read_eeprom.v) 22 | 23 | 24 | 25 | 1 26 | Configure Target Device 27 | Design Utilities 28 | Implement Design 29 | Implement Design/Map 30 | Implement Design/Place & Route 31 | Implement Design/Translate 32 | Synthesize - XST 33 | User Constraints 34 | 35 | 36 | 37 | 38 | 0 39 | 0 40 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000234000000010000000100000000000000000000000064ffffffff000000810000000000000001000002340000000100000000 41 | false 42 | 43 | 44 | 45 | 46 | 1 47 | 48 | 49 | 0 50 | 0 51 | 000000ff000000000000000100000000000000000100000000000000000000000000000000000003a3000000040101000100000000000000000000000064ffffffff000000810000000000000004000000770000000100000000000000c50000000100000000000000790000000100000000000001ee0000000100000000 52 | false 53 | avr_interface.v 54 | 55 | 56 | 57 | 1 58 | work 59 | 60 | 61 | 0 62 | 0 63 | 000000ff00000000000000010000000000000000010000000000000000000000000000000000000109000000010001000100000000000000000000000064ffffffff000000810000000000000001000001090000000100000000 64 | false 65 | work 66 | 67 | 000000ff00000000000000020000010b0000011201000000040100000002 68 | Implementation 69 | 70 | 71 | 1 72 | Design Utilities 73 | 74 | 75 | 76 | 77 | 0 78 | 0 79 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000157000000010000000100000000000000000000000064ffffffff000000810000000000000001000001570000000100000000 80 | false 81 | 82 | 83 | 84 | 85 | 1 86 | 87 | 88 | 89 | 90 | 0 91 | 0 92 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000234000000010000000100000000000000000000000064ffffffff000000810000000000000001000002340000000100000000 93 | false 94 | 95 | 96 | 97 | 98 | 2 99 | /avr_interface C:|Users|matt|Documents|projects|mojo|mojo-base-project-master|src|avr_interface.v 100 | 101 | 102 | testbench (C:/Users/matt/Documents/projects/mojo/mojo-base-project-master/testbench.v) 103 | 104 | 3 105 | 0 106 | 000000ff00000000000000010000000100000000000000000000000000000000020200000001000000010000006400000150000000020000000000000000000000000200000064ffffffff000000810000000300000002000001500000000100000003000000000000000100000003 107 | false 108 | testbench (C:/Users/matt/Documents/projects/mojo/mojo-base-project-master/testbench.v) 109 | 110 | 111 | 112 | 1 113 | Design Utilities 114 | 115 | 116 | 117 | 118 | 0 119 | 0 120 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000157000000010000000100000000000000000000000064ffffffff000000810000000000000001000001570000000100000000 121 | false 122 | 123 | 124 | 125 | 126 | 1 127 | 128 | 129 | 130 | 131 | 0 132 | 0 133 | 000000ff00000000000000010000000100000000000000000000000000000000000000000000000157000000010000000100000000000000000000000064ffffffff000000810000000000000001000001570000000100000000 134 | false 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /iseconfig/mojo_top.xreport: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 2016-03-09T21:00:40 5 | mojo_top 6 | 2016-03-09T20:48:44 7 | C:/Users/matt/Documents/projects/mojo/i2c-eeprom/iseconfig/mojo_top.xreport 8 | C:/Users/matt/Documents/projects/mojo/i2c-eeprom/syn\ 9 | 2016-03-05T00:05:56 10 | false 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 32 | 33 | 37 | 38 | 43 | 44 | 45 | 56 | 57 | 83 | 148 | 149 | 214 | 215 |
216 | -------------------------------------------------------------------------------- /read_eeprom.v: -------------------------------------------------------------------------------- 1 | /* 2 | read_eeprom.v 3 | 4 | High Level module to read data from an i2c eeprom device. 5 | 6 | inputs are: 7 | - eeprom chip i2c slave address [7 bit] 8 | - memory address to read from [16 bit] 9 | - number of bytes to read [8 bit] 10 | - start flag to begin the read operation [1-bit] 11 | 12 | outputs are: 13 | - data_out [8-bits] 14 | - byte-ready [1-bit] 15 | 16 | The new byte is placed in data_out as it is read and the byte-ready 17 | flag is set 18 | 19 | There are then a number of lines which communicate with the i1c_master 20 | module which handles the actual communication with the eeprom chip. 21 | 22 | This module handles the sending and receiving of bytes through the i2c module 23 | This includes sending the slave address and memory address, the repeated start 24 | signal and then reading the requested number of bytes. 25 | 26 | The i2c_master module handles the lower level sending/receiving bytes with the actual chip. 27 | 28 | 29 | IDLE 30 | | 31 | | start signal high 32 | | Latch in slave addr, mem addr and nbytes 33 | V 34 | START 35 | | 36 | | set i2c control lines (addr, rw, etc) ready for address write 37 | | set nbytes=2 (16bit address) 38 | V 39 | WRITE_ADDR 40 | | 41 | | For both memory address bytes: 42 | | Wait for tx_data_req to go high (i1c requesting data) and then set it to the mem addr 43 | V 44 | READ_ADDR 45 | | 46 | | Send repeat start 47 | | While nbytes>0, wait for rx_data_ready, set data_out and byte ready 48 | V 49 | IDLE 50 | 51 | */ 52 | 53 | 54 | module read_eeprom( 55 | //inputs 56 | input wire clk, 57 | input wire reset, 58 | input wire [6:0] slave_addr_w, 59 | input wire [15:0] mem_addr_w, 60 | input wire [7:0] read_nbytes_w, 61 | input wire start, 62 | 63 | //outputs 64 | output reg [7:0] data_out, 65 | output reg byte_ready, 66 | 67 | //i2c master comms lines 68 | output reg [6:0] i2c_slave_addr, 69 | output reg i2c_rw, 70 | output reg [7:0] i2c_write_data, 71 | output reg [7:0] i2c_nbytes, 72 | input wire [7:0] i2c_read_data, 73 | input wire i2c_tx_data_req, 74 | input wire i2c_rx_data_ready, 75 | output reg i2c_start, 76 | output reg busy 77 | ); 78 | 79 | 80 | //state params 81 | localparam STATE_IDLE = 0; 82 | localparam STATE_START = 1; 83 | localparam STATE_WRITE_ADDR = 2; 84 | localparam STATE_REP_START = 3; 85 | localparam STATE_READ_DATA = 4; 86 | 87 | localparam READ = 1; 88 | localparam WRITE = 0; 89 | 90 | //local buffers to save the transfer information (device slave addr, 91 | // memory addr, etc) when the transfer is started 92 | reg [3:0] state; 93 | reg [6:0] slave_addr; 94 | reg [15:0] mem_addr; 95 | reg [7:0] read_nbytes; 96 | //output register definitions 97 | reg waiting_for_tx; 98 | reg read_prev_data; 99 | reg [7:0] byte_count; 100 | 101 | 102 | always @(posedge clk) begin 103 | 104 | if (reset == 1) begin 105 | i2c_slave_addr <= 0; 106 | i2c_rw <= 0; 107 | i2c_write_data <= 0; 108 | i2c_start <= 0; 109 | i2c_nbytes <= 0; 110 | 111 | data_out <= 0; 112 | byte_ready <= 0; 113 | 114 | mem_addr <= 0; 115 | slave_addr <= 0; 116 | read_nbytes <= 0; 117 | byte_count <= 0; 118 | waiting_for_tx <= 0; 119 | 120 | busy <= 0; 121 | 122 | state <= STATE_IDLE; 123 | 124 | end else begin 125 | 126 | case(state) 127 | 128 | STATE_IDLE: begin //idle 129 | 130 | busy <= 0; 131 | 132 | if (start) begin 133 | state <= STATE_START; 134 | 135 | //buffer all the control data 136 | slave_addr <= slave_addr_w; 137 | mem_addr <= mem_addr_w; 138 | read_nbytes <= read_nbytes_w; 139 | end 140 | end //state_idle 141 | 142 | 143 | STATE_START: begin 144 | state <= STATE_WRITE_ADDR; 145 | 146 | //set all the i2c control lines 147 | i2c_slave_addr <= slave_addr; 148 | i2c_rw <= WRITE; 149 | i2c_nbytes <= 2; //2 memory addr bytes 150 | byte_count <= 2; 151 | waiting_for_tx <= 0; 152 | 153 | i2c_start <= 1; 154 | busy <= 1; 155 | end //state_start 156 | 157 | 158 | 159 | STATE_WRITE_ADDR: begin 160 | 161 | if (waiting_for_tx == 0) begin 162 | if (i2c_tx_data_req == 1) begin 163 | waiting_for_tx <= 1; 164 | case (byte_count) 165 | 2: begin 166 | i2c_write_data <= mem_addr[15:8]; 167 | byte_count <= byte_count - 1'b1; 168 | end //case 2 169 | 170 | 1: begin 171 | i2c_write_data <= mem_addr[7:0]; 172 | byte_count <= byte_count - 1'b1; 173 | state <= STATE_REP_START; 174 | end //case 1 175 | endcase 176 | end//if i2x_tx_data_req 177 | end else begin 178 | if (i2c_tx_data_req == 0) begin 179 | waiting_for_tx <= 0; 180 | end //if i2x_tx_data_req 181 | end //if waiting_for_tx 182 | 183 | end //state WRITE_ADDR 184 | 185 | 186 | 187 | STATE_REP_START: begin 188 | state <= STATE_READ_DATA; 189 | //set conditions for repeated start and change to read mode 190 | i2c_start <= 1; 191 | i2c_rw <= READ; 192 | i2c_nbytes <= read_nbytes; 193 | read_prev_data <= 0; 194 | byte_count <= 0; 195 | 196 | end //state_rep_start 197 | 198 | 199 | 200 | STATE_READ_DATA: begin 201 | 202 | if (read_prev_data == 0) begin 203 | if (i2c_rx_data_ready) begin 204 | data_out <= i2c_read_data; 205 | byte_ready <= 1; 206 | if (byte_count < (read_nbytes-1)) begin 207 | byte_count <= byte_count + 1'b1; 208 | read_prev_data <= 1; 209 | end else begin 210 | //we are done 211 | i2c_start <= 0; 212 | state <= STATE_IDLE; 213 | end // if byte_count < read_nbytes 214 | end //if i2c_rx_data_ready 215 | 216 | end else begin 217 | if (i2c_rx_data_ready == 0) begin 218 | read_prev_data <= 0; 219 | byte_ready <= 0; 220 | end //if i2c_rx_data_ready 221 | end // if read_prev_data 222 | 223 | end //state_read_data 224 | 225 | endcase 226 | 227 | end 228 | 229 | end 230 | 231 | endmodule 232 | -------------------------------------------------------------------------------- /read_i2c_eeprom.v: -------------------------------------------------------------------------------- 1 | module read_i2c_eeprom( 2 | // 50MHz clock input 3 | input clk, 4 | // Input from reset button (active low) 5 | input rst_n, 6 | // cclk input from AVR, high when AVR is ready 7 | input cclk, 8 | // Outputs to the 8 onboard LEDs 9 | output[7:0]led, 10 | // AVR SPI connections 11 | output spi_miso, 12 | input spi_ss, 13 | input spi_mosi, 14 | input spi_sck, 15 | // AVR ADC channel select 16 | output [3:0] spi_channel, 17 | // Serial connections 18 | input avr_tx, // AVR Tx => FPGA Rx 19 | output avr_rx, // AVR Rx => FPGA Tx 20 | input avr_rx_busy // AVR Rx buffer full 21 | 22 | //i2c User Interface 23 | //output i2c_scl, 24 | //inout i2c_sda 25 | ); 26 | 27 | wire reset = ~rst_n; // make reset active high 28 | 29 | // these signals should be high-z when not used 30 | assign spi_miso = 1'bz; 31 | assign avr_rx = 1'bz; 32 | assign spi_channel = 4'bzzzz; 33 | 34 | assign led[5:0] = 6'b000000; 35 | assign led[7] = tick_1s; 36 | assign led[6] = clk_i2c_in; 37 | 38 | wire tick_1s; 39 | wire i2c_clk_in; 40 | 41 | //wire i2c_scl = 1'b1; 42 | //wire i2c_sda = 1'b1; 43 | 44 | //Generate a 1s timer 45 | timer #(.CTR_LEN(26)) second_timer ( 46 | //timer second_timer ( 47 | .clk(clk), 48 | .reset(reset), 49 | .tick(tick_1s) 50 | ); 51 | 52 | 53 | wire i2c_clk_divider_reset = reset; 54 | 55 | 56 | clk_divider i2c_clk_divider ( 57 | .reset(i2c_clk_divider_reset), 58 | .clk_in(clk), 59 | .clk_out(i2c_clk_in) 60 | ); 61 | 62 | 63 | wire i2c_start; 64 | wire i2c_reset; 65 | wire [7:0] i2c_nbytes; 66 | wire [6:0] i2c_slave_addr; 67 | wire i2c_rw; 68 | wire [7:0] i2c_write_data; 69 | wire [7:0] i2c_read_data; 70 | wire i2c_tx_data_req; 71 | wire i2c_rx_data_ready; 72 | wire i2c_sda; 73 | wire i2c_scl; 74 | wire ready; 75 | wire busy; 76 | 77 | i2c_master i2c ( 78 | .clk(i2c_clk_in), 79 | .reset(i2c_reset), 80 | .start(i2c_start), 81 | .nbytes_in(i2c_nbytes), 82 | .addr_in(i2c_slave_addr), 83 | .rw_in(i2c_rw), 84 | .write_data(i2c_write_data), 85 | .read_data(i2c_read_data), 86 | .tx_data_req(i2c_tx_data_req), 87 | .rx_data_ready(i2c_rx_data_ready), 88 | .sda_w(sda_w), 89 | .scl(scl), 90 | .ready(ready), 91 | .busy(busy) 92 | ); 93 | 94 | wire [6:0] slave_addr = 7'b1010000; 95 | wire [15:0] mem_addr = 16'h0000; 96 | wire [7:0] read_n_bytes = 8'd1; 97 | wire read_eeprom_reset = 1; 98 | 99 | wire [7:0] read_nbytes = 0; 100 | wire start = 0; 101 | wire [7:0] data_out; 102 | wire byte_ready; 103 | 104 | 105 | read_eeprom instance_name ( 106 | .clk(clk), 107 | .reset(read_eeprom_reset), 108 | .slave_addr_w(slave_addr), 109 | .mem_addr_w(mem_addr), 110 | .read_nbytes_w(read_nbytes), 111 | .start(start), 112 | .data_out(data_out), 113 | .byte_ready(byte_ready), 114 | .i2c_slave_addr(i2c_slave_addr), 115 | .i2c_rw(i2c_rw), 116 | .i2c_write_data(i2c_write_data), 117 | .i2c_nbytes(i2c_nbytes), 118 | .i2c_read_data(i2c_read_data), 119 | .i2c_tx_data_req(i2c_tx_data_req), 120 | .i2c_rx_data_ready(i2c_rx_data_ready), 121 | .i2c_start(i2c_start) 122 | ); 123 | 124 | 125 | always @(posedge tick_1s) begin 126 | if (reset == 1) begin 127 | 128 | end else begin 129 | 130 | end // reset 131 | end //always 132 | 133 | 134 | /* 135 | //constants 136 | wire [6:0] slave_addr = 7'b1010000; 137 | wire [7:0] mem_addr = 8'b00000000; 138 | wire [7:0] read_n_bytes = 8'd1; 139 | 140 | reg [7:0] data_out; 141 | 142 | //hookup wires 143 | wire [6:0] i2c_slave_addr; 144 | wire i2c_rw; 145 | wire [7:0] i2c_nbytes; 146 | wire [7:0] i2c_write_data; 147 | wire [7:0] i2c_read_data; 148 | wire i2c_tx_data_req; 149 | wire i2c_rx_data_ready; 150 | wire i2c_start; 151 | 152 | 153 | 154 | 155 | /we need to make sure the i2c module is reset *after* 156 | //it's clock has begun 157 | always @(posedge clk_i2c_in) begin 158 | 159 | if (reset == 1) begin 160 | 161 | end else begin 162 | i2c_reset <= 0; 163 | end 164 | end //posedge clk_i2c_in 165 | 166 | 167 | //Every 1s I read a new value from EEPROM 168 | always @(posedge tick_1s) begin 169 | 170 | 171 | end //posedge tick_1s 172 | 173 | 174 | 175 | read_eeprom instance_name ( 176 | .clk(clk), 177 | .reset(reset), 178 | .slave_addr_w(slave_addr), 179 | .mem_addr_w(mem_addr), 180 | .read_nbytes_w(read_nbytes), 181 | .start(start), 182 | .data_out(data_out), 183 | .byte_ready(byte_ready), 184 | .i2c_slave_addr(i2c_slave_addr), 185 | .i2c_rw(i2c_rw), 186 | .i2c_write_data(i2c_write_data), 187 | .i2c_nbytes(i2c_nbytes), 188 | .i2c_read_data(i2c_read_data), 189 | .i2c_tx_data_req(i2c_tx_data_req), 190 | .i2c_rx_data_ready(i2c_rx_data_ready), 191 | .i2c_start(i2c_start) 192 | ); 193 | 194 | 195 | wire ready; 196 | wire busy; 197 | wire i2c_reset; 198 | 199 | 200 | 201 | 202 | clk_divider i2c_clk_divider ( 203 | .reset(reset), 204 | .clk_in(clk), 205 | .clk_out(clk_i2c_in) 206 | ); 207 | 208 | 209 | i2c_master instance_name ( 210 | .clk(clk_i2c_in), 211 | .reset(i2c_reset), 212 | .start(i2c_start), 213 | .nbytes_in(i2c_nbytes), 214 | .addr_in(i2c_slave_addr), 215 | .rw_in(i2c_rw), 216 | .write_data(i2c_write_data), 217 | .read_data(i2c_read_data), 218 | .tx_data_req(i2c_tx_data_req), 219 | .rx_data_ready(i2c_rx_data_ready), 220 | .sda_w(i2c_sda), 221 | .scl(i2c_scl), 222 | .ready(ready), 223 | .busy(busy) 224 | ); 225 | 226 | */ 227 | 228 | 229 | 230 | 231 | endmodule -------------------------------------------------------------------------------- /src/24FC512.v: -------------------------------------------------------------------------------- 1 | // ******************************************************************************************************* 2 | // ** ** 3 | // ** 24FC512.v - Microchip 24FC512 512K-BIT I2C SERIAL EEPROM (VCC = +1.7V TO +5.5V) ** 4 | // ** ** 5 | // ******************************************************************************************************* 6 | // ** ** 7 | // ** This information is distributed under license from Young Engineering. ** 8 | // ** COPYRIGHT (c) 2009 YOUNG ENGINEERING ** 9 | // ** ALL RIGHTS RESERVED ** 10 | // ** ** 11 | // ** ** 12 | // ** Young Engineering provides design expertise for the digital world ** 13 | // ** Started in 1990, Young Engineering offers products and services for your electronic design ** 14 | // ** project. We have the expertise in PCB, FPGA, ASIC, firmware, and software design. ** 15 | // ** From concept to prototype to production, we can help you. ** 16 | // ** ** 17 | // ** http://www.young-engineering.com/ ** 18 | // ** ** 19 | // ******************************************************************************************************* 20 | // ** This information is provided to you for your convenience and use with Microchip products only. ** 21 | // ** Microchip disclaims all liability arising from this information and its use. ** 22 | // ** ** 23 | // ** THIS INFORMATION IS PROVIDED "AS IS." MICROCHIP MAKES NO REPRESENTATION OR WARRANTIES OF ** 24 | // ** ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO ** 25 | // ** THE INFORMATION PROVIDED TO YOU, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, ** 26 | // ** PERFORMANCE, MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR PURPOSE. ** 27 | // ** MICROCHIP IS NOT LIABLE, UNDER ANY CIRCUMSTANCES, FOR SPECIAL, INCIDENTAL OR CONSEQUENTIAL ** 28 | // ** DAMAGES, FOR ANY REASON WHATSOEVER. ** 29 | // ** ** 30 | // ** It is your responsibility to ensure that your application meets with your specifications. ** 31 | // ** ** 32 | // ******************************************************************************************************* 33 | // ** Revision : 1.0 ** 34 | // ** Modified Date : 02/04/2009 ** 35 | // ** Revision History: ** 36 | // ** ** 37 | // ** 02/04/2009: Initial design ** 38 | // ** ** 39 | // ******************************************************************************************************* 40 | // ** TABLE OF CONTENTS ** 41 | // ******************************************************************************************************* 42 | // **---------------------------------------------------------------------------------------------------** 43 | // ** DECLARATIONS ** 44 | // **---------------------------------------------------------------------------------------------------** 45 | // **---------------------------------------------------------------------------------------------------** 46 | // ** INITIALIZATION ** 47 | // **---------------------------------------------------------------------------------------------------** 48 | // **---------------------------------------------------------------------------------------------------** 49 | // ** CORE LOGIC ** 50 | // **---------------------------------------------------------------------------------------------------** 51 | // ** 1.01: START Bit Detection ** 52 | // ** 1.02: STOP Bit Detection ** 53 | // ** 1.03: Input Shift Register ** 54 | // ** 1.04: Input Bit Counter ** 55 | // ** 1.05: Control Byte Register ** 56 | // ** 1.06: Byte Address Register ** 57 | // ** 1.07: Write Data Buffer ** 58 | // ** 1.08: Acknowledge Generator ** 59 | // ** 1.09: Acknowledge Detect ** 60 | // ** 1.10: Write Cycle Timer ** 61 | // ** 1.11: Write Cycle Processor ** 62 | // ** 1.12: Read Data Multiplexor ** 63 | // ** 1.13: Read Data Processor ** 64 | // ** 1.14: SDA Data I/O Buffer ** 65 | // ** ** 66 | // **---------------------------------------------------------------------------------------------------** 67 | // ** DEBUG LOGIC ** 68 | // **---------------------------------------------------------------------------------------------------** 69 | // ** 2.01: Memory Data Bytes ** 70 | // ** 2.02: Write Data Buffer ** 71 | // ** ** 72 | // **---------------------------------------------------------------------------------------------------** 73 | // ** TIMING CHECKS ** 74 | // **---------------------------------------------------------------------------------------------------** 75 | // ** ** 76 | // ******************************************************************************************************* 77 | 78 | 79 | `timescale 1ns/10ps 80 | 81 | module M24FC512 (A0, A1, A2, WP, SDA, SCL, RESET); 82 | 83 | input A0; // chip select bit 84 | input A1; // chip select bit 85 | input A2; // chip select bit 86 | 87 | input WP; // write protect pin 88 | 89 | inout SDA; // serial data I/O 90 | input SCL; // serial data clock 91 | 92 | input RESET; // system reset 93 | 94 | 95 | // ******************************************************************************************************* 96 | // ** DECLARATIONS ** 97 | // ******************************************************************************************************* 98 | 99 | reg SDA_DO; // serial data - output 100 | reg SDA_OE; // serial data - output enable 101 | 102 | wire SDA_DriveEnable; // serial data output enable 103 | reg SDA_DriveEnableDlyd; // serial data output enable - delayed 104 | 105 | wire [02:00] ChipAddress; // hardwired chip address 106 | 107 | reg [03:00] BitCounter; // serial bit counter 108 | 109 | reg START_Rcvd; // START bit received flag 110 | reg STOP_Rcvd; // STOP bit received flag 111 | reg CTRL_Rcvd; // control byte received flag 112 | reg ADHI_Rcvd; // byte address hi received flag 113 | reg ADLO_Rcvd; // byte address lo received flag 114 | reg MACK_Rcvd; // master acknowledge received flag 115 | 116 | reg WrCycle; // memory write cycle 117 | reg RdCycle; // memory read cycle 118 | 119 | reg [07:00] ShiftRegister; // input data shift register 120 | 121 | reg [07:00] ControlByte; // control byte register 122 | wire RdWrBit; // read/write control bit 123 | 124 | reg [15:00] StartAddress; // memory access starting address 125 | reg [06:00] PageAddress; // memory page address 126 | 127 | reg [07:00] WrDataByte [0:127]; // memory write data buffer 128 | wire [07:00] RdDataByte; // memory read data 129 | 130 | reg [15:00] WrCounter; // write buffer counter 131 | 132 | reg [06:00] WrPointer; // write buffer pointer 133 | reg [15:00] RdPointer; // read address pointer 134 | 135 | reg WriteActive; // memory write cycle active 136 | 137 | reg [07:00] MemoryBlock [0:65535]; // EEPROM data memory array 138 | 139 | integer LoopIndex; // iterative loop index 140 | 141 | integer tAA; // timing parameter 142 | integer tWC; // timing parameter 143 | 144 | 145 | // ******************************************************************************************************* 146 | // ** INITIALIZATION ** 147 | // ******************************************************************************************************* 148 | 149 | initial begin 150 | `ifdef VCC_1_7V_TO_2_5V 151 | tAA = 900; // SCL to SDA output delay 152 | tWC = 5000000; // memory write cycle time 153 | `else 154 | `ifdef VCC_2_5V_TO_5_5V 155 | tAA = 400; // SCL to SDA output delay 156 | tWC = 5000000; // memory write cycle time 157 | `else 158 | tAA = 400; // SCL to SDA output delay 159 | tWC = 5000000; // memory write cycle time 160 | `endif 161 | `endif 162 | end 163 | 164 | initial begin 165 | SDA_DO = 0; 166 | SDA_OE = 0; 167 | end 168 | 169 | initial begin 170 | START_Rcvd = 0; 171 | STOP_Rcvd = 0; 172 | CTRL_Rcvd = 0; 173 | ADHI_Rcvd = 0; 174 | ADLO_Rcvd = 0; 175 | MACK_Rcvd = 0; 176 | end 177 | 178 | initial begin 179 | BitCounter = 0; 180 | ControlByte = 0; 181 | end 182 | 183 | initial begin 184 | WrCycle = 0; 185 | RdCycle = 0; 186 | 187 | WriteActive = 0; 188 | end 189 | 190 | assign ChipAddress = {A2,A1,A0}; 191 | 192 | 193 | // ******************************************************************************************************* 194 | // ** CORE LOGIC ** 195 | // ******************************************************************************************************* 196 | // ------------------------------------------------------------------------------------------------------- 197 | // 1.01: START Bit Detection 198 | // ------------------------------------------------------------------------------------------------------- 199 | 200 | always @(negedge SDA) begin 201 | if (SCL == 1) begin 202 | START_Rcvd <= 1; 203 | STOP_Rcvd <= 0; 204 | CTRL_Rcvd <= 0; 205 | ADHI_Rcvd <= 0; 206 | ADLO_Rcvd <= 0; 207 | MACK_Rcvd <= 0; 208 | 209 | WrCycle <= #1 0; 210 | RdCycle <= #1 0; 211 | 212 | BitCounter <= 0; 213 | end 214 | end 215 | 216 | // ------------------------------------------------------------------------------------------------------- 217 | // 1.02: STOP Bit Detection 218 | // ------------------------------------------------------------------------------------------------------- 219 | 220 | always @(posedge SDA) begin 221 | if (SCL == 1) begin 222 | START_Rcvd <= 0; 223 | STOP_Rcvd <= 1; 224 | CTRL_Rcvd <= 0; 225 | ADHI_Rcvd <= 0; 226 | ADLO_Rcvd <= 0; 227 | MACK_Rcvd <= 0; 228 | 229 | WrCycle <= #1 0; 230 | RdCycle <= #1 0; 231 | 232 | BitCounter <= 10; 233 | end 234 | end 235 | 236 | // ------------------------------------------------------------------------------------------------------- 237 | // 1.03: Input Shift Register 238 | // ------------------------------------------------------------------------------------------------------- 239 | 240 | always @(posedge SCL) begin 241 | ShiftRegister[00] <= SDA; 242 | ShiftRegister[01] <= ShiftRegister[00]; 243 | ShiftRegister[02] <= ShiftRegister[01]; 244 | ShiftRegister[03] <= ShiftRegister[02]; 245 | ShiftRegister[04] <= ShiftRegister[03]; 246 | ShiftRegister[05] <= ShiftRegister[04]; 247 | ShiftRegister[06] <= ShiftRegister[05]; 248 | ShiftRegister[07] <= ShiftRegister[06]; 249 | end 250 | 251 | // ------------------------------------------------------------------------------------------------------- 252 | // 1.04: Input Bit Counter 253 | // ------------------------------------------------------------------------------------------------------- 254 | 255 | always @(posedge SCL) begin 256 | if (BitCounter < 10) BitCounter <= BitCounter + 1; 257 | end 258 | 259 | // ------------------------------------------------------------------------------------------------------- 260 | // 1.05: Control Byte Register 261 | // ------------------------------------------------------------------------------------------------------- 262 | 263 | always @(negedge SCL) begin 264 | if (START_Rcvd & (BitCounter == 8)) begin 265 | if (!WriteActive & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]})) begin 266 | if (ShiftRegister[00] == 0) WrCycle <= 1; 267 | if (ShiftRegister[00] == 1) RdCycle <= 1; 268 | 269 | ControlByte <= ShiftRegister[07:00]; 270 | 271 | CTRL_Rcvd <= 1; 272 | end 273 | 274 | START_Rcvd <= 0; 275 | end 276 | end 277 | 278 | assign RdWrBit = ControlByte[00]; 279 | 280 | // ------------------------------------------------------------------------------------------------------- 281 | // 1.06: Byte Address Register 282 | // ------------------------------------------------------------------------------------------------------- 283 | 284 | always @(negedge SCL) begin 285 | if (CTRL_Rcvd & (BitCounter == 8)) begin 286 | if (RdWrBit == 0) begin 287 | StartAddress[15:08] <= ShiftRegister[07:00]; 288 | RdPointer[15:08] <= ShiftRegister[07:00]; 289 | 290 | ADHI_Rcvd <= 1; 291 | end 292 | 293 | WrCounter <= 0; 294 | WrPointer <= 0; 295 | 296 | CTRL_Rcvd <= 0; 297 | end 298 | end 299 | 300 | always @(negedge SCL) begin 301 | if (ADHI_Rcvd & (BitCounter == 8)) begin 302 | if (RdWrBit == 0) begin 303 | StartAddress[07:00] <= ShiftRegister[07:00]; 304 | RdPointer[07:00] <= ShiftRegister[07:00]; 305 | 306 | ADLO_Rcvd <= 1; 307 | end 308 | 309 | WrCounter <= 0; 310 | WrPointer <= 0; 311 | 312 | ADHI_Rcvd <= 0; 313 | end 314 | end 315 | 316 | // ------------------------------------------------------------------------------------------------------- 317 | // 1.07: Write Data Buffer 318 | // ------------------------------------------------------------------------------------------------------- 319 | 320 | always @(negedge SCL) begin 321 | if (ADLO_Rcvd & (BitCounter == 8)) begin 322 | if (RdWrBit == 0) begin 323 | WrDataByte[WrPointer] <= ShiftRegister[07:00]; 324 | 325 | WrCounter <= WrCounter + 1; 326 | WrPointer <= WrPointer + 1; 327 | end 328 | end 329 | end 330 | 331 | // ------------------------------------------------------------------------------------------------------- 332 | // 1.08: Acknowledge Generator 333 | // ------------------------------------------------------------------------------------------------------- 334 | 335 | always @(negedge SCL) begin 336 | if (!WriteActive) begin 337 | if (BitCounter == 8) begin 338 | if (WrCycle | (START_Rcvd & (ShiftRegister[07:01] == {4'b1010,ChipAddress[02:00]}))) begin 339 | SDA_DO <= 0; 340 | SDA_OE <= 1; 341 | end 342 | end 343 | if (BitCounter == 9) begin 344 | BitCounter <= 0; 345 | 346 | if (!RdCycle) begin 347 | SDA_DO <= 0; 348 | SDA_OE <= 0; 349 | end 350 | end 351 | end 352 | end 353 | 354 | // ------------------------------------------------------------------------------------------------------- 355 | // 1.09: Acknowledge Detect 356 | // ------------------------------------------------------------------------------------------------------- 357 | 358 | always @(posedge SCL) begin 359 | if (RdCycle & (BitCounter == 8)) begin 360 | if ((SDA == 0) & (SDA_OE == 0)) MACK_Rcvd <= 1; 361 | end 362 | end 363 | 364 | always @(negedge SCL) MACK_Rcvd <= 0; 365 | 366 | // ------------------------------------------------------------------------------------------------------- 367 | // 1.10: Write Cycle Timer 368 | // ------------------------------------------------------------------------------------------------------- 369 | 370 | always @(posedge STOP_Rcvd) begin 371 | if (WrCycle & (WP == 0) & (WrCounter > 0)) begin 372 | WriteActive = 1; 373 | #(tWC); 374 | WriteActive = 0; 375 | end 376 | end 377 | 378 | always @(posedge STOP_Rcvd) begin 379 | #(1.0); 380 | STOP_Rcvd = 0; 381 | end 382 | 383 | // ------------------------------------------------------------------------------------------------------- 384 | // 1.11: Write Cycle Processor 385 | // ------------------------------------------------------------------------------------------------------- 386 | 387 | always @(negedge WriteActive) begin 388 | for (LoopIndex = 0; LoopIndex < WrCounter; LoopIndex = LoopIndex + 1) begin 389 | PageAddress = StartAddress[06:00] + LoopIndex; 390 | 391 | MemoryBlock[{StartAddress[15:07],PageAddress[06:00]}] = WrDataByte[LoopIndex[06:00]]; 392 | end 393 | end 394 | 395 | // ------------------------------------------------------------------------------------------------------- 396 | // 1.12: Read Data Multiplexor 397 | // ------------------------------------------------------------------------------------------------------- 398 | 399 | always @(negedge SCL) begin 400 | if (BitCounter == 8) begin 401 | if (WrCycle & ADLO_Rcvd) begin 402 | RdPointer <= StartAddress + WrPointer + 1; 403 | end 404 | if (RdCycle) begin 405 | RdPointer <= RdPointer + 1; 406 | end 407 | end 408 | end 409 | 410 | assign RdDataByte = MemoryBlock[RdPointer[15:00]]; 411 | 412 | // ------------------------------------------------------------------------------------------------------- 413 | // 1.13: Read Data Processor 414 | // ------------------------------------------------------------------------------------------------------- 415 | 416 | always @(negedge SCL) begin 417 | if (RdCycle) begin 418 | if (BitCounter == 8) begin 419 | SDA_DO <= 0; 420 | SDA_OE <= 0; 421 | end 422 | else if (BitCounter == 9) begin 423 | SDA_DO <= RdDataByte[07]; 424 | 425 | if (MACK_Rcvd) SDA_OE <= 1; 426 | end 427 | else begin 428 | SDA_DO <= RdDataByte[7-BitCounter]; 429 | end 430 | end 431 | end 432 | 433 | // ------------------------------------------------------------------------------------------------------- 434 | // 1.14: SDA Data I/O Buffer 435 | // ------------------------------------------------------------------------------------------------------- 436 | 437 | bufif1 (SDA, 1'b0, SDA_DriveEnableDlyd); 438 | 439 | assign SDA_DriveEnable = !SDA_DO & SDA_OE; 440 | always @(SDA_DriveEnable) SDA_DriveEnableDlyd <= #(tAA) SDA_DriveEnable; 441 | 442 | 443 | // ******************************************************************************************************* 444 | // ** DEBUG LOGIC ** 445 | // ******************************************************************************************************* 446 | // ------------------------------------------------------------------------------------------------------- 447 | // 2.01: Memory Data Bytes 448 | // ------------------------------------------------------------------------------------------------------- 449 | 450 | wire [07:00] MemoryByte_000 = MemoryBlock[00]; 451 | wire [07:00] MemoryByte_001 = MemoryBlock[01]; 452 | wire [07:00] MemoryByte_002 = MemoryBlock[02]; 453 | wire [07:00] MemoryByte_003 = MemoryBlock[03]; 454 | wire [07:00] MemoryByte_004 = MemoryBlock[04]; 455 | wire [07:00] MemoryByte_005 = MemoryBlock[05]; 456 | wire [07:00] MemoryByte_006 = MemoryBlock[06]; 457 | wire [07:00] MemoryByte_007 = MemoryBlock[07]; 458 | wire [07:00] MemoryByte_008 = MemoryBlock[08]; 459 | wire [07:00] MemoryByte_009 = MemoryBlock[09]; 460 | wire [07:00] MemoryByte_00A = MemoryBlock[10]; 461 | wire [07:00] MemoryByte_00B = MemoryBlock[11]; 462 | wire [07:00] MemoryByte_00C = MemoryBlock[12]; 463 | wire [07:00] MemoryByte_00D = MemoryBlock[13]; 464 | wire [07:00] MemoryByte_00E = MemoryBlock[14]; 465 | wire [07:00] MemoryByte_00F = MemoryBlock[15]; 466 | 467 | // ------------------------------------------------------------------------------------------------------- 468 | // 2.02: Write Data Buffer 469 | // ------------------------------------------------------------------------------------------------------- 470 | 471 | wire [07:00] WriteData_00 = WrDataByte[00]; 472 | wire [07:00] WriteData_01 = WrDataByte[01]; 473 | wire [07:00] WriteData_02 = WrDataByte[02]; 474 | wire [07:00] WriteData_03 = WrDataByte[03]; 475 | wire [07:00] WriteData_04 = WrDataByte[04]; 476 | wire [07:00] WriteData_05 = WrDataByte[05]; 477 | wire [07:00] WriteData_06 = WrDataByte[06]; 478 | wire [07:00] WriteData_07 = WrDataByte[07]; 479 | wire [07:00] WriteData_08 = WrDataByte[08]; 480 | wire [07:00] WriteData_09 = WrDataByte[09]; 481 | wire [07:00] WriteData_0A = WrDataByte[10]; 482 | wire [07:00] WriteData_0B = WrDataByte[11]; 483 | wire [07:00] WriteData_0C = WrDataByte[12]; 484 | wire [07:00] WriteData_0D = WrDataByte[13]; 485 | wire [07:00] WriteData_0E = WrDataByte[14]; 486 | wire [07:00] WriteData_0F = WrDataByte[15]; 487 | 488 | wire [07:00] WriteData_10 = WrDataByte[16]; 489 | wire [07:00] WriteData_11 = WrDataByte[17]; 490 | wire [07:00] WriteData_12 = WrDataByte[18]; 491 | wire [07:00] WriteData_13 = WrDataByte[19]; 492 | wire [07:00] WriteData_14 = WrDataByte[20]; 493 | wire [07:00] WriteData_15 = WrDataByte[21]; 494 | wire [07:00] WriteData_16 = WrDataByte[22]; 495 | wire [07:00] WriteData_17 = WrDataByte[23]; 496 | wire [07:00] WriteData_18 = WrDataByte[24]; 497 | wire [07:00] WriteData_19 = WrDataByte[25]; 498 | wire [07:00] WriteData_1A = WrDataByte[26]; 499 | wire [07:00] WriteData_1B = WrDataByte[27]; 500 | wire [07:00] WriteData_1C = WrDataByte[28]; 501 | wire [07:00] WriteData_1D = WrDataByte[29]; 502 | wire [07:00] WriteData_1E = WrDataByte[30]; 503 | wire [07:00] WriteData_1F = WrDataByte[31]; 504 | 505 | wire [07:00] WriteData_20 = WrDataByte[32]; 506 | wire [07:00] WriteData_21 = WrDataByte[33]; 507 | wire [07:00] WriteData_22 = WrDataByte[34]; 508 | wire [07:00] WriteData_23 = WrDataByte[35]; 509 | wire [07:00] WriteData_24 = WrDataByte[36]; 510 | wire [07:00] WriteData_25 = WrDataByte[37]; 511 | wire [07:00] WriteData_26 = WrDataByte[38]; 512 | wire [07:00] WriteData_27 = WrDataByte[39]; 513 | wire [07:00] WriteData_28 = WrDataByte[40]; 514 | wire [07:00] WriteData_29 = WrDataByte[41]; 515 | wire [07:00] WriteData_2A = WrDataByte[42]; 516 | wire [07:00] WriteData_2B = WrDataByte[43]; 517 | wire [07:00] WriteData_2C = WrDataByte[44]; 518 | wire [07:00] WriteData_2D = WrDataByte[45]; 519 | wire [07:00] WriteData_2E = WrDataByte[46]; 520 | wire [07:00] WriteData_2F = WrDataByte[47]; 521 | 522 | wire [07:00] WriteData_30 = WrDataByte[48]; 523 | wire [07:00] WriteData_31 = WrDataByte[49]; 524 | wire [07:00] WriteData_32 = WrDataByte[50]; 525 | wire [07:00] WriteData_33 = WrDataByte[51]; 526 | wire [07:00] WriteData_34 = WrDataByte[52]; 527 | wire [07:00] WriteData_35 = WrDataByte[53]; 528 | wire [07:00] WriteData_36 = WrDataByte[54]; 529 | wire [07:00] WriteData_37 = WrDataByte[55]; 530 | wire [07:00] WriteData_38 = WrDataByte[56]; 531 | wire [07:00] WriteData_39 = WrDataByte[57]; 532 | wire [07:00] WriteData_3A = WrDataByte[58]; 533 | wire [07:00] WriteData_3B = WrDataByte[59]; 534 | wire [07:00] WriteData_3C = WrDataByte[60]; 535 | wire [07:00] WriteData_3D = WrDataByte[61]; 536 | wire [07:00] WriteData_3E = WrDataByte[62]; 537 | wire [07:00] WriteData_3F = WrDataByte[63]; 538 | 539 | wire [07:00] WriteData_40 = WrDataByte[64]; 540 | wire [07:00] WriteData_41 = WrDataByte[65]; 541 | wire [07:00] WriteData_42 = WrDataByte[66]; 542 | wire [07:00] WriteData_43 = WrDataByte[67]; 543 | wire [07:00] WriteData_44 = WrDataByte[68]; 544 | wire [07:00] WriteData_45 = WrDataByte[69]; 545 | wire [07:00] WriteData_46 = WrDataByte[70]; 546 | wire [07:00] WriteData_47 = WrDataByte[71]; 547 | wire [07:00] WriteData_48 = WrDataByte[72]; 548 | wire [07:00] WriteData_49 = WrDataByte[73]; 549 | wire [07:00] WriteData_4A = WrDataByte[74]; 550 | wire [07:00] WriteData_4B = WrDataByte[75]; 551 | wire [07:00] WriteData_4C = WrDataByte[76]; 552 | wire [07:00] WriteData_4D = WrDataByte[77]; 553 | wire [07:00] WriteData_4E = WrDataByte[78]; 554 | wire [07:00] WriteData_4F = WrDataByte[79]; 555 | 556 | wire [07:00] WriteData_50 = WrDataByte[80]; 557 | wire [07:00] WriteData_51 = WrDataByte[81]; 558 | wire [07:00] WriteData_52 = WrDataByte[82]; 559 | wire [07:00] WriteData_53 = WrDataByte[83]; 560 | wire [07:00] WriteData_54 = WrDataByte[84]; 561 | wire [07:00] WriteData_55 = WrDataByte[85]; 562 | wire [07:00] WriteData_56 = WrDataByte[86]; 563 | wire [07:00] WriteData_57 = WrDataByte[87]; 564 | wire [07:00] WriteData_58 = WrDataByte[88]; 565 | wire [07:00] WriteData_59 = WrDataByte[89]; 566 | wire [07:00] WriteData_5A = WrDataByte[90]; 567 | wire [07:00] WriteData_5B = WrDataByte[91]; 568 | wire [07:00] WriteData_5C = WrDataByte[92]; 569 | wire [07:00] WriteData_5D = WrDataByte[93]; 570 | wire [07:00] WriteData_5E = WrDataByte[94]; 571 | wire [07:00] WriteData_5F = WrDataByte[95]; 572 | 573 | wire [07:00] WriteData_60 = WrDataByte[96]; 574 | wire [07:00] WriteData_61 = WrDataByte[97]; 575 | wire [07:00] WriteData_62 = WrDataByte[98]; 576 | wire [07:00] WriteData_63 = WrDataByte[99]; 577 | wire [07:00] WriteData_64 = WrDataByte[100]; 578 | wire [07:00] WriteData_65 = WrDataByte[101]; 579 | wire [07:00] WriteData_66 = WrDataByte[102]; 580 | wire [07:00] WriteData_67 = WrDataByte[103]; 581 | wire [07:00] WriteData_68 = WrDataByte[104]; 582 | wire [07:00] WriteData_69 = WrDataByte[105]; 583 | wire [07:00] WriteData_6A = WrDataByte[106]; 584 | wire [07:00] WriteData_6B = WrDataByte[107]; 585 | wire [07:00] WriteData_6C = WrDataByte[108]; 586 | wire [07:00] WriteData_6D = WrDataByte[109]; 587 | wire [07:00] WriteData_6E = WrDataByte[110]; 588 | wire [07:00] WriteData_6F = WrDataByte[111]; 589 | 590 | wire [07:00] WriteData_70 = WrDataByte[112]; 591 | wire [07:00] WriteData_71 = WrDataByte[113]; 592 | wire [07:00] WriteData_72 = WrDataByte[114]; 593 | wire [07:00] WriteData_73 = WrDataByte[115]; 594 | wire [07:00] WriteData_74 = WrDataByte[116]; 595 | wire [07:00] WriteData_75 = WrDataByte[117]; 596 | wire [07:00] WriteData_76 = WrDataByte[118]; 597 | wire [07:00] WriteData_77 = WrDataByte[119]; 598 | wire [07:00] WriteData_78 = WrDataByte[120]; 599 | wire [07:00] WriteData_79 = WrDataByte[121]; 600 | wire [07:00] WriteData_7A = WrDataByte[122]; 601 | wire [07:00] WriteData_7B = WrDataByte[123]; 602 | wire [07:00] WriteData_7C = WrDataByte[124]; 603 | wire [07:00] WriteData_7D = WrDataByte[125]; 604 | wire [07:00] WriteData_7E = WrDataByte[126]; 605 | wire [07:00] WriteData_7F = WrDataByte[127]; 606 | 607 | 608 | // ******************************************************************************************************* 609 | // ** TIMING CHECKS ** 610 | // ******************************************************************************************************* 611 | 612 | wire TimingCheckEnable = (RESET == 0) & (SDA_OE == 0); 613 | wire tstSTOP = STOP_Rcvd; 614 | 615 | specify 616 | `ifdef VCC_1_7V_TO_2_5V 617 | specparam 618 | tHI = 600, // SCL pulse width - high 619 | tLO = 1300, // SCL pulse width - low 620 | tSU_STA = 600, // SCL to SDA setup time 621 | tHD_STA = 600, // SCL to SDA hold time 622 | tSU_DAT = 100, // SDA to SCL setup time 623 | tSU_STO = 600, // SCL to SDA setup time 624 | tSU_WP = 600, // WP to SDA setup time 625 | tHD_WP = 1300, // WP to SDA hold time 626 | tBUF = 1300; // Bus free time 627 | `else 628 | `ifdef VCC_2_5V_TO_5_5V 629 | specparam 630 | tHI = 500, // SCL pulse width - high 631 | tLO = 500, // SCL pulse width - low 632 | tSU_STA = 250, // SCL to SDA setup time 633 | tHD_STA = 250, // SCL to SDA hold time 634 | tSU_DAT = 100, // SDA to SCL setup time 635 | tSU_STO = 250, // SCL to SDA setup time 636 | tSU_WP = 600, // WP to SDA setup time 637 | tHD_WP = 1300, // WP to SDA hold time 638 | tBUF = 500; // Bus free time 639 | `else 640 | specparam 641 | tHI = 500, // SCL pulse width - high 642 | tLO = 500, // SCL pulse width - low 643 | tSU_STA = 250, // SCL to SDA setup time 644 | tHD_STA = 250, // SCL to SDA hold time 645 | tSU_DAT = 100, // SDA to SCL setup time 646 | tSU_STO = 250, // SCL to SDA setup time 647 | tSU_WP = 600, // WP to SDA setup time 648 | tHD_WP = 1300, // WP to SDA hold time 649 | tBUF = 500; // Bus free time 650 | `endif 651 | `endif 652 | 653 | $width (posedge SCL, tHI); 654 | $width (negedge SCL, tLO); 655 | 656 | $width (posedge SDA &&& SCL, tBUF); 657 | 658 | $setup (posedge SCL, negedge SDA &&& TimingCheckEnable, tSU_STA); 659 | $setup (SDA, posedge SCL &&& TimingCheckEnable, tSU_DAT); 660 | $setup (posedge SCL, posedge SDA &&& TimingCheckEnable, tSU_STO); 661 | $setup (WP, posedge tstSTOP &&& TimingCheckEnable, tSU_WP); 662 | 663 | $hold (negedge SDA &&& TimingCheckEnable, negedge SCL, tHD_STA); 664 | $hold (posedge tstSTOP &&& TimingCheckEnable, WP, tHD_WP); 665 | endspecify 666 | 667 | endmodule 668 | -------------------------------------------------------------------------------- /src/avr_interface.v: -------------------------------------------------------------------------------- 1 | module avr_interface #( 2 | parameter CLK_RATE = 50000000, 3 | parameter SERIAL_BAUD_RATE = 500000 4 | )( 5 | input clk, 6 | input rst, 7 | 8 | // cclk, or configuration clock is used when the FPGA is begin configured. 9 | // The AVR will hold cclk high when it has finished initializing. 10 | // It is important not to drive the lines connecting to the AVR 11 | // until cclk is high for a short period of time to avoid contention. 12 | input cclk, 13 | 14 | // AVR SPI Signals 15 | output spi_miso, 16 | input spi_mosi, 17 | input spi_sck, 18 | input spi_ss, 19 | output [3:0] spi_channel, 20 | 21 | // AVR Serial Signals 22 | output tx, 23 | input rx, 24 | 25 | // ADC Interface Signals 26 | input [3:0] channel, 27 | output new_sample, 28 | output [9:0] sample, 29 | output [3:0] sample_channel, 30 | 31 | // Serial TX User Interface 32 | input [7:0] tx_data, 33 | input new_tx_data, 34 | output tx_busy, 35 | input tx_block, 36 | 37 | // Serial Rx User Interface 38 | output [7:0] rx_data, 39 | output new_rx_data 40 | ); 41 | 42 | wire ready; 43 | wire n_rdy = !ready; 44 | wire spi_done; 45 | wire [7:0] spi_dout; 46 | 47 | wire tx_m; 48 | wire spi_miso_m; 49 | 50 | reg byte_ct_d, byte_ct_q; 51 | reg [9:0] sample_d, sample_q; 52 | reg new_sample_d, new_sample_q; 53 | reg [3:0] sample_channel_d, sample_channel_q; 54 | reg [3:0] block_d, block_q; 55 | reg busy_d, busy_q; 56 | 57 | // cclk_detector is used to detect when cclk is high signaling when 58 | // the AVR is ready 59 | cclk_detector #(.CLK_RATE(CLK_RATE)) cclk_detector ( 60 | .clk(clk), 61 | .rst(rst), 62 | .cclk(cclk), 63 | .ready(ready) 64 | ); 65 | 66 | spi_slave spi_slave ( 67 | .clk(clk), 68 | .rst(n_rdy), 69 | .ss(spi_ss), 70 | .mosi(spi_mosi), 71 | .miso(spi_miso_m), 72 | .sck(spi_sck), 73 | .done(spi_done), 74 | .din(8'hff), 75 | .dout(spi_dout) 76 | ); 77 | 78 | // CLK_PER_BIT is the number of cycles each 'bit' lasts for 79 | // rtoi converts a 'real' number to an 'integer' 80 | parameter CLK_PER_BIT = $rtoi($ceil(CLK_RATE/SERIAL_BAUD_RATE)); 81 | 82 | serial_rx #(.CLK_PER_BIT(CLK_PER_BIT)) serial_rx ( 83 | .clk(clk), 84 | .rst(n_rdy), 85 | .rx(rx), 86 | .data(rx_data), 87 | .new_data(new_rx_data) 88 | ); 89 | 90 | serial_tx #(.CLK_PER_BIT(CLK_PER_BIT)) serial_tx ( 91 | .clk(clk), 92 | .rst(n_rdy), 93 | .tx(tx_m), 94 | .block(busy_q), 95 | .busy(tx_busy), 96 | .data(tx_data), 97 | .new_data(new_tx_data) 98 | ); 99 | 100 | // Output declarations 101 | assign new_sample = new_sample_q; 102 | assign sample = sample_q; 103 | assign sample_channel = sample_channel_q; 104 | 105 | // these signals connect to the AVR and should be Z when the AVR isn't ready 106 | assign spi_channel = ready ? channel : 4'bZZZZ; 107 | assign spi_miso = ready && !spi_ss ? spi_miso_m : 1'bZ; 108 | assign tx = ready ? tx_m : 1'bZ; 109 | 110 | always @(*) begin 111 | byte_ct_d = byte_ct_q; 112 | sample_d = sample_q; 113 | new_sample_d = 1'b0; 114 | sample_channel_d = sample_channel_q; 115 | 116 | busy_d = busy_q; 117 | block_d = {block_q[2:0], tx_block}; 118 | 119 | if (block_q[3] ^ block_q[2]) 120 | busy_d = 1'b0; 121 | 122 | if (!tx_busy && new_tx_data) 123 | busy_d = 1'b1; 124 | 125 | if (spi_ss) begin // device is not selected 126 | byte_ct_d = 1'b0; 127 | end 128 | 129 | if (spi_done) begin // sent/received data from SPI 130 | if (byte_ct_q == 1'b0) begin 131 | sample_d[7:0] = spi_dout; // first byte is the 8 LSB of the sample 132 | byte_ct_d = 1'b1; 133 | end else begin 134 | sample_d[9:8] = spi_dout[1:0]; // second byte is the channel 2 MSB of the sample 135 | sample_channel_d = spi_dout[7:4]; // and the channel that was sampled 136 | byte_ct_d = 1'b1; // slave-select must be brought high before the next transfer 137 | new_sample_d = 1'b1; 138 | end 139 | end 140 | end 141 | 142 | always @(posedge clk) begin 143 | if (n_rdy) begin 144 | byte_ct_q <= 1'b0; 145 | sample_q <= 10'b0; 146 | new_sample_q <= 1'b0; 147 | end else begin 148 | byte_ct_q <= byte_ct_d; 149 | sample_q <= sample_d; 150 | new_sample_q <= new_sample_d; 151 | end 152 | 153 | block_q <= block_d; 154 | busy_q <= busy_d; 155 | sample_channel_q <= sample_channel_d; 156 | end 157 | 158 | endmodule -------------------------------------------------------------------------------- /src/cclk_detector.v: -------------------------------------------------------------------------------- 1 | module cclk_detector #( 2 | parameter CLK_RATE = 50000000 3 | )( 4 | input clk, 5 | input rst, 6 | input cclk, 7 | output ready 8 | ); 9 | 10 | parameter CTR_SIZE = $clog2(CLK_RATE/50000); 11 | 12 | reg [CTR_SIZE-1:0] ctr_d, ctr_q; 13 | reg ready_d, ready_q; 14 | 15 | assign ready = ready_q; 16 | 17 | // ready should only go high once cclk has been high for a while 18 | // if cclk ever falls, ready should go low again 19 | always @(ctr_q or cclk) begin 20 | ready_d = 1'b0; 21 | if (cclk == 1'b0) begin // when cclk is 0 reset the counter 22 | ctr_d = 1'b0; 23 | end else if (ctr_q != {CTR_SIZE{1'b1}}) begin 24 | ctr_d = ctr_q + 1'b1; // counter isn't max value yet 25 | end else begin 26 | ctr_d = ctr_q; 27 | ready_d = 1'b1; // counter reached the max, we are ready 28 | end 29 | 30 | end 31 | 32 | always @(posedge clk) begin 33 | if (rst) begin 34 | ctr_q <= 1'b0; 35 | ready_q <= 1'b0; 36 | end else begin 37 | ctr_q <= ctr_d; 38 | ready_q <= ready_d; 39 | end 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /src/mojo.ucf: -------------------------------------------------------------------------------- 1 | #Created by Constraints Editor (xc6slx9-tqg144-3) - 2012/11/05 2 | NET "clk" TNM_NET = clk; 3 | TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%; 4 | 5 | # PlanAhead Generated physical constraints 6 | NET "clk" LOC = P56 | IOSTANDARD = LVTTL; 7 | NET "rst_n" LOC = P38 | IOSTANDARD = LVTTL; 8 | 9 | NET "cclk" LOC = P70 | IOSTANDARD = LVTTL; 10 | 11 | NET "led<0>" LOC = P134 | IOSTANDARD = LVTTL; 12 | NET "led<1>" LOC = P133 | IOSTANDARD = LVTTL; 13 | NET "led<2>" LOC = P132 | IOSTANDARD = LVTTL; 14 | NET "led<3>" LOC = P131 | IOSTANDARD = LVTTL; 15 | NET "led<4>" LOC = P127 | IOSTANDARD = LVTTL; 16 | NET "led<5>" LOC = P126 | IOSTANDARD = LVTTL; 17 | NET "led<6>" LOC = P124 | IOSTANDARD = LVTTL; 18 | NET "led<7>" LOC = P123 | IOSTANDARD = LVTTL; 19 | 20 | NET "spi_mosi" LOC = P44 | IOSTANDARD = LVTTL; 21 | NET "spi_miso" LOC = P45 | IOSTANDARD = LVTTL; 22 | NET "spi_ss" LOC = P48 | IOSTANDARD = LVTTL; 23 | NET "spi_sck" LOC = P43 | IOSTANDARD = LVTTL; 24 | NET "spi_channel<0>" LOC = P46 | IOSTANDARD = LVTTL; 25 | NET "spi_channel<1>" LOC = P61 | IOSTANDARD = LVTTL; 26 | NET "spi_channel<2>" LOC = P62 | IOSTANDARD = LVTTL; 27 | NET "spi_channel<3>" LOC = P65 | IOSTANDARD = LVTTL; 28 | 29 | NET "avr_tx" LOC = P55 | IOSTANDARD = LVTTL; 30 | NET "avr_rx" LOC = P59 | IOSTANDARD = LVTTL; 31 | NET "avr_rx_busy" LOC = P39 | IOSTANDARD = LVTTL; 32 | 33 | NET "i2c_sda" LOC = P57 | IOSTANDARD = LVTTL; 34 | NET "i2c_scl" LOC = P66 | IOSTANDARD = LVTTL; 35 | NET "i2c_clk_in" LOC = P74 | IOSTANDARD = LVTTL; 36 | 37 | -------------------------------------------------------------------------------- /src/mojo_top.v: -------------------------------------------------------------------------------- 1 | module mojo_top( 2 | // 50MHz clock input 3 | input wire clk, 4 | // Input from reset button (active low) 5 | input wire rst_n, 6 | // cclk input from AVR, high when AVR is ready 7 | input wire cclk, 8 | // Outputs to the 8 onboard LEDs 9 | output wire [7:0]led, 10 | // AVR SPI connections 11 | output wire spi_miso, 12 | input wire spi_ss, 13 | input wire spi_mosi, 14 | input wire spi_sck, 15 | // AVR ADC channel select 16 | output wire [3:0] spi_channel, 17 | // Serial connections 18 | input wire avr_tx, // AVR Tx => FPGA Rx 19 | output wire avr_rx, // AVR Rx => FPGA Tx 20 | input wire avr_rx_busy, // AVR Rx buffer full 21 | 22 | output wire i2c_scl, 23 | inout wire i2c_sda, 24 | 25 | output wire i2c_clk_in 26 | ); 27 | 28 | wire reset = ~rst_n; // make reset active high 29 | 30 | // these signals should be high-z when not used 31 | assign spi_miso = 1'bz; 32 | assign avr_rx = 1'bz; 33 | assign spi_channel = 4'bzzzz; 34 | 35 | assign led[5:0] = led_buffer; 36 | assign led[7] = tick_1s; 37 | assign led[6] = i2c_clk_in; 38 | 39 | wire tick_1s; 40 | 41 | //Generate a 1s timer 42 | //timer #(.CTR_LEN(26)) second_timer ( 43 | timer #(.CTR_LEN(16)) second_timer ( 44 | .clk(clk), 45 | .reset(reset), 46 | .tick(tick_1s) 47 | ); 48 | 49 | 50 | clk_divider #(.DIVIDER(500)) i2c_clk_divider ( 51 | .reset(reset), 52 | .clk_in(clk), 53 | .clk_out(i2c_clk_in) 54 | ); 55 | 56 | wire i2c_start; 57 | reg i2c_reset = 1'b1; 58 | wire [7:0] i2c_nbytes; 59 | wire [6:0] i2c_slave_addr; 60 | wire i2c_rw; 61 | wire [7:0] i2c_write_data; 62 | wire [7:0] i2c_read_data; 63 | wire i2c_tx_data_req; 64 | wire i2c_rx_data_ready; 65 | wire ready; 66 | wire busy; 67 | 68 | i2c_master i2c ( 69 | .clk(i2c_clk_in), 70 | .reset(i2c_reset), 71 | .start(i2c_start), 72 | .nbytes_in(i2c_nbytes), 73 | .addr_in(i2c_slave_addr), 74 | .rw_in(i2c_rw), 75 | .write_data(i2c_write_data), 76 | .read_data(i2c_read_data), 77 | .tx_data_req(i2c_tx_data_req), 78 | .rx_data_ready(i2c_rx_data_ready), 79 | .sda_w(i2c_sda), 80 | .scl(i2c_scl) 81 | ); 82 | 83 | wire [6:0] slave_addr = 7'b1010000; 84 | reg [15:0] mem_addr; 85 | wire [7:0] read_n_bytes = 8'd1; 86 | 87 | wire [7:0] read_nbytes = 1; 88 | reg start = 0; 89 | wire [7:0] data_out; 90 | wire byte_ready; 91 | wire eeprom_busy; 92 | 93 | read_eeprom instance_name ( 94 | .clk(clk), 95 | .reset(reset), 96 | .slave_addr_w(slave_addr), 97 | .mem_addr_w(mem_addr), 98 | .read_nbytes_w(read_nbytes), 99 | .start(start), 100 | .data_out(data_out), 101 | .byte_ready(byte_ready), 102 | .i2c_slave_addr(i2c_slave_addr), 103 | .i2c_rw(i2c_rw), 104 | .i2c_write_data(i2c_write_data), 105 | .i2c_nbytes(i2c_nbytes), 106 | .i2c_read_data(i2c_read_data), 107 | .i2c_tx_data_req(i2c_tx_data_req), 108 | .i2c_rx_data_ready(i2c_rx_data_ready), 109 | .i2c_start(i2c_start), 110 | .busy(eeprom_busy) 111 | ); 112 | 113 | reg [5:0] led_buffer; 114 | 115 | //every time a new byte is ready, write it to the LEDs 116 | always @(posedge byte_ready) begin 117 | led_buffer <= data_out[5:0]; 118 | end 119 | 120 | 121 | reg measured_this_pulse; 122 | 123 | always @(posedge clk) begin 124 | if (reset == 1) begin 125 | mem_addr <= 16'h0000; 126 | measured_this_pulse <= 0; 127 | 128 | end else begin 129 | 130 | if ((tick_1s == 1) && (measured_this_pulse == 0)) begin 131 | measured_this_pulse <= 1; 132 | mem_addr <= mem_addr + 1'b1; 133 | if (mem_addr > 8) begin 134 | mem_addr <= 0; 135 | end 136 | start <= 1; 137 | end //tick_1s==1 138 | 139 | if ((start == 1) && (eeprom_busy == 1)) begin 140 | start <= 0; 141 | end //eeprom_busy and start 142 | 143 | if (tick_1s == 0) begin 144 | measured_this_pulse <= 0; 145 | end //tick_1s==0 146 | 147 | end //reset 148 | end 149 | 150 | 151 | //we need to make sure the i2c module is reset *after* 152 | //it's clock has begun 153 | always @(negedge i2c_clk_in) begin 154 | 155 | if (reset == 1) begin 156 | i2c_reset <= 1; 157 | end else begin 158 | i2c_reset <= 0; 159 | end 160 | end //posedge clk_i2c_in 161 | 162 | 163 | 164 | 165 | 166 | endmodule -------------------------------------------------------------------------------- /src/serial_rx.v: -------------------------------------------------------------------------------- 1 | module serial_rx #( 2 | parameter CLK_PER_BIT = 50 3 | )( 4 | input clk, 5 | input rst, 6 | input rx, 7 | output [7:0] data, 8 | output new_data 9 | ); 10 | 11 | // clog2 is 'ceiling of log base 2' which gives you the number of bits needed to store a value 12 | parameter CTR_SIZE = $clog2(CLK_PER_BIT); 13 | 14 | localparam STATE_SIZE = 2; 15 | localparam IDLE = 2'd0, 16 | WAIT_HALF = 2'd1, 17 | WAIT_FULL = 2'd2, 18 | WAIT_HIGH = 2'd3; 19 | 20 | reg [CTR_SIZE-1:0] ctr_d, ctr_q; 21 | reg [2:0] bit_ctr_d, bit_ctr_q; 22 | reg [7:0] data_d, data_q; 23 | reg new_data_d, new_data_q; 24 | reg [STATE_SIZE-1:0] state_d, state_q = IDLE; 25 | reg rx_d, rx_q; 26 | 27 | assign new_data = new_data_q; 28 | assign data = data_q; 29 | 30 | always @(*) begin 31 | rx_d = rx; 32 | state_d = state_q; 33 | ctr_d = ctr_q; 34 | bit_ctr_d = bit_ctr_q; 35 | data_d = data_q; 36 | new_data_d = 1'b0; 37 | 38 | case (state_q) 39 | IDLE: begin 40 | bit_ctr_d = 3'b0; 41 | ctr_d = 1'b0; 42 | if (rx_q == 1'b0) begin 43 | state_d = WAIT_HALF; 44 | end 45 | end 46 | WAIT_HALF: begin 47 | ctr_d = ctr_q + 1'b1; 48 | if (ctr_q == (CLK_PER_BIT >> 1)) begin 49 | ctr_d = 1'b0; 50 | state_d = WAIT_FULL; 51 | end 52 | end 53 | WAIT_FULL: begin 54 | ctr_d = ctr_q + 1'b1; 55 | if (ctr_q == CLK_PER_BIT - 1) begin 56 | data_d = {rx_q, data_q[7:1]}; 57 | bit_ctr_d = bit_ctr_q + 1'b1; 58 | ctr_d = 1'b0; 59 | if (bit_ctr_q == 3'd7) begin 60 | state_d = WAIT_HIGH; 61 | new_data_d = 1'b1; 62 | end 63 | end 64 | end 65 | WAIT_HIGH: begin 66 | if (rx_q == 1'b1) begin 67 | state_d = IDLE; 68 | end 69 | end 70 | default: begin 71 | state_d = IDLE; 72 | end 73 | endcase 74 | 75 | end 76 | 77 | always @(posedge clk) begin 78 | if (rst) begin 79 | ctr_q <= 1'b0; 80 | bit_ctr_q <= 3'b0; 81 | new_data_q <= 1'b0; 82 | state_q <= IDLE; 83 | end else begin 84 | ctr_q <= ctr_d; 85 | bit_ctr_q <= bit_ctr_d; 86 | new_data_q <= new_data_d; 87 | state_q <= state_d; 88 | end 89 | 90 | rx_q <= rx_d; 91 | data_q <= data_d; 92 | end 93 | 94 | endmodule -------------------------------------------------------------------------------- /src/serial_tx.v: -------------------------------------------------------------------------------- 1 | module serial_tx #( 2 | parameter CLK_PER_BIT = 50 3 | )( 4 | input clk, 5 | input rst, 6 | output tx, 7 | input block, 8 | output busy, 9 | input [7:0] data, 10 | input new_data 11 | ); 12 | 13 | // clog2 is 'ceiling of log base 2' which gives you the number of bits needed to store a value 14 | parameter CTR_SIZE = $clog2(CLK_PER_BIT); 15 | 16 | localparam STATE_SIZE = 2; 17 | localparam IDLE = 2'd0, 18 | START_BIT = 2'd1, 19 | DATA = 2'd2, 20 | STOP_BIT = 2'd3; 21 | 22 | reg [CTR_SIZE-1:0] ctr_d, ctr_q; 23 | reg [2:0] bit_ctr_d, bit_ctr_q; 24 | reg [7:0] data_d, data_q; 25 | reg [STATE_SIZE-1:0] state_d, state_q = IDLE; 26 | reg tx_d, tx_q; 27 | reg busy_d, busy_q; 28 | reg block_d, block_q; 29 | 30 | assign tx = tx_q; 31 | assign busy = busy_q; 32 | 33 | always @(*) begin 34 | block_d = block; 35 | ctr_d = ctr_q; 36 | bit_ctr_d = bit_ctr_q; 37 | data_d = data_q; 38 | state_d = state_q; 39 | busy_d = busy_q; 40 | 41 | case (state_q) 42 | IDLE: begin 43 | if (block_q) begin 44 | busy_d = 1'b1; 45 | tx_d = 1'b1; 46 | end else begin 47 | busy_d = 1'b0; 48 | tx_d = 1'b1; 49 | bit_ctr_d = 3'b0; 50 | ctr_d = 1'b0; 51 | if (new_data) begin 52 | data_d = data; 53 | state_d = START_BIT; 54 | busy_d = 1'b1; 55 | end 56 | end 57 | end 58 | START_BIT: begin 59 | busy_d = 1'b1; 60 | ctr_d = ctr_q + 1'b1; 61 | tx_d = 1'b0; 62 | if (ctr_q == CLK_PER_BIT - 1) begin 63 | ctr_d = 1'b0; 64 | state_d = DATA; 65 | end 66 | end 67 | DATA: begin 68 | busy_d = 1'b1; 69 | tx_d = data_q[bit_ctr_q]; 70 | ctr_d = ctr_q + 1'b1; 71 | if (ctr_q == CLK_PER_BIT - 1) begin 72 | ctr_d = 1'b0; 73 | bit_ctr_d = bit_ctr_q + 1'b1; 74 | if (bit_ctr_q == 7) begin 75 | state_d = STOP_BIT; 76 | end 77 | end 78 | end 79 | STOP_BIT: begin 80 | busy_d = 1'b1; 81 | tx_d = 1'b1; 82 | ctr_d = ctr_q + 1'b1; 83 | if (ctr_q == CLK_PER_BIT - 1) begin 84 | state_d = IDLE; 85 | end 86 | end 87 | default: begin 88 | state_d = IDLE; 89 | end 90 | endcase 91 | end 92 | 93 | always @(posedge clk) begin 94 | if (rst) begin 95 | state_q <= IDLE; 96 | tx_q <= 1'b1; 97 | end else begin 98 | state_q <= state_d; 99 | tx_q <= tx_d; 100 | end 101 | 102 | block_q <= block_d; 103 | data_q <= data_d; 104 | bit_ctr_q <= bit_ctr_d; 105 | ctr_q <= ctr_d; 106 | busy_q <= busy_d; 107 | end 108 | 109 | endmodule -------------------------------------------------------------------------------- /src/spi_slave.v: -------------------------------------------------------------------------------- 1 | module spi_slave( 2 | input clk, 3 | input rst, 4 | input ss, 5 | input mosi, 6 | output miso, 7 | input sck, 8 | output done, 9 | input [7:0] din, 10 | output [7:0] dout 11 | ); 12 | 13 | reg mosi_d, mosi_q; 14 | reg ss_d, ss_q; 15 | reg sck_d, sck_q; 16 | reg sck_old_d, sck_old_q; 17 | reg [7:0] data_d, data_q; 18 | reg done_d, done_q; 19 | reg [2:0] bit_ct_d, bit_ct_q; 20 | reg [7:0] dout_d, dout_q; 21 | reg miso_d, miso_q; 22 | 23 | assign miso = miso_q; 24 | assign done = done_q; 25 | assign dout = dout_q; 26 | 27 | always @(*) begin 28 | ss_d = ss; 29 | mosi_d = mosi; 30 | miso_d = miso_q; 31 | sck_d = sck; 32 | sck_old_d = sck_q; 33 | data_d = data_q; 34 | done_d = 1'b0; 35 | bit_ct_d = bit_ct_q; 36 | dout_d = dout_q; 37 | 38 | if (ss_q) begin 39 | bit_ct_d = 3'b0; 40 | data_d = din; 41 | miso_d = data_q[7]; 42 | end else begin 43 | if (!sck_old_q && sck_q) begin // rising edge 44 | data_d = {data_q[6:0], mosi_q}; 45 | bit_ct_d = bit_ct_q + 1'b1; 46 | if (bit_ct_q == 3'b111) begin 47 | dout_d = {data_q[6:0], mosi_q}; 48 | done_d = 1'b1; 49 | data_d = din; 50 | end 51 | end else if (sck_old_q && !sck_q) begin // falling edge 52 | miso_d = data_q[7]; 53 | end 54 | end 55 | end 56 | 57 | always @(posedge clk) begin 58 | if (rst) begin 59 | done_q <= 1'b0; 60 | bit_ct_q <= 3'b0; 61 | dout_q <= 8'b0; 62 | miso_q <= 1'b1; 63 | end else begin 64 | done_q <= done_d; 65 | bit_ct_q <= bit_ct_d; 66 | dout_q <= dout_d; 67 | miso_q <= miso_d; 68 | end 69 | 70 | sck_q <= sck_d; 71 | mosi_q <= mosi_d; 72 | ss_q <= ss_d; 73 | data_q <= data_d; 74 | sck_old_q <= sck_old_d; 75 | 76 | end 77 | 78 | 79 | endmodule 80 | -------------------------------------------------------------------------------- /syn/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /testbench.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns / 1ps 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 00:28:21 02/28/2016 8 | // Design Name: i2c_master_v4 9 | // Module Name: C:/Users/matt/Documents/mojo/i2c_master/test_i2c_master_v4.v 10 | // Project Name: i2c_master 11 | // Target Device: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Verilog Test Fixture created by ISE for module: i2c_master_v4 16 | // 17 | // Dependencies: 18 | // 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | //////////////////////////////////////////////////////////////////////////////// 24 | 25 | module testbench; 26 | 27 | // Inputs 28 | reg clk; 29 | reg reset; 30 | reg i2c_reset; 31 | reg [15:0] mem_addr; 32 | reg [6:0] slave_addr; 33 | reg [7:0] read_nbytes; 34 | reg data_ready; 35 | 36 | reg start; 37 | 38 | 39 | // Outputs 40 | wire scl; 41 | wire [7:0] data_out; 42 | 43 | 44 | // Bidirs 45 | wire sda_w; 46 | 47 | 48 | wire i2c_clk; 49 | wire [7:0] i2c_nbytes; 50 | wire [6:0] i2c_slave_addr; 51 | wire i2c_rw; 52 | wire [7:0] i2c_write_data; 53 | wire [7:0] i2c_read_data; 54 | wire i2c_tx_data_req; 55 | wire i2c_rx_data_ready; 56 | wire i2c_start; 57 | 58 | wire byte_ready; 59 | 60 | 61 | 62 | // Instantiate the Unit Under Test (UUT) 63 | i2c_master uut2 ( 64 | .clk(i2c_clk), 65 | .reset(i2c_reset), 66 | .start(i2c_start), 67 | .nbytes_in(i2c_nbytes), 68 | .addr_in(i2c_slave_addr), 69 | .rw_in(i2c_rw), 70 | .write_data(i2c_write_data), 71 | .read_data(i2c_read_data), 72 | .tx_data_req(i2c_tx_data_req), 73 | .rx_data_ready(i2c_rx_data_ready), 74 | .sda_w(sda_w), 75 | .scl(scl) 76 | ); 77 | 78 | 79 | clk_divider #(.DIVIDER(500)) i2c_clk_divider ( 80 | .reset(reset), 81 | .clk_in(clk), 82 | .clk_out(i2c_clk) 83 | ); 84 | 85 | read_eeprom uut ( 86 | .clk(clk), 87 | .reset(reset), 88 | .slave_addr_w(slave_addr), 89 | .mem_addr_w(mem_addr), 90 | .read_nbytes_w(read_nbytes), 91 | .start(start), 92 | .i2c_slave_addr(i2c_slave_addr), 93 | .i2c_rw(i2c_rw), 94 | .i2c_write_data(i2c_write_data), 95 | .i2c_nbytes(i2c_nbytes), 96 | .i2c_read_data(i2c_read_data), 97 | .i2c_tx_data_req(i2c_tx_data_req), 98 | .i2c_rx_data_ready(i2c_rx_data_ready), 99 | .i2c_start(i2c_start), 100 | .data_out(data_out), 101 | .byte_ready(byte_ready) 102 | ); 103 | 104 | 105 | initial begin 106 | // Initialize Inputs 107 | clk = 0; 108 | forever begin 109 | clk = #1 ~clk; 110 | end 111 | end 112 | 113 | initial begin 114 | // Initialize Inputs 115 | reset = 1; 116 | i2c_reset = 1; 117 | 118 | // Wait 100 ns for global reset to finish 119 | #5000; 120 | //start up the clocks 121 | reset = 0; 122 | #5000; 123 | 124 | // Add stimulus here 125 | i2c_reset = 0; 126 | slave_addr = 8'haa; 127 | mem_addr = 16'hF0F0; 128 | read_nbytes = 2; 129 | 130 | #10000; 131 | 132 | //set the start bit 133 | start = 1; 134 | 135 | 136 | #10000 137 | start = 0; 138 | #100000; 139 | 140 | 141 | $finish; 142 | 143 | end 144 | 145 | endmodule 146 | 147 | -------------------------------------------------------------------------------- /testbench_mojo_top.v: -------------------------------------------------------------------------------- 1 | `timescale 10ns / 1ps 2 | 3 | //////////////////////////////////////////////////////////////////////////////// 4 | // Company: 5 | // Engineer: 6 | // 7 | // Create Date: 19:54:18 03/09/2016 8 | // Design Name: mojo_top 9 | // Module Name: C:/Users/matt/Documents/projects/mojo/i2c-eeprom/testbench_mojo_top.v 10 | // Project Name: Mojo-Base 11 | // Target Device: 12 | // Tool versions: 13 | // Description: 14 | // 15 | // Verilog Test Fixture created by ISE for module: mojo_top 16 | // 17 | // Dependencies: 18 | // 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | //////////////////////////////////////////////////////////////////////////////// 24 | 25 | module testbench_mojo_top; 26 | 27 | // Inputs 28 | reg clk; 29 | reg rst_n; 30 | reg cclk; 31 | reg spi_ss; 32 | reg spi_mosi; 33 | reg spi_sck; 34 | reg avr_tx; 35 | reg avr_rx_busy; 36 | 37 | // Outputs 38 | wire [7:0] led; 39 | wire spi_miso; 40 | wire [3:0] spi_channel; 41 | wire avr_rx; 42 | wire i2c_scl; 43 | wire i2c_clk_in; 44 | 45 | // Bidirs 46 | wire i2c_sda; 47 | 48 | // Instantiate the Unit Under Test (UUT) 49 | mojo_top uut ( 50 | .clk(clk), 51 | .rst_n(rst_n), 52 | .cclk(cclk), 53 | .led(led), 54 | .spi_miso(spi_miso), 55 | .spi_ss(spi_ss), 56 | .spi_mosi(spi_mosi), 57 | .spi_sck(spi_sck), 58 | .spi_channel(spi_channel), 59 | .avr_tx(avr_tx), 60 | .avr_rx(avr_rx), 61 | .avr_rx_busy(avr_rx_busy), 62 | .i2c_scl(i2c_scl), 63 | .i2c_sda(i2c_sda), 64 | .i2c_clk_in(i2c_clk_in) 65 | ); 66 | 67 | 68 | wire A0 = 0; 69 | wire A1 = 0; 70 | wire A2 = 0; 71 | wire WP = 0; 72 | wire reset = ~rst_n; 73 | 74 | M24FC512 eeprom ( 75 | .A0(A0), 76 | .A1(A1), 77 | .A2(A2), 78 | .WP(WP), 79 | .SDA(i2c_sda), 80 | .SCL(i2c_scl), 81 | .RESET(reset) 82 | ); 83 | 84 | initial begin 85 | // Initialize Inputs 86 | clk = 0; 87 | forever begin 88 | clk = #1 ~clk; 89 | end 90 | end 91 | 92 | initial begin 93 | // Initialize Inputs 94 | rst_n = 0; 95 | cclk = 0; 96 | spi_ss = 0; 97 | spi_mosi = 0; 98 | spi_sck = 0; 99 | avr_tx = 0; 100 | avr_rx_busy = 0; 101 | 102 | // Wait 100 ns for global reset to finish 103 | #100; 104 | 105 | // Add stimulus here 106 | cclk = 1; 107 | rst_n = 1; 108 | 109 | end 110 | 111 | endmodule 112 | 113 | -------------------------------------------------------------------------------- /timer.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 19:14:34 03/04/2016 7 | // Design Name: 8 | // Module Name: timer 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module timer #(parameter CTR_LEN = 26) ( 22 | input clk, 23 | input reset, 24 | output tick 25 | ); 26 | 27 | reg [CTR_LEN-1:0] counter_d, counter_q; 28 | 29 | assign tick = counter_q[CTR_LEN-1]; 30 | 31 | always @(counter_q) begin 32 | counter_d = counter_q + 1'b1; 33 | end 34 | 35 | always @(posedge clk) begin 36 | if (reset) begin 37 | counter_q <= 25'b0; 38 | end else begin 39 | counter_q <= counter_d; 40 | end 41 | end 42 | endmodule 43 | 44 | --------------------------------------------------------------------------------