mirror of
https://github.com/UzixLS/TSConf_MiST.git
synced 2025-07-18 23:01:37 +03:00
89 lines
2.8 KiB
Verilog
89 lines
2.8 KiB
Verilog
// part of NeoGS project (c) 2007-2008 NedoPC
|
|
//
|
|
|
|
// SPI mode 0 8-bit master module
|
|
//
|
|
// short diagram for speed=0 (Fclk/Fspi=2, no rdy shown)
|
|
//
|
|
// clk: ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ (positive edges)
|
|
// counter: 00|00|00|10|11|12|13|14|15|16|17|18|19|1A|1B|1C|1D|1E|1F|00|00|00 // internal!
|
|
// sck: ___________/``\__/``\__/``\__/``\__/``\__/``\__/``\__/``\_______
|
|
// sdo: --------< do7 | do6 | do5 | do4 | do3 | do2 | do1 | do0 >-------
|
|
// sdi: --------< di7 | di6 | di5 | di4 | di3 | di2 | di1 | di0 >-------
|
|
// bsync: ________/`````\_________________________________________________
|
|
// start: _____/``\_______________________________________________________
|
|
// din: -----<IN>-------------------------------------------------------
|
|
// dout: old old old old old old old old old old old old old | new new new
|
|
//
|
|
// data on sdo must be latched by slave on rising sck edge. data on sdo changes on falling edge of sck
|
|
//
|
|
// data from sdi is latched by master on positive edge of sck, while slave changes it on falling edge.
|
|
// WARNING: slave must emit valid di7 bit BEFORE first pulse on sck!
|
|
//
|
|
// start is synchronous pulse, which starts all transfer and also latches din data on the same clk edge
|
|
// as it is registered high. start can be given anytime (only when speed=0),
|
|
// so it is functioning then as synchronous reset. when speed!=0, there is global enable for majority of
|
|
// flipflops in the module, so start can't be accepted at any time
|
|
//
|
|
// dout updates with freshly received data at the clk edge in which sck goes high for the last time, thus
|
|
// latching last bit on sdi.
|
|
//
|
|
// sdo emits last bit shifted out after the transfer end
|
|
|
|
module spi
|
|
(
|
|
// SPI wires
|
|
input clk, // system clock
|
|
output sck, // SCK
|
|
output reg sdo, // MOSI
|
|
input sdi, // MISO
|
|
|
|
// DMA interface
|
|
input dma_req,
|
|
input [7:0] dma_din,
|
|
|
|
// Z80 interface
|
|
input cpu_req,
|
|
input [7:0] cpu_din,
|
|
|
|
// output
|
|
output start, // start strobe, 1 clock length
|
|
output reg [7:0] dout
|
|
);
|
|
|
|
assign sck = counter[0];
|
|
assign start = req && rdy;
|
|
|
|
wire [7:0] din = dma_req ? dma_din : cpu_din;
|
|
wire rdy = counter[4]; // 0 - transmission in progress
|
|
wire req = cpu_req || dma_req;
|
|
|
|
reg [4:0] counter;
|
|
always @(posedge clk) begin
|
|
reg [7:0] shift;
|
|
|
|
if (start) begin
|
|
counter <= 5'b0;
|
|
sdo <= din[7];
|
|
shift[7:1] <= din[6:0];
|
|
end
|
|
else if (!rdy) begin
|
|
counter <= counter + 5'd1;
|
|
|
|
// shift in (rising edge of SCK)
|
|
if (!sck) begin
|
|
shift[0] <= sdi;
|
|
|
|
if (&counter[3:1]) dout <= {shift[7:1], sdi};
|
|
end
|
|
|
|
// shift out (falling edge of sck)
|
|
if (sck) begin
|
|
sdo <= shift[7];
|
|
shift[7:1] <= shift[6:0]; // last bit remains after end of exchange
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|