https://chanfifo77.tistory.com/71
오늘은 저번 포스팅에 이어 SPI Slave와 RAM 까지 작성해보도록 하겠습니다.
SPI Slave module
Master→ → Slave
R/W | 0 | 0 | A[4] | A[3] | A[2] | A[1] | A[0] | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
Slave module에서 위의 표와 같은 순서로 8-bit nCS 8-bit 순서로 MOSI를 통해 값을 받습니다.
그 후에는 ADDR, DOUT을 통해 RAM과 데이터를 주고받고, MISO를 통해 읽을 값을 Master에게 전달하는 동작이 진행되어야 하기 때문에 Code 작성 후, Test 진행하며 수정해보도록 하겠습니다.
w_en 이 변하지 않는 모습입니다.
(phase = 1에서 nCS이후 1번째 bit가 1이면 Write으로 동작해야하지만 변하지 않는 모습)
- wire로 re_data추가 후 DIN과 연결하여 인스턴스
- w_en part, bit_cnt part 수정
MOSI 첫번 째 bit가 SCLK시작 전에 들어와서 끝난 후에 값이 종료되는 것 확인하였습니다. 이 펄스를 토대로
기존 w_en part의
always @ (phase) 를
always @ (posedge SCLK)로 변경하였습니다.
수정 후 phase = 1 && MOSI 1번 bit에 따라서 w_en 변화하는 모습 확인 가능합니다.
w_en = 1이 된 후에 MISO가 없어 오류가 없어 보이는 모습입니다.
32x8 RAM
IP Catalog > RAM select
마지막으로 Slave module 에서 RAM을 Instance합니다.
Schematic
Code
Slave Code를 마지막으로 마무리하겠습니다.
spi_slave.v 1차
invaild code
`timescale 1ns / 1ps
module spi_slave (
input NCS,
input SCLK,
input MOSI,
output reg MISO,
input [7:0] DIN,
output [4:0] ADDR,
output [7:0] DOUT
);
reg [7:0] in_reg;
reg [2:0] bit_cnt = 3'b000;
reg [4:0] addr_reg;
reg [2:0] state;
reg phase = 0; // 1 : Command, 0 : Data
reg w_en; // 1 : read enable, 0 write enable
wire [7:0] rd_data;
//Declare State Parameter
parameter [1:0] IDLE = 2'b00,
WRITE = 2'b01,
READ = 2'b10;
assign DIN = rd_data;
assign ADDR = addr_reg; // 5-bit [4byte] data
assign DOUT = in_reg; // 8-bit data save at register
always @ (negedge NCS) begin
phase <= ~phase; // Switch the Command or Data Phase
end
// w_en Part
always @ (posedge SCLK) begin // when phase value is change
if (phase && !NCS && (bit_cnt == 0)) begin // former phase is R/D cmd and address
w_en <= MOSI;
end
end
//bit count part
always @(posedge NCS or negedge SCLK) begin
if(NCS)begin
state <= IDLE;
bit_cnt <= 3'b000;
end
else if (!NCS) begin
if(bit_cnt != 3'b111) begin
bit_cnt <= bit_cnt + 1;
end
else if (bit_cnt == 3'b111)begin
bit_cnt <= 3'b000;
end
end
end
// ADDR / DATA part
always @ (posedge SCLK or negedge NCS) begin
// addr_reg
// former phase
if (phase) begin
if (bit_cnt >= 3 && bit_cnt <= 7) begin // if bit_cnt value is 3~7,
addr_reg[7-bit_cnt] <= MOSI; // Transfer MOSI's Data to addr_reg
end
end
// Data Write / Read
// latter phase
else if (!phase) begin
case (state)
IDLE : begin
in_reg <= 8'h00; // initialize the in_reg(connected with DOUT)
if(w_en && !NCS) state <= WRITE; // change state idle to write
else if (!w_en && !NCS) state <= READ; // change state idle to read
end//idle
WRITE : begin
if(w_en) begin
in_reg[(7 - bit_cnt)] <= MOSI; // Write each Data once in SCLK
end
else if (!w_en) begin
state <= READ; // change state write to read
end
else if (in_reg[0] == MOSI) begin // if last data of in_reg is equal with MOSI (= when write operation is end)
state <= IDLE; // change state write to idle
end
end//write
READ : begin
if(!w_en) begin
MISO <= rd_data[7-bit_cnt]; // Read each data one in SCLK
end
else if (w_en) begin // change state read to write
state <= WRITE;
end
else if (rd_data[0] == MISO) begin // if last data of DIN is equal with MISO (when read operatiom is end)
state <= IDLE; // change state read to idle
end
end//read
endcase
end//if(phase)
end
// Instance RAM module
blk_mem_gen_0 ram_0
(SCLK,
w_en,
addr_reg,
in_reg,
rd_data
);
endmodule
spi_slave.v (modified)
invaild code
`timescale 1ns / 1ps
module spi_slave (
input NCS,
input SCLK,
input MOSI,
output reg MISO,
input [7:0] DIN,
output [4:0] ADDR,
output [7:0] DOUT
);
reg [7:0] in_reg;
reg [2:0] bit_cnt = 3'b000;
reg [4:0] addr_reg;
reg [2:0] state;
reg phase = 0; // 1 : Command, 0 : Data
reg w_en; // 1 : wirte enable, 0 : read enable
wire [7:0] rd_data;
//Declare State Parameter
parameter [1:0] IDLE = 2'b00,
WRITE = 2'b01,
READ = 2'b10;
assign DIN = rd_data; // 8-bit rd_data for DIN from RAM
assign ADDR = addr_reg; // 5-bit address
assign DOUT = in_reg; // 8-bit data save at register
always @ (negedge NCS) begin
phase <= ~phase; // Switch the Command or Data Phase
end
// w_en Part
always @ (posedge SCLK) begin // when phase value is change
if (phase && !NCS && (bit_cnt == 0)) begin // first bit on positive phase
w_en <= MOSI; // transfer to w_en
end
end
//bit count part
always @(posedge NCS or negedge SCLK) begin // modified (before : always @ (NCS or negedge SCLK) but, can not use 'edge' and 'level')
if(NCS)begin // initialize state and bit_cnt, during nCS = 1
bit_cnt <= 3'b000;
end
else if (!NCS) begin // else if nCS = 0
if(bit_cnt != 3'b111) begin // if bit_cnt is not full
bit_cnt <= bit_cnt + 1; // bit_cnt ++
end
else if (bit_cnt == 3'b111)begin // if bit_cnt is full
bit_cnt <= 3'b000; // initialize the bit_cnt to zero
end
end
end
// ADDR / DATA part
always @ (posedge SCLK or negedge NCS or posedge NCS) begin
if(NCS) state <= IDLE;
// addr_reg
// former phase
if (phase) begin
if (bit_cnt >= 3 && bit_cnt <= 7) begin // if bit_cnt value is 3~7,
addr_reg[7-bit_cnt] <= MOSI; // Transfer MOSI's Data to addr_reg
end
end//if(phase)
// Data Write / Read
// latter phase
else if (!phase) begin
case (state)
IDLE : begin
in_reg <= 8'h00; // initialize the in_reg(connected with DOUT)
if(w_en && !NCS) state <= WRITE; // change state idle to write
else if (!w_en && !NCS) state <= READ; // change state idle to read
end//idle
WRITE : begin
if(w_en) begin
in_reg[(7 - bit_cnt)] <= MOSI; // Write each Data once in SCLK
end
else if (!w_en) begin
state <= READ; // change state write to read
end
else if (in_reg[0] == MOSI) begin // if last data of in_reg is equal with MOSI (= when write operation is end)
state <= IDLE; // change state write to idle
end
end//write
READ : begin
if(!w_en) begin
MISO <= rd_data[7-bit_cnt]; // Read each data one in SCLK
end
else if (w_en) begin // change state read to write
state <= WRITE;
end
else if (rd_data[0] == MISO) begin // if last data of DIN is equal with MISO (when read operatiom is end)
state <= IDLE; // change state read to idle
end
end//read
endcase
end//if(!phase)
end
// Instance RAM module
blk_mem_gen_0 ram_0
(SCLK,
w_en,
addr_reg,
in_reg,
rd_data
);
endmodule
https://chanfifo77.tistory.com/86
https://chanfifo77.tistory.com/87
수정사항.
'Circuit Design > 🔥HDL' 카테고리의 다른 글
[Verilog] 20. SPI Debugging(1) (0) | 2024.07.18 |
---|---|
[Verilog] 19. AXI Lite(AXI - Light weight) (1) | 2024.07.14 |
[Verilog] 17. SPI Master 설계 (0) | 2024.07.02 |
[Verilog] 16. SPI(Serial Peripheral Interface) (0) | 2024.06.27 |
[Vitis] 1. AXI (0) | 2024.06.27 |