module spi_master(sysclk,key,reset,mosi,miso,sclk,ss,led);
input sysclk;
input reset;
input miso;
input [1:0] key;
output mosi;
output ss;
output sclk;
output [1:0] led; // led?????????
reg mosi;
reg sclk;
reg ss;
reg en; // ????
reg [7:0] shifter; // ?????
reg [1:0] cnt; // ?????
reg [5:0] cnt1;
reg [12:0] cnt2;
reg [6:0] cnt3;
reg [7:0] data; // ??????
reg [3:0] count;
reg [4:0] addr;
reg [1:0] key_buf1; // ???????
reg [1:0] key_buf2;
reg [1:0] key_on_r;
reg [1:0] key_on_rr;
wire [1:0] key_on; // ???????????????????
wire clk5khz;
wire sclk2; // ???sclk?????
always @(posedge sysclk or negedge reset)
if(~reset)
cnt2 <= 13'd0;
else if(cnt2== 13'd6400)
cnt2 <= 13'd0;
else
cnt2 <= cnt2 + 13'd1;
assign clk5khz = (cnt2 == 13'd6400); // ????
always @(posedge sysclk or negedge reset)
if(~reset)
begin
key_buf1 <= 2'b11;
key_buf2 <= 2'b11;
end
else if(clk5khz)
begin
key_buf1 <= key;
key_buf2 <= key_buf1;
end
// ?????????????????????
wire [1:0] nege_edge=key_buf2 & (~key_buf1);
// ???????????????????20ms?????????
always @(posedge sysclk or negedge reset)
if(~reset)
cnt3 <= 7'b0;
else if(clk5khz)
begin
if(nege_edge)
cnt3 <= 7'b0;
else if(cnt3!=7'd100)
cnt3 <= cnt3 + 7'd1;
end
always @(posedge sysclk or negedge reset)
if(~reset)
begin
key_on_r <= 2'b11;
key_on_rr <= 2'b11;
end
else if(clk5khz&& cnt3==7'd100)
begin
key_on_r <= key;
key_on_rr <= key_on_r;
end
// ????????????
assign key_on = (~key_on_r & key_on_rr);
// ?????????????
always @(posedge sysclk or negedge reset)
if(~reset)
en <= 1'b0;
else if(clk5khz && key_on[1])
en <= ~en;
always @(posedge sysclk or negedge reset)
if(~reset)
ss <= 1'b1;
else if(clk5khz && key_on[0])
ss <= ~ss;
assign led[1] = ~en;
assign led[0] = ss;
// ?????sclk??
always @ (posedge sysclk or negedge reset)
if(~reset)
cnt <= 2'b0;
else if(cnt == 2'd3)
cnt <= 2'b0;
else
cnt <= cnt + 2'd1;
assign sclk2=(cnt==2'd3);
// sclk??????
always @(posedge sysclk or negedge reset)
if(~reset)
cnt1 <= 6'b0;
else if(en)
cnt1 <= cnt1 +6'd1;
wire clk1 = (cnt1 == 6'b111111);
// ?????????
always @(posedge clk1 or negedge reset)
if(~reset)
addr <= 5'd0;
else if(en)
addr <= addr + 5'd1;
always @(posedge sclk2 or negedge reset)
if(~reset)
count <= 5'd0;
else if(en)
count <= count + 5'd1;
always @(posedge sclk2 or negedge reset)
if(~reset)
sclk <= 1'b1;
else
sclk <= ~ sclk;
always @(posedge sclk2 or negedge reset)
if (~reset)
begin
shifter <= 8'b0;
mosi <= 1'bz;
end
else if(en)
case(count)
4'd1: shifter <= {shifter[6:0],miso};
4'd3: shifter <= {shifter[6:0],miso};
4'd5: shifter <= {shifter[6:0],miso};
4'd7: shifter <= {shifter[6:0],miso};
4'd9: shifter <= {shifter[6:0],miso};
4'd11: shifter <= {shifter[6:0],miso};
4'd13: shifter <= {shifter[6:0],miso};
4'd15: begin
shifter <= {shifter[6:0],miso};
shifter <= data; // ????
end
default:mosi <= shifter[7]; // ???????
endcase
else
mosi <= 1'bz;
always @(addr)
case(addr) // ??????
5'd0: data = 8'b0000_1111;
5'd1: data = 8'b0000_1111;
5'd2: data = 8'b0000_1111;
5'd3: data = 8'b0000_1111;
5'd4: data = 8'b0000_1111;
5'd5: data = 8'b0000_1111;
5'd6: data = 8'b0000_1111;
5'd7: data = 8'b0000_1111;
5'd8: data = 8'b0000_1111;
5'd9: data = 8'b0000_1111;
5'd10:data = 8'b0000_1111;
5'd11:data = 8'b0000_1111;
5'd12:data = 8'b0000_1111;
5'd13:data = 8'b0000_1111;
5'd14:data = 8'b0000_1111;
5'd15:data = 8'b0000_1111;
5'd16:data = 8'b0000_1111;
5'd17:data = 8'b0000_1111;
5'd18:data = 8'b0000_1111;
5'd19:data = 8'b0000_1111;
5'd20:data = 8'b0000_1111;
5'd21:data = 8'b0000_1111;
5'd22:data = 8'b0000_1111;
5'd23:data = 8'b0000_1111;
5'd24:data = 8'b0000_1111;
5'd25:data = 8'b0000_1111;
5'd26:data = 8'b0000_1111;
5'd27:data = 8'b0000_1111;
5'd28:data = 8'b0000_1111;
5'd29:data = 8'b0000_1111;
5'd30:data = 8'b0000_1111;
5'd31:data = 8'b0000_1111;
default:data = 8'b0000_1111;
endcase
endmodule
测试代码:
`timescale 1ns/1ns
module spi_test ;
reg sysclk;
reg reset;
reg [1:0] key;
reg miso;
wire mosi;
wire sclk;
wire ss;
wire [1:0] led;
spi_master spi(.sysclk(sysclk),
.key(key),
.reset(reset),
.mosi(mosi),
.miso(miso),
.sclk(sclk),
.ss(ss),
.led(led)
);
initial
begin
#0 sysclk = 1'b0;
#0 reset = 1'b0;
#10 reset = 1'b1;
end
initial
begin
#0 key = 2'b11;
#200 key = 2'b10;
#7000_000 key = 2'b11;
#8000_000 key = 2'b01;
#15000000 key = 2'b11;
end
always #5 sysclk = ~sysclk;
reg [2:0] cnt5;
always @(posedge sclk or negedge reset)
if(~reset)
cnt5 <= 3'b0;
else
cnt5 <= cnt5 + 3'd1;
always @(*)
case(cnt5)
3'd0: miso = 1'b0;
3'd1: miso = 1'b1;
3'd2: miso = 1'b0;
3'd3: miso = 1'b1;
3'd4: miso = 1'b0;
3'd5: miso = 1'b1;
3'd6: miso = 1'b0;
3'd7: miso = 1'b1;
default:miso=1'b0;
endcase
endmodule
网上来的,还有一个slave参考代码(有可能是上面master对应实验时用的slave???)如下:
//use SPI 3 mode,CHOL = 1,CHAL = 1
module spi(input clk,
input rst_n,
input CS_N,
input SCK,
input MOSI,
input [7:0] txd_data,
output reg MISO,
output reg [7:0] rxd_data,
output rxd_flag);
//-------------------------capture the sck-----------------------------
reg sck_r0,sck_r1;
wire sck_n,sck_p;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
sck_r0 <= 1'b1; //sck of the idle state is high
sck_r1 <= 1'b1;
end
else
begin
sck_r0 <= SCK;
sck_r1 <= sck_r0;
end
end
assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0; //capture the sck negedge
assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0; //capture the sck posedge
//-----------------------spi_slaver read data-------------------------------
reg rxd_flag_r;
reg [2:0] rxd_state;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rxd_data <= 1'b0;
rxd_flag_r <= 1'b0;
rxd_state <= 1'b0;
end
else if(sck_p && !CS_N)
begin
case(rxd_state)
3'd0:begin
rxd_data[7] <= MOSI;
rxd_flag_r <= 1'b0; //reset rxd_flag
rxd_state <= 3'd1;
end
3'd1:begin
rxd_data[6] <= MOSI;
rxd_state <= 3'd2;
end
3'd2:begin
rxd_data[5] <= MOSI;
rxd_state <= 3'd3;
end
3'd3:begin
rxd_data[4] <= MOSI;
rxd_state <= 3'd4;
end
3'd4:begin
rxd_data[3] <= MOSI;
rxd_state <= 3'd5;
end
3'd5:begin
rxd_data[2] <= MOSI;
rxd_state <= 3'd6;
end
3'd6:begin
rxd_data[1] <= MOSI;
rxd_state <= 3'd7;
end
3'd7:begin
rxd_data[0] <= MOSI;
rxd_flag_r <= 1'b1; //set rxd_flag
rxd_state <= 3'd0;
end
default: ;
endcase
end
end
//--------------------capture spi_flag posedge--------------------------------
reg rxd_flag_r0,rxd_flag_r1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rxd_flag_r0 <= 1'b0;
rxd_flag_r1 <= 1'b0;
end
else
begin
rxd_flag_r0 <= rxd_flag_r;
rxd_flag_r1 <= rxd_flag_r0;
end
end
assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0;
//---------------------spi_slaver send data---------------------------
reg [2:0] txd_state;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
txd_state <= 1'b0;
end
else if(sck_n && !CS_N)
begin
case(txd_state)
3'd0:begin
MISO <= txd_data[7];
txd_state <= 3'd1;
end
3'd1:begin
MISO <= txd_data[6];
txd_state <= 3'd2;
end
3'd2:begin
MISO <= txd_data[5];
txd_state <= 3'd3;
end
3'd3:begin
MISO <= txd_data[4];
txd_state <= 3'd4;
end
3'd4:begin
MISO <= txd_data[3];
txd_state <= 3'd5;
end
3'd5:begin
MISO <= txd_data[2];
txd_state <= 3'd6;
end
3'd6:begin
MISO <= txd_data[1];
txd_state <= 3'd7;
end
3'd7:begin
MISO <= txd_data[0];
txd_state <= 3'd0;
end
default: ;
endcase
end
end
endmodule
来源:oschina
链接:https://my.oschina.net/u/2963604/blog/4321414