From a68f31b6049889a4aab6e0cd2f01cb643a466040 Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Sun, 5 Apr 2020 22:27:00 +0800 Subject: [PATCH] perips: add uart_tx and gpio Signed-off-by: liangkangnan --- rtl/core/rib.v | 82 ++++++++++++ rtl/perips/gpio.v | 70 ++++++++++ rtl/perips/uart_tx.v | 248 ++++++++++++++++++++++++++++++++++++ rtl/soc/tinyriscv_soc_top.v | 59 +++++++++ sim/sim_default_nowave.bat | 2 +- sim/sim_new_nowave.bat | 2 +- 6 files changed, 461 insertions(+), 2 deletions(-) create mode 100644 rtl/perips/gpio.v create mode 100644 rtl/perips/uart_tx.v diff --git a/rtl/core/rib.v b/rtl/core/rib.v index 289cbc4..27b1d61 100644 --- a/rtl/core/rib.v +++ b/rtl/core/rib.v @@ -71,6 +71,22 @@ module rib( output reg s2_req_o, output reg s2_we_o, + // slave 3 interface + output reg[`MemAddrBus] s3_addr_o, + output reg[`MemBus] s3_data_o, + input wire[`MemBus] s3_data_i, + input wire s3_ack_i, + output reg s3_req_o, + output reg s3_we_o, + + // slave 4 interface + output reg[`MemAddrBus] s4_addr_o, + output reg[`MemBus] s4_data_o, + input wire[`MemBus] s4_data_i, + input wire s4_ack_i, + output reg s4_req_o, + output reg s4_we_o, + output reg hold_flag_o ); @@ -79,6 +95,8 @@ module rib( parameter [3:0]slave_0 = 4'b0000; parameter [3:0]slave_1 = 4'b0001; parameter [3:0]slave_2 = 4'b0010; + parameter [3:0]slave_3 = 4'b0011; + parameter [3:0]slave_4 = 4'b0100; parameter [1:0]grant0 = 2'h0; parameter [1:0]grant1 = 2'h1; @@ -166,15 +184,23 @@ module rib( s0_addr_o <= `ZeroWord; s1_addr_o <= `ZeroWord; s2_addr_o <= `ZeroWord; + s3_addr_o <= `ZeroWord; + s4_addr_o <= `ZeroWord; s0_data_o <= `ZeroWord; s1_data_o <= `ZeroWord; s2_data_o <= `ZeroWord; + s3_data_o <= `ZeroWord; + s4_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; s0_we_o <= `WriteDisable; s1_we_o <= `WriteDisable; s2_we_o <= `WriteDisable; + s3_we_o <= `WriteDisable; + s4_we_o <= `WriteDisable; end else begin m0_ack_o <= `RIB_NACK; m1_ack_o <= `RIB_NACK; @@ -186,15 +212,23 @@ module rib( s0_addr_o <= `ZeroWord; s1_addr_o <= `ZeroWord; s2_addr_o <= `ZeroWord; + s3_addr_o <= `ZeroWord; + s4_addr_o <= `ZeroWord; s0_data_o <= `ZeroWord; s1_data_o <= `ZeroWord; s2_data_o <= `ZeroWord; + s3_data_o <= `ZeroWord; + s4_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; s0_we_o <= `WriteDisable; s1_we_o <= `WriteDisable; s2_we_o <= `WriteDisable; + s3_we_o <= `WriteDisable; + s4_we_o <= `WriteDisable; case (grant) grant0: begin @@ -223,6 +257,22 @@ module rib( m0_ack_o <= s2_ack_i; m0_data_o <= s2_data_i; end + slave_3: begin + s3_req_o <= m0_req_i; + s3_we_o <= m0_we_i; + s3_addr_o <= {{4'h0}, {m0_addr_i[27:0]}}; + s3_data_o <= m0_data_i; + m0_ack_o <= s3_ack_i; + m0_data_o <= s3_data_i; + end + slave_4: begin + s4_req_o <= m0_req_i; + s4_we_o <= m0_we_i; + s4_addr_o <= {{4'h0}, {m0_addr_i[27:0]}}; + s4_data_o <= m0_data_i; + m0_ack_o <= s4_ack_i; + m0_data_o <= s4_data_i; + end default: begin end @@ -254,6 +304,22 @@ module rib( m1_ack_o <= s2_ack_i; m1_data_o <= s2_data_i; end + slave_3: begin + s3_req_o <= m1_req_i; + s3_we_o <= m1_we_i; + s3_addr_o <= {{4'h0}, {m1_addr_i[27:0]}}; + s3_data_o <= m1_data_i; + m1_ack_o <= s3_ack_i; + m1_data_o <= s3_data_i; + end + slave_4: begin + s4_req_o <= m1_req_i; + s4_we_o <= m1_we_i; + s4_addr_o <= {{4'h0}, {m1_addr_i[27:0]}}; + s4_data_o <= m1_data_i; + m1_ack_o <= s4_ack_i; + m1_data_o <= s4_data_i; + end default: begin end @@ -285,6 +351,22 @@ module rib( m2_ack_o <= s2_ack_i; m2_data_o <= s2_data_i; end + slave_3: begin + s3_req_o <= m2_req_i; + s3_we_o <= m2_we_i; + s3_addr_o <= {{4'h0}, {m2_addr_i[27:0]}}; + s3_data_o <= m2_data_i; + m2_ack_o <= s3_ack_i; + m2_data_o <= s3_data_i; + end + slave_4: begin + s4_req_o <= m2_req_i; + s4_we_o <= m2_we_i; + s4_addr_o <= {{4'h0}, {m2_addr_i[27:0]}}; + s4_data_o <= m2_data_i; + m2_ack_o <= s4_ack_i; + m2_data_o <= s4_data_i; + end default: begin end diff --git a/rtl/perips/gpio.v b/rtl/perips/gpio.v new file mode 100644 index 0000000..3162221 --- /dev/null +++ b/rtl/perips/gpio.v @@ -0,0 +1,70 @@ + /* + 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. + */ + + + +module gpio( + + input wire clk, + input wire rst, + + input wire we_i, + input wire req_i, + input wire[31:0] addr_i, + input wire[31:0] data_i, + + output reg[31:0] data_o, + output reg ack_o, + output wire io_pin + + ); + + + localparam GPIO_DATA = 4'h4; + + reg[31:0] gpio_data; + + + assign io_pin = gpio_data[0]; + + + always @ (posedge clk) begin + if (rst == 1'b0) begin + gpio_data <= 32'h0; + end else begin + if (we_i == 1'b1) begin + case (addr_i[3:0]) + GPIO_DATA: begin + gpio_data <= data_i; + end + endcase + end + end + end + + always @ (*) begin + if (rst == 1'b0) begin + data_o <= 32'h0; + end else begin + case (addr_i[3:0]) + GPIO_DATA: begin + data_o <= gpio_data; + end + endcase + end + end + +endmodule diff --git a/rtl/perips/uart_tx.v b/rtl/perips/uart_tx.v new file mode 100644 index 0000000..26958fb --- /dev/null +++ b/rtl/perips/uart_tx.v @@ -0,0 +1,248 @@ + /* + 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. + */ + + +module uart_tx( + + input wire clk, + input wire rst, + + input wire we_i, + input wire req_i, + input wire[31:0] addr_i, + input wire[31:0] data_i, + + output reg[31:0] data_o, + output reg ack_o, + output wire tx_pin + + ); + + + localparam BAUD_115200 = 32'h1B3; + + localparam S_IDLE = 4'b0001; + localparam S_START = 4'b0010; + localparam S_SEND_BYTE = 4'b0100; + localparam S_STOP = 4'b1000; + + reg[31:0] fifo_data[31:0]; + reg tx_data_valid; + reg tx_data_ready; + reg[8:0] fifo_index; + reg[8:0] fifo_count; + + reg[3:0] state; + reg[3:0] next_state; + reg[15:0] cycle_cnt; + reg[2:0] bit_cnt; + reg[7:0] tx_data; + reg tx_reg; + + localparam UART_CTRL = 4'h0; + localparam UART_STATUS = 4'h4; + localparam UART_BAUD = 4'h8; + localparam UART_TXDATA = 4'hc; + + reg[31:0] uart_ctrl; + reg[31:0] uart_status; + reg[31:0] uart_baud; + + + assign tx_pin = tx_reg; + + + always @ (posedge clk) begin + if (rst == 1'b0) begin + uart_ctrl <= 32'h0; + uart_status <= 32'h0; + fifo_count <= 8'h0; + fifo_index <= 8'h0; + uart_baud <= BAUD_115200; + end else begin + if (we_i == 1'b1) begin + case (addr_i[3:0]) + UART_CTRL: begin + uart_ctrl <= data_i; + if (data_i[1] == 1'b1) begin + fifo_count <= 8'h0; + end + if (uart_ctrl[0] == 1'b0 && data_i[0] == 1'b1) begin + if (fifo_count > 8'h0) begin + tx_data_valid <= 1'b1; + fifo_index <= 8'h0; + uart_status <= 32'h1; + end + end + end + UART_BAUD: begin + uart_baud <= data_i; + end + UART_TXDATA: begin + if (fifo_count <= 8'd31) begin + fifo_data[fifo_count] <= data_i; + fifo_count <= fifo_count + 1'b1; + end + end + endcase + end else begin + if (tx_data_ready == 1'b1 && tx_data_valid == 1'b1) begin + fifo_count <= 8'h0; + tx_data_valid <= 1'b0; + fifo_index <= 8'h0; + uart_status <= 32'h0; + uart_ctrl[0] <= 1'b0; + end else if (cycle_cnt == uart_baud[15:0] && bit_cnt == 3'd7) begin + fifo_index <= fifo_index + 1'b1; + end + end + end + end + + always @ (*) begin + if (rst == 1'b0) begin + data_o <= 32'h0; + end else begin + case (addr_i[3:0]) + UART_CTRL: begin + data_o <= uart_ctrl; + end + UART_STATUS: begin + data_o <= uart_status; + end + UART_BAUD: begin + data_o <= uart_baud; + end + default: begin + data_o <= 32'h0; + end + endcase + end + end + + always @ (posedge clk) begin + if (rst == 1'b0) begin + state <= S_IDLE; + end else begin + state <= next_state; + end + end + + always @ (*) begin + case (state) + S_IDLE: begin + if (tx_data_valid == 1'b1) begin + next_state <= S_START; + end else begin + next_state <= S_IDLE; + end + end + S_START: begin + if (cycle_cnt == uart_baud[15:0]) begin + next_state <= S_SEND_BYTE; + end else begin + next_state <= S_START; + end + end + S_SEND_BYTE: begin + if (cycle_cnt == uart_baud[15:0] && bit_cnt == 3'd7) begin + next_state <= S_STOP; + end else begin + next_state <= S_SEND_BYTE; + end + end + S_STOP: begin + if (cycle_cnt == uart_baud[15:0]) begin + next_state <= S_IDLE; + end else begin + next_state <= S_STOP; + end + end + default: begin + next_state <= S_IDLE; + end + endcase + end + + always @ (posedge clk) begin + if (rst == 1'b0) begin + tx_data_ready <= 1'b0; + end else if (state == S_STOP && cycle_cnt == uart_baud[15:0]) begin + if (fifo_index == (fifo_count - 1'b1)) begin + tx_data_ready <= 1'b1; + end + end else begin + tx_data_ready <= 1'b0; + end + end + + always @ (posedge clk) begin + if (rst == 1'b0) begin + tx_data <= 8'd0; + end else if (state == S_IDLE && tx_data_valid == 1'b1) begin + tx_data <= fifo_data[fifo_index]; + end + end + + always @ (posedge clk) begin + if (rst == 1'b0) begin + bit_cnt <= 3'd0; + end else if (state == S_SEND_BYTE) begin + if (cycle_cnt == uart_baud[15:0]) begin + bit_cnt <= bit_cnt + 3'd1; + end else begin + bit_cnt <= bit_cnt; + end + end else begin + bit_cnt <= 3'd0; + end + end + + always @ (posedge clk) begin + if (rst == 1'b0) begin + cycle_cnt <= 16'd0; + end else if ((state == S_SEND_BYTE && cycle_cnt == uart_baud[15:0]) || next_state != state) begin + cycle_cnt <= 16'd0; + end else begin + cycle_cnt <= cycle_cnt + 16'd1; + end + end + + always @ (posedge clk) begin + if (rst == 1'b0) begin + tx_reg <= 1'b1; + end else begin + case (state) + S_IDLE: begin + tx_reg <= 1'b1; + end + S_START: begin + tx_reg <= 1'b0; + end + S_SEND_BYTE: begin + tx_reg <= tx_data[bit_cnt]; + end + S_STOP: begin + tx_reg <= 1'b1; + end + default: begin + tx_reg <= 1'b1; + end + endcase + end + end + +endmodule diff --git a/rtl/soc/tinyriscv_soc_top.v b/rtl/soc/tinyriscv_soc_top.v index 10ae4d2..9a638a1 100644 --- a/rtl/soc/tinyriscv_soc_top.v +++ b/rtl/soc/tinyriscv_soc_top.v @@ -27,6 +27,9 @@ module tinyriscv_soc_top( output wire halted_ind, + output wire tx_pin, + output wire io_pin, + input wire jtag_TCK, input wire jtag_TMS, input wire jtag_TDI, @@ -83,6 +86,22 @@ module tinyriscv_soc_top( wire s2_req_o; wire s2_we_o; + // slave 3 interface + wire[`MemAddrBus] s3_addr_o; + wire[`MemBus] s3_data_o; + wire[`MemBus] s3_data_i; + wire s3_ack_i; + wire s3_req_o; + wire s3_we_o; + + // slave 4 interface + wire[`MemAddrBus] s4_addr_o; + wire[`MemBus] s4_data_o; + wire[`MemBus] s4_data_i; + wire s4_ack_i; + wire s4_req_o; + wire s4_we_o; + // rib wire rib_hold_flag_o; @@ -177,6 +196,30 @@ module tinyriscv_soc_top( .ack_o(s2_ack_i) ); + uart_tx uart_tx_0( + .clk(clk), + .rst(rst), + .we_i(s3_we_o), + .req_i(s3_req_o), + .addr_i(s3_addr_o), + .data_i(s3_data_o), + .data_o(s3_data_i), + .ack_o(s3_ack_i), + .tx_pin(tx_pin) + ); + + gpio gpio_0( + .clk(clk), + .rst(rst), + .we_i(s4_we_o), + .req_i(s4_req_o), + .addr_i(s4_addr_o), + .data_i(s4_data_o), + .data_o(s4_data_i), + .ack_o(s4_ack_i), + .io_pin(io_pin) + ); + rib u_rib( .clk(clk), .rst(rst), @@ -229,6 +272,22 @@ module tinyriscv_soc_top( .s2_req_o(s2_req_o), .s2_we_o(s2_we_o), + // slave 3 interface + .s3_addr_o(s3_addr_o), + .s3_data_o(s3_data_o), + .s3_data_i(s3_data_i), + .s3_ack_i(s3_ack_i), + .s3_req_o(s3_req_o), + .s3_we_o(s3_we_o), + + // slave 4 interface + .s4_addr_o(s4_addr_o), + .s4_data_o(s4_data_o), + .s4_data_i(s4_data_i), + .s4_ack_i(s4_ack_i), + .s4_req_o(s4_req_o), + .s4_we_o(s4_we_o), + .hold_flag_o(rib_hold_flag_o) ); diff --git a/sim/sim_default_nowave.bat b/sim/sim_default_nowave.bat index 4194d3d..859891e 100644 --- a/sim/sim_default_nowave.bat +++ b/sim/sim_default_nowave.bat @@ -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\core\ram.v ..\rtl\core\rom.v ..\rtl\core\if_id.v ..\rtl\core\div.v ..\rtl\core\rib.v ..\rtl\core\clint.v ..\rtl\debug\jtag_dm.v ..\rtl\debug\jtag_driver.v ..\rtl\debug\jtag_top.v ..\rtl\perips\timer.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\core\ram.v ..\rtl\core\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 vvp out.vvp diff --git a/sim/sim_new_nowave.bat b/sim/sim_new_nowave.bat index 7b46e99..0d857b1 100644 --- a/sim/sim_new_nowave.bat +++ b/sim/sim_new_nowave.bat @@ -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\core\ram.v ..\rtl\core\rom.v ..\rtl\core\if_id.v ..\rtl\core\div.v ..\rtl\core\rib.v ..\rtl\core\clint.v ..\rtl\debug\jtag_dm.v ..\rtl\debug\jtag_driver.v ..\rtl\debug\jtag_top.v ..\rtl\perips\timer.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\core\ram.v ..\rtl\core\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 vvp out.vvp