perips: add spi master

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/1/head
liangkangnan 2020-05-05 18:31:08 +08:00
parent 837af2c977
commit 07b33baf94
5 changed files with 328 additions and 4 deletions

View File

@ -87,6 +87,14 @@ module rib(
output reg s4_req_o, // 4访
output reg s4_we_o, // 4
// slave 5 interface
output reg[`MemAddrBus] s5_addr_o, // 5
output reg[`MemBus] s5_data_o, // 5
input wire[`MemBus] s5_data_i, // 5
input wire s5_ack_i, // 5访
output reg s5_req_o, // 5访
output reg s5_we_o, // 5
output reg hold_flag_o // 线
);
@ -99,6 +107,7 @@ module rib(
parameter [3:0]slave_2 = 4'b0010;
parameter [3:0]slave_3 = 4'b0011;
parameter [3:0]slave_4 = 4'b0100;
parameter [3:0]slave_5 = 4'b0101;
parameter [1:0]grant0 = 2'h0;
parameter [1:0]grant1 = 2'h1;
@ -191,21 +200,25 @@ module rib(
s2_addr_o = `ZeroWord;
s3_addr_o = `ZeroWord;
s4_addr_o = `ZeroWord;
s5_addr_o = `ZeroWord;
s0_data_o = `ZeroWord;
s1_data_o = `ZeroWord;
s2_data_o = `ZeroWord;
s3_data_o = `ZeroWord;
s4_data_o = `ZeroWord;
s5_data_o = `ZeroWord;
s0_req_o = `RIB_NREQ;
s1_req_o = `RIB_NREQ;
s2_req_o = `RIB_NREQ;
s3_req_o = `RIB_NREQ;
s4_req_o = `RIB_NREQ;
s5_req_o = `RIB_NREQ;
s0_we_o = `WriteDisable;
s1_we_o = `WriteDisable;
s2_we_o = `WriteDisable;
s3_we_o = `WriteDisable;
s4_we_o = `WriteDisable;
s5_we_o = `WriteDisable;
end else begin
m0_ack_o = `RIB_NACK;
m1_ack_o = `RIB_NACK;
@ -219,21 +232,25 @@ module rib(
s2_addr_o = `ZeroWord;
s3_addr_o = `ZeroWord;
s4_addr_o = `ZeroWord;
s5_addr_o = `ZeroWord;
s0_data_o = `ZeroWord;
s1_data_o = `ZeroWord;
s2_data_o = `ZeroWord;
s3_data_o = `ZeroWord;
s4_data_o = `ZeroWord;
s5_data_o = `ZeroWord;
s0_req_o = `RIB_NREQ;
s1_req_o = `RIB_NREQ;
s2_req_o = `RIB_NREQ;
s3_req_o = `RIB_NREQ;
s4_req_o = `RIB_NREQ;
s5_req_o = `RIB_NREQ;
s0_we_o = `WriteDisable;
s1_we_o = `WriteDisable;
s2_we_o = `WriteDisable;
s3_we_o = `WriteDisable;
s4_we_o = `WriteDisable;
s5_we_o = `WriteDisable;
case (grant)
grant0: begin
@ -278,6 +295,14 @@ module rib(
m0_ack_o = s4_ack_i;
m0_data_o = s4_data_i;
end
slave_5: begin
s5_req_o = m0_req_i;
s5_we_o = m0_we_i;
s5_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
s5_data_o = m0_data_i;
m0_ack_o = s5_ack_i;
m0_data_o = s5_data_i;
end
default: begin
end
@ -325,6 +350,14 @@ module rib(
m1_ack_o = s4_ack_i;
m1_data_o = s4_data_i;
end
slave_5: begin
s5_req_o = m1_req_i;
s5_we_o = m1_we_i;
s5_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
s5_data_o = m1_data_i;
m1_ack_o = s5_ack_i;
m1_data_o = s5_data_i;
end
default: begin
end
@ -372,13 +405,21 @@ module rib(
m2_ack_o = s4_ack_i;
m2_data_o = s4_data_i;
end
slave_5: begin
s5_req_o = m2_req_i;
s5_we_o = m2_we_i;
s5_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
s5_data_o = m2_data_i;
m2_ack_o = s5_ack_i;
m2_data_o = s5_data_i;
end
default: begin
end
endcase
end
default: begin
end
endcase
end

246
rtl/perips/spi.v Normal file
View File

@ -0,0 +1,246 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// spi master
module spi(
input wire clk,
input wire rst,
input wire[31:0] data_i,
input wire[31:0] addr_i,
input wire we_i,
input wire req_i,
output reg[31:0] data_o,
output reg ack_o,
output reg spi_mosi, // spispi
input wire spi_miso, // spispi
output wire spi_ss, // spi
output reg spi_clk // spiclk
);
localparam SPI_CTRL = 4'h0; // spi_ctrl
localparam SPI_DATA = 4'h4; // spi_data
localparam SPI_STATUS = 4'h8; // spi_status
// spi
// addr: 0x00
// [0]: 1: enable, 0: disable
// [1]: CPOL
// [2]: CPHA
// [3]: select slave, 1: select, 0: deselect
// [15:8]: clk div
reg[31:0] spi_ctrl;
// spi
// addr: 0x04
// [7:0] cmd or inout data
reg[31:0] spi_data;
// spi
// addr: 0x08
// [0]: 1: busy, 0: idle
reg[31:0] spi_status;
reg[8:0] clk_cnt; //
reg en; // 使
reg[4:0] spi_clk_edge_cnt; // spi clk沿
reg spi_clk_edge_level; // spi clk沿
reg[7:0] rdata; // spi
reg done; //
reg[3:0] bit_index; // bit
wire[8:0] div_cnt;
assign spi_ss = ~spi_ctrl[3]; // SPI
assign div_cnt = spi_ctrl[15:8];// 0: 21428316432
// 使
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
en <= 1'b0;
end else begin
if (spi_ctrl[0] == 1'b1) begin
en <= 1'b1;
end else if (done == 1'b1) begin
en <= 1'b0;
end else begin
en <= en;
end
end
end
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
clk_cnt <= 9'h0;
end else if (en == 1'b1) begin
if (clk_cnt == div_cnt) begin
clk_cnt <= 9'h0;
end else begin
clk_cnt <= clk_cnt + 1'b1;
end
end else begin
clk_cnt <= 9'h0;
end
end
// spi clk沿
// 沿
always @ (posedge clk) begin
if (rst == 1'b0) begin
spi_clk_edge_cnt <= 5'h0;
spi_clk_edge_level <= 1'b0;
end else if (en == 1'b1) begin
//
if (clk_cnt == div_cnt) begin
if (spi_clk_edge_cnt == 5'd17) begin
spi_clk_edge_cnt <= 5'h0;
spi_clk_edge_level <= 1'b0;
end else begin
spi_clk_edge_cnt <= spi_clk_edge_cnt + 1'b1;
spi_clk_edge_level <= 1'b1;
end
end else begin
spi_clk_edge_level <= 1'b0;
end
end else begin
spi_clk_edge_cnt <= 5'h0;
spi_clk_edge_level <= 1'b0;
end
end
// bit
always @ (posedge clk) begin
if (rst == 1'b0) begin
spi_clk <= 1'b0;
rdata <= 8'h0;
spi_mosi <= 1'b0;
bit_index <= 4'h0;
end else begin
if (en) begin
if (spi_clk_edge_level == 1'b1) begin
case (spi_clk_edge_cnt)
// 沿
1, 3, 5, 7, 9, 11, 13, 15: begin
spi_clk <= ~spi_clk;
if (spi_ctrl[2] == 1'b1) begin
spi_mosi <= spi_data[bit_index]; // 1bit
bit_index <= bit_index - 1'b1;
end else begin
rdata <= {rdata[6:0], spi_miso}; // 1bit
end
end
// 沿
2, 4, 6, 8, 10, 12, 14, 16: begin
spi_clk <= ~spi_clk;
if (spi_ctrl[2] == 1'b1) begin
rdata <= {rdata[6:0], spi_miso}; // 1bit
end else begin
spi_mosi <= spi_data[bit_index]; // 1bit
bit_index <= bit_index - 1'b1;
end
end
17: begin
spi_clk <= spi_ctrl[1];
end
endcase
end
end else begin
//
spi_clk <= spi_ctrl[1];
if (spi_ctrl[2] == 1'b0) begin
spi_mosi <= spi_data[7]; //
bit_index <= 4'h6;
end else begin
bit_index <= 4'h7;
end
end
end
end
// ()
always @ (posedge clk) begin
if (rst == 1'b0) begin
done <= 1'b0;
end else begin
if (en && spi_clk_edge_cnt == 5'd17) begin
done <= 1'b1;
end else begin
done <= 1'b0;
end
end
end
// write reg
always @ (posedge clk) begin
if (rst == 1'b0) begin
spi_ctrl <= 32'h0;
spi_data <= 32'h0;
spi_status <= 32'h0;
end else begin
spi_status[0] <= en;
if (we_i == 1'b1) begin
case (addr_i[3:0])
SPI_CTRL: begin
spi_ctrl <= data_i;
end
SPI_DATA: begin
spi_data <= data_i;
end
default: begin
end
endcase
end else begin
spi_ctrl[0] <= 1'b0;
//
if (done == 1'b1) begin
spi_data <= {24'h0, rdata};
end
end
end
end
// read reg
always @ (*) begin
if (rst == 1'b0) begin
data_o = 32'h0;
end else begin
case (addr_i[3:0])
SPI_CTRL: begin
data_o = spi_ctrl;
end
SPI_DATA: begin
data_o = spi_data;
end
SPI_STATUS: begin
data_o = spi_status;
end
default: begin
data_o = 32'h0;
end
endcase
end
end
endmodule

View File

@ -33,7 +33,12 @@ module tinyriscv_soc_top(
input wire jtag_TCK, // JTAG TCK
input wire jtag_TMS, // JTAG TMS
input wire jtag_TDI, // JTAG TDI
output wire jtag_TDO // JTAG TDO
output wire jtag_TDO, // JTAG TDO
input wire spi_miso, // SPI MISO
output wire spi_mosi, // SPI MOSI
output wire spi_ss, // SPI SS
output wire spi_clk // SPI CLK
);
@ -102,6 +107,14 @@ module tinyriscv_soc_top(
wire s4_req_o;
wire s4_we_o;
// slave 5 interface
wire[`MemAddrBus] s5_addr_o;
wire[`MemBus] s5_data_o;
wire[`MemBus] s5_data_i;
wire s5_ack_i;
wire s5_req_o;
wire s5_we_o;
// rib
wire rib_hold_flag_o;
@ -227,6 +240,22 @@ module tinyriscv_soc_top(
.io_pin(io_pin)
);
// spi
spi spi_0(
.clk(clk),
.rst(rst),
.data_i(s5_data_o),
.addr_i(s5_addr_o),
.we_i(s5_we_o),
.req_i(s5_req_o),
.data_o(s5_data_i),
.ack_o(s5_ack_i),
.spi_mosi(spi_mosi),
.spi_miso(spi_miso),
.spi_ss(spi_ss),
.spi_clk(spi_clk)
);
// rib
rib u_rib(
.clk(clk),
@ -296,6 +325,14 @@ module tinyriscv_soc_top(
.s4_req_o(s4_req_o),
.s4_we_o(s4_we_o),
// slave 5 interface
.s5_addr_o(s5_addr_o),
.s5_data_o(s5_data_o),
.s5_data_i(s5_data_i),
.s5_ack_i(s5_ack_i),
.s5_req_o(s5_req_o),
.s5_we_o(s5_we_o),
.hold_flag_o(rib_hold_flag_o)
);

View File

@ -1,2 +1,2 @@
iverilog -s tinyriscv_soc_tb -o out.vvp -I ..\rtl\core tinyriscv_soc_tb.v ..\rtl\core\defines.v ..\rtl\core\ex.v ..\rtl\core\id.v ..\rtl\core\tinyriscv.v ..\rtl\core\pc_reg.v ..\rtl\core\id_ex.v ..\rtl\core\ctrl.v ..\rtl\core\regs.v ..\rtl\perips\ram.v ..\rtl\perips\rom.v ..\rtl\core\if_id.v ..\rtl\core\div.v ..\rtl\core\rib.v ..\rtl\core\clint.v ..\rtl\core\csr_reg.v ..\rtl\debug\jtag_dm.v ..\rtl\debug\jtag_driver.v ..\rtl\debug\jtag_top.v ..\rtl\perips\timer.v ..\rtl\perips\uart_tx.v ..\rtl\perips\gpio.v ..\rtl\soc\tinyriscv_soc_top.v
iverilog -s tinyriscv_soc_tb -o out.vvp -I ..\rtl\core tinyriscv_soc_tb.v ..\rtl\core\defines.v ..\rtl\core\ex.v ..\rtl\core\id.v ..\rtl\core\tinyriscv.v ..\rtl\core\pc_reg.v ..\rtl\core\id_ex.v ..\rtl\core\ctrl.v ..\rtl\core\regs.v ..\rtl\perips\ram.v ..\rtl\perips\rom.v ..\rtl\perips\spi.v ..\rtl\core\if_id.v ..\rtl\core\div.v ..\rtl\core\rib.v ..\rtl\core\clint.v ..\rtl\core\csr_reg.v ..\rtl\debug\jtag_dm.v ..\rtl\debug\jtag_driver.v ..\rtl\debug\jtag_top.v ..\rtl\perips\timer.v ..\rtl\perips\uart_tx.v ..\rtl\perips\gpio.v ..\rtl\soc\tinyriscv_soc_top.v
vvp out.vvp

View File

@ -1,3 +1,3 @@
..\tools\BinToMem_CLI.exe %1 %2
iverilog -s tinyriscv_soc_tb -o out.vvp -I ..\rtl\core tinyriscv_soc_tb.v ..\rtl\core\defines.v ..\rtl\core\ex.v ..\rtl\core\id.v ..\rtl\core\tinyriscv.v ..\rtl\core\pc_reg.v ..\rtl\core\id_ex.v ..\rtl\core\ctrl.v ..\rtl\core\regs.v ..\rtl\perips\ram.v ..\rtl\perips\rom.v ..\rtl\core\if_id.v ..\rtl\core\div.v ..\rtl\core\rib.v ..\rtl\core\clint.v ..\rtl\core\csr_reg.v ..\rtl\debug\jtag_dm.v ..\rtl\debug\jtag_driver.v ..\rtl\debug\jtag_top.v ..\rtl\perips\timer.v ..\rtl\perips\uart_tx.v ..\rtl\perips\gpio.v ..\rtl\soc\tinyriscv_soc_top.v
iverilog -s tinyriscv_soc_tb -o out.vvp -I ..\rtl\core tinyriscv_soc_tb.v ..\rtl\core\defines.v ..\rtl\core\ex.v ..\rtl\core\id.v ..\rtl\core\tinyriscv.v ..\rtl\core\pc_reg.v ..\rtl\core\id_ex.v ..\rtl\core\ctrl.v ..\rtl\core\regs.v ..\rtl\perips\ram.v ..\rtl\perips\rom.v ..\rtl\perips\spi.v ..\rtl\core\if_id.v ..\rtl\core\div.v ..\rtl\core\rib.v ..\rtl\core\clint.v ..\rtl\core\csr_reg.v ..\rtl\debug\jtag_dm.v ..\rtl\debug\jtag_driver.v ..\rtl\debug\jtag_top.v ..\rtl\perips\timer.v ..\rtl\perips\uart_tx.v ..\rtl\perips\gpio.v ..\rtl\soc\tinyriscv_soc_top.v
vvp out.vvp