| `default_nettype none | |
| // Simple I/O expander | |
| // | |
| // Input pinout: | |
| // 0 clk logic clock | |
| // 1 reset logic reset (positive) | |
| // 2 sclk spi clock | |
| // 3 CE spi chip enable (negative) | |
| // 4 sin spi in (into this device) | |
| // 5 IN0 input 0 | |
| // 6 IN1 input 1 | |
| // 7 IN2 input 2 | |
| // | |
| // Output pinout: | |
| // 0 OUT0 | |
| // 1 OUT1 | |
| // 2 OUT2 | |
| // 3 OUT3 | |
| // 4 OUT4 | |
| // 5 OUT5 | |
| // 6 OUT6 | |
| // 7 sout spi out (out of this device) | |
| // Top level io for this module should stay the same to fit into the scan_wrapper. | |
| // The pin connections within the user_module are up to you, | |
| // although (if one is present) it is recommended to place a clock on io_in[0]. | |
| // This allows use of the internal clock divider if you wish. | |
| module user_module_341432284947153491( | |
| input [7:0] io_in, | |
| output [7:0] io_out | |
| ); | |
| wire clk, reset, sclk, ce, sin, in0, in1, in2; | |
| assign clk = io_in[0]; | |
| assign reset = io_in[1]; | |
| assign sclk = io_in[2]; | |
| assign ce = io_in[3]; | |
| assign sin = io_in[4]; | |
| assign in0 = io_in[5]; | |
| assign in1 = io_in[6]; | |
| assign in2 = io_in[7]; | |
| wire [6:0] out; | |
| wire sout; | |
| assign io_out = { sout, out }; | |
| wire [2:0] ioexp_in; | |
| assign ioexp_in = { io_in[7], io_in[6], io_in[5] }; | |
| spi_341432284947153491 #(.INBITS(3), .OUTBITS(7)) spi_core ( | |
| .reset(reset), | |
| .clk(clk), | |
| .sclk(sclk), | |
| .ce(ce), | |
| .sin(sin), | |
| .sout(sout), | |
| .inputs(ioexp_in), | |
| .outputs(out) | |
| ); | |
| // The SPI module latches in the inputs on neg CE and latches out the | |
| // outputs on pos CE | |
| endmodule | |
| // SPI in, shift in new output while shifting out old outputs | |
| module spi_341432284947153491 #( | |
| parameter INBITS = 4, | |
| parameter OUTBITS = 4 | |
| ) ( | |
| input reset, // synchronous internal reset | |
| input clk, // system clock | |
| input sclk, // negative polarity | |
| input ce, // active low | |
| input sin, | |
| output sout, | |
| input [INBITS-1:0] inputs, | |
| output [OUTBITS-1:0] outputs | |
| ); | |
| // Note: We shift IN the IO OUTPUTS. We shift OUT the IO INPUTS. | |
| reg [OUTBITS-1:0] inlatch; // serial input latch (latch on CE rising edge) | |
| reg [OUTBITS-1:0] inbuf; // serial input buffer (latch on CE rising edge) | |
| reg [INBITS-1:0] outlatch; // serial output latch (latch on CE falling edge) | |
| assign sout = outlatch[0]; | |
| assign outputs = inlatch; | |
| wire ce_posedge, ce_negedge; | |
| posedge_341432284947153491 pe_ce(.clk(clk), .in(ce), .pedge(ce_posedge)); | |
| negedge_341432284947153491 ne_ce(.clk(clk), .in(ce), .nedge(ce_negedge)); | |
| wire sclk_posedge, sclk_negedge; | |
| posedge_341432284947153491 pe_sclk(.clk(clk), .in(sclk), .pedge(sclk_posedge)); | |
| negedge_341432284947153491 ne_sclk(.clk(clk), .in(sclk), .nedge(sclk_negedge)); | |
| always @(posedge clk) begin | |
| if (reset) begin | |
| inbuf <= 0; | |
| inlatch <= 0; | |
| outlatch <= 0; | |
| end else if (ce_posedge) begin | |
| inlatch <= inbuf; | |
| end else if (ce_negedge) begin | |
| outlatch <= inputs; | |
| //end else if (ce) begin | |
| //inbuf <= 0; | |
| //outlatch <= 0; | |
| end else begin | |
| if (sclk_posedge) begin | |
| outlatch <= { 1'b0, outlatch[INBITS-1:1] }; | |
| end else if (sclk_negedge) begin | |
| inbuf <= { inbuf[OUTBITS-2:0], sin }; | |
| end | |
| end | |
| end | |
| endmodule | |
| module posedge_341432284947153491(input clk, input in, output pedge); | |
| reg last, now; | |
| assign pedge = !last && now; | |
| always @(posedge clk) begin | |
| {last, now} = {now, in}; | |
| end | |
| endmodule | |
| module negedge_341432284947153491(input clk, input in, output nedge); | |
| reg last, now; | |
| assign nedge = last && !now; | |
| always @(posedge clk) begin | |
| {last, now} = {now, in}; | |
| end | |
| endmodule | |