Модуль SPI для чтения SPI чипов типа 25f512 и подобных.
регистр команд 177400:
177400[15] выбор чипа CS
177400[7] 1 идет передача
регистр данных 177402:
по записи - передаваемое слово
по чтению - принятое слово
передача запускается обращением по записи к рег данных

пример программы:
Код:
1 .asect
2 001000 .=1000
3 001000 012700 000100 mov #10,r0 ; число слов 8+2
4 001004 012701 001400 mov #1400,r1 ; команда 03h
5 001010 012702 010000 mov #7774,r2 ; загрузка с 10000 адреса
6 001014 052737 100000 177400 bis #100000,@#177400 ; выбор чипа
7
8 001022 000240 st: nop
9 001024 010137 177402 mov r1, @#177402 ; передаем команду
10 001030 032737 000200 177400 $1: bit #200,@#177400 ;
11 001036 001374 bne $1 ; ждем конца передачи
12 001040 013712 177402 mov @#177402,(r2) ; сохраняем в рам
13 001044 000322 swab (r2)+ ; ?
14 001046 005001 clr r1 ; теперь здесь адрес
15 001050 077014 sob r0, st ; повторяем
16 001052 042737 100000 177400 bic #100000,@#177400 ; снимаем выбор чипа
17 001060 000000 halt
Код:
module r177400
(
input sys_init,
input wb_clk_i,
input [15:0] wb_adr_i,
input [15:0] wb_dat_i,
output [15:0] wb_dat_o,
input wb_cyc_i,
input wb_we_i,
input [1:0] wb_sel_i,
input wb_stb_i,
output wb_ack_o,
output [15:0] test0,
output [15:0] test2,
//-----------------------------------
output reg spi_clk_m,
output reg spi_dout_m,
output spi_cs_m,
input spi_din_m,
output k
);
reg start;
wire [1:0] ena;
reg [1:0]ack;
reg [3:0] bit_cnt;
reg [15:0] vm_reg0, vm_reg2, vm_reg4, vm_reg6;
reg [2:0] state;
reg [15:0] rx;
assign spi_cs_m = ~vm_reg0[15];
assign k = ~vm_reg0[7];
assign test0 = vm_reg0[15:0];
assign test2 = vm_reg2[15:0];
assign wb_dat_o = (((wb_adr_i[2:1])==2'b00)? vm_reg0 :16'h0000)
// |(((wb_adr_i[2:1])==2'b01)? vm_reg2 :16'h0000) //vm_reg2
|(((wb_adr_i[2:1])==2'b01)? rx :16'h0000)
|(((wb_adr_i[2:1])==2'b10)? vm_reg4 :16'h0000)
|(((wb_adr_i[2:1])==2'b11)? vm_reg6 :16'h0000);
//----------------------------------------------------------------------
parameter S0 = 0, S1 = 1, S2 = 2, S3 = 3;
reg [3:0] dl;
always @ (posedge wb_clk_i ) begin
dl <= dl+1'b1;
if (sys_init)
begin
vm_reg2 <= 16'o000000;
vm_reg0 <= 16'o000000;
vm_reg0[7]<=1'b0;
state <= S0;
end
if (wb_stb_i & wb_we_i & (wb_adr_i[2:1])==2'b00) vm_reg0[15] <= wb_dat_i[15];
if (wb_stb_i & wb_we_i & (wb_adr_i[2:1])==2'b01) begin vm_reg0[7] <= 1'b1; start <= 1'b1;
if (wb_stb_i & wb_we_i & (wb_adr_i[2:1])==2'b01) vm_reg2 <= wb_dat_i; end
if (dl==4'h0) begin
case (state)
S0: begin if (start==1'b1) begin state <= S1; bit_cnt <= 4'b1111;end else state <= S0; end
S1: begin state <= S2; bit_cnt <= bit_cnt - 1'b1; spi_clk_m <= 1'b1; end
S2: begin if (bit_cnt==4'b1111) state <= S3; else state <= S1; spi_clk_m <= 1'b0; end
S3: begin state <= S0; start <= 1'b0; vm_reg0[7] <= 1'b0;end
endcase
end end
always @ (negedge wb_clk_i )
if (dl==4'h0) begin
spi_dout_m = vm_reg2[bit_cnt];
end
always @ (posedge spi_clk_m)
if (dl==4'h0) begin
rx [15:0] <= { rx[14:0],spi_din_m};
end
//-------------------------------------------------------------------------
assign ena = wb_we_i ? wb_sel_i : 2'b11;
assign wb_ack_o = wb_cyc_i & wb_stb_i & (ack[1] | wb_we_i);
always @ (posedge wb_clk_i)
begin
ack[0] <= wb_cyc_i & wb_stb_i;
ack[1] <= wb_cyc_i & ack[0];
end
endmodule