From a73b0ea36bff22bced97d7f56733f6732065690d Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Sat, 4 Jul 2020 14:32:31 +0800 Subject: [PATCH] rtl: add uart_debug module Signed-off-by: liangkangnan --- rtl/core/rib.v | 102 +++++++++++- rtl/debug/uart_debug.v | 324 ++++++++++++++++++++++++++++++++++++ rtl/soc/tinyriscv_soc_top.v | 38 ++++- 3 files changed, 455 insertions(+), 9 deletions(-) create mode 100644 rtl/debug/uart_debug.v diff --git a/rtl/core/rib.v b/rtl/core/rib.v index f596f03..c6b898c 100644 --- a/rtl/core/rib.v +++ b/rtl/core/rib.v @@ -47,6 +47,14 @@ module rib( input wire m2_req_i, // 主设备2访问请求标志 input wire m2_we_i, // 主设备2写标志 + // master 3 interface + input wire[`MemAddrBus] m3_addr_i, // 主设备3读、写地址 + input wire[`MemBus] m3_data_i, // 主设备3写数据 + output reg[`MemBus] m3_data_o, // 主设备3读取到的数据 + output reg m3_ack_o, // 主设备3访问完成标志 + input wire m3_req_i, // 主设备3访问请求标志 + input wire m3_we_i, // 主设备3写标志 + // slave 0 interface output reg[`MemAddrBus] s0_addr_o, // 从设备0读、写地址 output reg[`MemBus] s0_data_o, // 从设备0写数据 @@ -112,15 +120,16 @@ module rib( parameter [1:0]grant0 = 2'h0; parameter [1:0]grant1 = 2'h1; parameter [1:0]grant2 = 2'h2; + parameter [1:0]grant3 = 2'h3; - wire[2:0] req; + wire[3:0] req; reg[1:0] grant; reg[1:0] next_grant; // 主设备请求信号 - assign req = {m2_req_i, m1_req_i, m0_req_i}; + assign req = {m3_req_i, m2_req_i, m1_req_i, m0_req_i}; // 授权主设备切换 @@ -142,7 +151,10 @@ module rib( end else begin case (grant) grant0: begin - if (req[0]) begin + if (req[3]) begin + next_grant = grant3; + hold_flag_o = `HoldEnable; + end else if (req[0]) begin next_grant = grant0; hold_flag_o = `HoldEnable; end else if (req[2]) begin @@ -154,7 +166,10 @@ module rib( end end grant1: begin - if (req[0]) begin + if (req[3]) begin + next_grant = grant3; + hold_flag_o = `HoldEnable; + end else if (req[0]) begin next_grant = grant0; hold_flag_o = `HoldEnable; end else if (req[2]) begin @@ -166,7 +181,25 @@ module rib( end end grant2: begin - if (req[0]) begin + if (req[3]) begin + next_grant = grant3; + hold_flag_o = `HoldEnable; + end else if (req[0]) begin + next_grant = grant0; + hold_flag_o = `HoldEnable; + end else if (req[2]) begin + next_grant = grant2; + hold_flag_o = `HoldEnable; + end else begin + next_grant = grant1; + hold_flag_o = `HoldDisable; + end + end + grant3: begin + if (req[3]) begin + next_grant = grant3; + hold_flag_o = `HoldEnable; + end else if (req[0]) begin next_grant = grant0; hold_flag_o = `HoldEnable; end else if (req[2]) begin @@ -191,9 +224,11 @@ module rib( m0_ack_o = `RIB_NACK; m1_ack_o = `RIB_NACK; m2_ack_o = `RIB_NACK; + m3_ack_o = `RIB_NACK; m0_data_o = `ZeroWord; m1_data_o = `INST_NOP; m2_data_o = `ZeroWord; + m3_data_o = `ZeroWord; s0_addr_o = `ZeroWord; s1_addr_o = `ZeroWord; @@ -223,9 +258,11 @@ module rib( m0_ack_o = `RIB_NACK; m1_ack_o = `RIB_NACK; m2_ack_o = `RIB_NACK; + m3_ack_o = `RIB_NACK; m0_data_o = `ZeroWord; m1_data_o = `INST_NOP; m2_data_o = `ZeroWord; + m3_data_o = `ZeroWord; s0_addr_o = `ZeroWord; s1_addr_o = `ZeroWord; @@ -418,6 +455,61 @@ module rib( end endcase end + grant3: begin + case (m3_addr_i[31:28]) + slave_0: begin + s0_req_o = m3_req_i; + s0_we_o = m3_we_i; + s0_addr_o = {{4'h0}, {m3_addr_i[27:0]}}; + s0_data_o = m3_data_i; + m3_ack_o = s0_ack_i; + m3_data_o = s0_data_i; + end + slave_1: begin + s1_req_o = m3_req_i; + s1_we_o = m3_we_i; + s1_addr_o = {{4'h0}, {m3_addr_i[27:0]}}; + s1_data_o = m3_data_i; + m3_ack_o = s1_ack_i; + m3_data_o = s1_data_i; + end + slave_2: begin + s2_req_o = m3_req_i; + s2_we_o = m3_we_i; + s2_addr_o = {{4'h0}, {m3_addr_i[27:0]}}; + s2_data_o = m3_data_i; + m3_ack_o = s2_ack_i; + m3_data_o = s2_data_i; + end + slave_3: begin + s3_req_o = m3_req_i; + s3_we_o = m3_we_i; + s3_addr_o = {{4'h0}, {m3_addr_i[27:0]}}; + s3_data_o = m3_data_i; + m3_ack_o = s3_ack_i; + m3_data_o = s3_data_i; + end + slave_4: begin + s4_req_o = m3_req_i; + s4_we_o = m3_we_i; + s4_addr_o = {{4'h0}, {m3_addr_i[27:0]}}; + s4_data_o = m3_data_i; + m3_ack_o = s4_ack_i; + m3_data_o = s4_data_i; + end + slave_5: begin + s5_req_o = m3_req_i; + s5_we_o = m3_we_i; + s5_addr_o = {{4'h0}, {m3_addr_i[27:0]}}; + s5_data_o = m3_data_i; + m3_ack_o = s5_ack_i; + m3_data_o = s5_data_i; + end + default: begin + + end + endcase + end default: begin end diff --git a/rtl/debug/uart_debug.v b/rtl/debug/uart_debug.v new file mode 100644 index 0000000..803a95d --- /dev/null +++ b/rtl/debug/uart_debug.v @@ -0,0 +1,324 @@ + /* + 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. + */ + + +// clk = 50MHz时对应的波特率分频系数 +`define UART_BAUD_115200 32'h1B8 + +// 串口寄存器地址 +`define UART_CTRL_REG 32'h30000000 +`define UART_STATUS_REG 32'h30000004 +`define UART_BAUD_REG 32'h30000008 +`define UART_TX_REG 32'h3000000c +`define UART_RX_REG 32'h30000010 + +`define UART_TX_BUSY_FLAG 32'h1 +`define UART_RX_OVER_FLAG 32'h2 + +// 第一个包的大小 +`define UART_FIRST_PACKET_LEN 8'd131 +// 其他包的大小(每次烧写的字节数) +`define UART_REMAIN_PACKET_LEN 8'd131 + +`define UART_RESP_ACK 32'h6 +`define UART_RESP_NAK 32'h15 + +// 烧写起始地址 +`define ROM_START_ADDR 32'h0 + + +// 串口更新固件模块 +module uart_debug( + + input wire clk, // 时钟信号 + input wire rst, // 复位信号 + + input wire debug_en_i, // 模块使能信号 + + output wire req_o, + output reg mem_we_o, + output reg[31:0] mem_addr_o, + output reg[31:0] mem_wdata_o, + input wire[31:0] mem_rdata_i + + ); + + + // 状态 + localparam S_IDLE = 1; + localparam S_INIT_UART_BAUD = 2; + localparam S_CLEAR_UART_RX_OVER_FLAG = 3; + localparam S_WAIT_BYTE = 4; + localparam S_WAIT_BYTE2 = 5; + localparam S_GET_BYTE = 6; + localparam S_REC_FIRST_PACKET = 7; + localparam S_REC_REMAIN_PACKET = 8; + localparam S_SEND_ACK = 9; + localparam S_SEND_NAK = 10; + localparam S_CRC_START = 11; + localparam S_CRC_CALC = 12; + localparam S_CRC_END = 13; + localparam S_WRITE_MEM = 14; + + reg[3:0] state; + + // 存放串口接收到的数据 + reg[7:0] rx_data[0:131]; + reg[7:0] rec_bytes_index; + reg[7:0] need_to_rec_bytes; + reg[15:0] remain_packet_count; + reg[31:0] fw_file_size; + reg[31:0] write_mem_addr; + reg[31:0] write_mem_data; + reg[7:0] write_mem_byte_index; + + reg[15:0] crc_result; + reg[3:0] crc_bit_index; + reg[7:0] crc_byte_index; + + + // 向总线请求信号 + assign req_o = (rst == 1'b1 && debug_en_i == 1'b1)? 1'b1: 1'b0; + + + always @ (posedge clk) begin + if (rst == 1'b0 || debug_en_i == 1'b0) begin + mem_addr_o <= 32'h0; + mem_we_o <= 1'b0; + mem_wdata_o <= 32'h0; + state <= S_IDLE; + remain_packet_count <= 16'h0; + end else begin + case (state) + S_IDLE: begin + mem_addr_o <= `UART_CTRL_REG; + mem_wdata_o <= 32'h3; + mem_we_o <= 1'b1; + state <= S_INIT_UART_BAUD; + end + S_INIT_UART_BAUD: begin + mem_addr_o <= `UART_BAUD_REG; + mem_wdata_o <= `UART_BAUD_115200; + mem_we_o <= 1'b1; + state <= S_REC_FIRST_PACKET; + end + S_REC_FIRST_PACKET: begin + remain_packet_count <= 16'h0; + mem_addr_o <= 32'h0; + mem_we_o <= 1'b0; + mem_wdata_o <= 32'h0; + state <= S_CLEAR_UART_RX_OVER_FLAG; + end + S_REC_REMAIN_PACKET: begin + mem_addr_o <= 32'h0; + mem_we_o <= 1'b0; + mem_wdata_o <= 32'h0; + state <= S_CLEAR_UART_RX_OVER_FLAG; + end + S_CLEAR_UART_RX_OVER_FLAG: begin + mem_addr_o <= `UART_STATUS_REG; + mem_wdata_o <= 32'h0; + mem_we_o <= 1'b1; + state <= S_WAIT_BYTE; + end + S_WAIT_BYTE: begin + mem_addr_o <= `UART_STATUS_REG; + mem_wdata_o <= 32'h0; + mem_we_o <= 1'b0; + state <= S_WAIT_BYTE2; + end + S_WAIT_BYTE2: begin + if ((mem_rdata_i & `UART_RX_OVER_FLAG) == `UART_RX_OVER_FLAG) begin + mem_addr_o <= `UART_RX_REG; + mem_wdata_o <= 32'h0; + mem_we_o <= 1'b0; + state <= S_GET_BYTE; + end + end + S_GET_BYTE: begin + if (rec_bytes_index == (need_to_rec_bytes - 1'b1)) begin + state <= S_CRC_START; + end else begin + state <= S_CLEAR_UART_RX_OVER_FLAG; + end + end + S_CRC_START: begin + state <= S_CRC_CALC; + end + S_CRC_CALC: begin + if ((crc_byte_index == need_to_rec_bytes - 2) && crc_bit_index == 4'h8) begin + state <= S_CRC_END; + end + end + S_CRC_END: begin + if (crc_result == {rx_data[need_to_rec_bytes - 1], rx_data[need_to_rec_bytes - 2]}) begin + if (need_to_rec_bytes == `UART_FIRST_PACKET_LEN && remain_packet_count == 16'h0) begin + remain_packet_count <= {7'h0, fw_file_size[31:7]} + 1'b1; + state <= S_SEND_ACK; + end else begin + remain_packet_count <= remain_packet_count - 1'b1; + state <= S_WRITE_MEM; + end + end else begin + state <= S_SEND_NAK; + end + end + S_WRITE_MEM: begin + if (write_mem_byte_index == (need_to_rec_bytes + 2)) begin + state <= S_SEND_ACK; + end else begin + mem_addr_o <= write_mem_addr; + mem_wdata_o <= write_mem_data; + mem_we_o <= 1'b1; + end + end + S_SEND_ACK: begin + mem_addr_o <= `UART_TX_REG; + mem_wdata_o <= `UART_RESP_ACK; + mem_we_o <= 1'b1; + if (remain_packet_count > 0) begin + state <= S_REC_REMAIN_PACKET; + end else begin + state <= S_REC_FIRST_PACKET; + end + end + S_SEND_NAK: begin + mem_addr_o <= `UART_TX_REG; + mem_wdata_o <= `UART_RESP_NAK; + mem_we_o <= 1'b1; + if (remain_packet_count > 0) begin + state <= S_REC_REMAIN_PACKET; + end else begin + state <= S_REC_FIRST_PACKET; + end + end + endcase + end + end + + // 数据包的大小 + always @ (posedge clk) begin + if (rst == 1'b0 || debug_en_i == 1'b0) begin + need_to_rec_bytes <= 8'h0; + end else begin + case (state) + S_REC_FIRST_PACKET: begin + need_to_rec_bytes <= `UART_FIRST_PACKET_LEN; + end + S_REC_REMAIN_PACKET: begin + need_to_rec_bytes <= `UART_REMAIN_PACKET_LEN; + end + endcase + end + end + + // 读接收到的串口数据 + always @ (posedge clk) begin + if (rst == 1'b0 || debug_en_i == 1'b0) begin + rec_bytes_index <= 8'h0; + end else begin + case (state) + S_GET_BYTE: begin + rx_data[rec_bytes_index] <= mem_rdata_i[7:0]; + rec_bytes_index <= rec_bytes_index + 1'b1; + end + S_REC_FIRST_PACKET: begin + rec_bytes_index <= 8'h0; + end + S_REC_REMAIN_PACKET: begin + rec_bytes_index <= 8'h0; + end + endcase + end + end + + // 固件大小 + always @ (posedge clk) begin + if (rst == 1'b0 || debug_en_i == 1'b0) begin + fw_file_size <= 32'h0; + end else begin + case (state) + S_CRC_START: begin + fw_file_size <= {rx_data[61], rx_data[62], rx_data[63], rx_data[64]}; + end + endcase + end + end + + // 烧写固件 + always @ (posedge clk) begin + if (rst == 1'b0 || debug_en_i == 1'b0) begin + write_mem_addr <= 32'h0; + write_mem_data <= 32'h0; + write_mem_byte_index <= 8'h0; + end else begin + case (state) + S_REC_FIRST_PACKET: begin + write_mem_addr <= `ROM_START_ADDR; + write_mem_data <= 32'h0; + write_mem_byte_index <= 8'h0; + end + S_CRC_END: begin + write_mem_data <= {rx_data[4], rx_data[3], rx_data[2], rx_data[1]}; + write_mem_byte_index <= 8'h5; + if (write_mem_addr > 0) + write_mem_addr <= write_mem_addr - 4; + end + S_WRITE_MEM: begin + write_mem_addr <= write_mem_addr + 4; + write_mem_data <= {rx_data[write_mem_byte_index + 3], rx_data[write_mem_byte_index + 2], rx_data[write_mem_byte_index + 1], rx_data[write_mem_byte_index]}; + write_mem_byte_index <= write_mem_byte_index + 4; + end + endcase + end + end + + // CRC计算 + always @ (posedge clk) begin + if (rst == 1'b0 || debug_en_i == 1'b0) begin + crc_result <= 16'h0; + crc_bit_index <= 4'h0; + crc_byte_index <= 8'h0; + end else begin + case (state) + S_CRC_START: begin + crc_result <= 16'hffff; + crc_bit_index <= 4'h0; + crc_byte_index <= 8'h1; + end + S_CRC_CALC: begin + if (crc_bit_index == 4'h0) begin + crc_result <= crc_result ^ rx_data[crc_byte_index]; + crc_byte_index <= crc_byte_index + 1'b1; + crc_bit_index <= crc_bit_index + 1'b1; + end else begin + if (crc_bit_index < 4'h9) begin + crc_bit_index <= crc_bit_index + 1'b1; + if (crc_result[0] == 1'b1) begin + crc_result <= {1'b0, crc_result[15:1]} ^ 16'ha001; + end else begin + crc_result <= {1'b0, crc_result[15:1]}; + end + end else begin + crc_bit_index <= 4'h0; + end + end + end + endcase + end + end + +endmodule diff --git a/rtl/soc/tinyriscv_soc_top.v b/rtl/soc/tinyriscv_soc_top.v index abe427b..3cc5109 100644 --- a/rtl/soc/tinyriscv_soc_top.v +++ b/rtl/soc/tinyriscv_soc_top.v @@ -27,8 +27,10 @@ module tinyriscv_soc_top( output wire halted_ind, // jtag是否已经halt住CPU信号 - output wire tx_pin, // UART发送引脚 - input wire rx_pin, // UART接收引脚 + input wire uart_debug_pin, // 串口下载使能引脚 + + output wire uart_tx_pin, // UART发送引脚 + input wire uart_rx_pin, // UART接收引脚 inout wire[1:0] gpio, // GPIO引脚 input wire jtag_TCK, // JTAG TCK引脚 @@ -68,6 +70,14 @@ module tinyriscv_soc_top( wire m2_req_i; wire m2_we_i; + // master 3 interface + wire[`MemAddrBus] m3_addr_i; + wire[`MemBus] m3_data_i; + wire[`MemBus] m3_data_o; + wire m3_ack_o; + wire m3_req_i; + wire m3_we_i; + // slave 0 interface wire[`MemAddrBus] s0_addr_o; wire[`MemBus] s0_data_o; @@ -229,8 +239,8 @@ module tinyriscv_soc_top( .data_i(s3_data_o), .data_o(s3_data_i), .ack_o(s3_ack_i), - .tx_pin(tx_pin), - .rx_pin(rx_pin) + .tx_pin(uart_tx_pin), + .rx_pin(uart_rx_pin) ); // io0 @@ -300,6 +310,14 @@ module tinyriscv_soc_top( .m2_req_i(m2_req_i), .m2_we_i(m2_we_i), + // master 3 interface + .m3_addr_i(m3_addr_i), + .m3_data_i(m3_data_i), + .m3_data_o(m3_data_o), + .m3_ack_o(m3_ack_o), + .m3_req_i(m3_req_i), + .m3_we_i(m3_we_i), + // slave 0 interface .s0_addr_o(s0_addr_o), .s0_data_o(s0_data_o), @@ -351,6 +369,18 @@ module tinyriscv_soc_top( .hold_flag_o(rib_hold_flag_o) ); + // 串口下载模块例化 + uart_debug u_uart_debug( + .clk(clk), + .rst(rst), + .debug_en_i(uart_debug_pin), + .req_o(m3_req_i), + .mem_we_o(m3_we_i), + .mem_addr_o(m3_addr_i), + .mem_wdata_o(m3_data_i), + .mem_rdata_i(m3_data_o) + ); + // jtag模块复位逻辑 always @ (posedge clk) begin if (rst == `RstEnable) begin