spi_debug_ifc.v (2892B)
1 // Copyright 2015, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 `default_nettype none 5 6 `timescale 1ns / 1ps 7 8 module spi_debug_ifc( 9 input spi_clk, 10 input spi_cs_i, 11 input spi_data_i, 12 output spi_data_o, 13 input sys_clk, 14 output sys_wr_o, 15 output [15:0]sys_waddr_o, 16 output [15:0]sys_wdata_o 17 ); 18 19 reg [15:0]spi_shift = 16'd0; 20 reg [16:0]spi_data = 17'd0; 21 reg [3:0]spi_count = 4'd0; 22 reg spi_signal = 1'd0; 23 reg spi_flag = 1'd0; 24 25 assign spi_data_o = 1'b0; 26 27 wire [15:0]spi_next = { spi_data_i, spi_shift[15:1] }; 28 29 reg [15:0]spi_shift_next; 30 reg [16:0]spi_data_next; 31 reg [3:0]spi_count_next; 32 reg spi_signal_next; 33 reg spi_flag_next; 34 35 always @(*) begin 36 spi_shift_next = spi_shift; 37 spi_data_next = spi_data; 38 spi_count_next = spi_count; 39 spi_signal_next = spi_signal; 40 spi_flag_next = spi_flag; 41 42 if (spi_cs_i) begin 43 spi_count_next = 4'd0; 44 spi_flag_next = 1'b1; 45 end else begin 46 spi_shift_next = spi_next; 47 spi_count_next = spi_count + 4'd1; 48 if (spi_count == 4'd15) begin 49 spi_data_next = { spi_flag, spi_next }; 50 spi_signal_next = ~spi_signal; 51 spi_flag_next = 1'b0; 52 end 53 end 54 end 55 56 always @(posedge spi_clk) begin 57 spi_shift <= spi_shift_next; 58 spi_data <= spi_data_next; 59 spi_count <= spi_count_next; 60 spi_signal <= spi_signal_next; 61 spi_flag <= spi_flag_next; 62 end 63 64 wire sys_signal; 65 66 sync_oneway sync_spi_sys( 67 .txclk(spi_clk), 68 .txdat(spi_signal), 69 .rxclk(sys_clk), 70 .rxdat(sys_signal) 71 ); 72 73 reg sys_signal_ack = 1'b0; 74 reg enabled = 1'b0; 75 reg [15:0]addr; 76 reg [15:0]data; 77 reg wr = 1'b0; 78 79 reg [15:0]addr_next; 80 reg [15:0]data_next; 81 reg enabled_next; 82 reg sys_signal_ack_next; 83 reg wr_next; 84 85 reg [15:0]delay = 16'd0; 86 reg [15:0]delay_next; 87 88 always @(*) begin 89 delay_next = delay; 90 addr_next = addr; 91 data_next = data; 92 sys_signal_ack_next = sys_signal_ack; 93 wr_next = wr; 94 95 // ensure we're up and running before accepting writes 96 // there's got to be a nicer way to do this 97 if (delay != 16'hFFFF) begin 98 delay_next = delay + 1'd1; 99 enabled_next = 1'b0; 100 end else begin 101 enabled_next = 1'b1; 102 end 103 104 if (sys_signal ^ sys_signal_ack) begin 105 sys_signal_ack_next = ~sys_signal_ack; 106 if (spi_data[16]) begin 107 addr_next = spi_data[15:0]; 108 end else begin 109 data_next = spi_data[15:0]; 110 wr_next = 1'b1; 111 end 112 end else begin 113 if (wr) begin 114 wr_next = 1'b0; 115 addr_next = addr + 16'd1; 116 end 117 end 118 end 119 120 always @(posedge sys_clk) begin 121 delay <= delay_next; 122 addr <= addr_next; 123 data <= data_next; 124 enabled <= enabled_next; 125 sys_signal_ack <= sys_signal_ack_next; 126 wr <= wr_next; 127 end 128 129 assign sys_wr_o = wr & enabled; 130 assign sys_waddr_o = addr; 131 assign sys_wdata_o = data; 132 133 endmodule 134 135 136 137 module sync_oneway( 138 input txclk, 139 input txdat, 140 input rxclk, 141 output rxdat 142 ); 143 144 reg a = 0; 145 146 // these should be adjacent 147 reg b = 0, c = 0; 148 149 always @(posedge txclk) 150 a <= txdat; 151 152 always @(posedge rxclk) begin 153 b <= a; 154 c <= b; 155 end 156 157 assign rxdat = c; 158 159 endmodule