diff --git a/rtl/digital_thermometer.v b/rtl/digital_thermometer.v index e8785e2..a4c6742 100644 --- a/rtl/digital_thermometer.v +++ b/rtl/digital_thermometer.v @@ -1,7 +1,7 @@ `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Engineer: Yangshenbo -// +// version:V1.0 // Create Date: 2026/03/22 ////////////////////////////////////////////////////////////////////////////////// diff --git a/rtl/digital_top.v b/rtl/digital_top.v new file mode 100644 index 0000000..68bb407 --- /dev/null +++ b/rtl/digital_top.v @@ -0,0 +1,26 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 2026/04/03 22:01:15 +// Design Name: +// Module Name: digital_top +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +module digital_top( + + ); +endmodule diff --git a/rtl/systemregfile/my_systemregfile.v b/rtl/systemregfile/my_systemregfile.v new file mode 100644 index 0000000..4a21946 --- /dev/null +++ b/rtl/systemregfile/my_systemregfile.v @@ -0,0 +1,102 @@ +//+FHDR-------------------------------------------------------------------------------------------------------- +// 增加一个新寄存器: + +// SECTION A: 添加 localparam ADDR_NEW = 16'hXX;。 + +// SECTION B: 声明 wire sel_new, we_new, [31:0] reg_new;。 + +// SECTION C: 增加译码逻辑:assign sel_new = (reg_idx == ADDR_NEW >> 2);。 + +// SECTION D: 调用底层库,例如 sirv_gnrl_dfflr #(32) new_dff (we_new, wrdata, reg_new, clk, rst_n);。 + +// SECTION F: 在 always 块中加入 else if (sel_new) rddata_reg = reg_new;。 + +// SECTION G: 将 reg_new 映射给模块的输出端口。 +//-FHDR-------------------------------------------------------------------------------------------------------- + +module system_regfile # ( + parameter CHIPCODE = 32'hDA400801, + parameter MFDATE = 32'h20260510 +)( + // [BLOCK 0] 系统与总线接口 + input clk, // 时钟 + input rst_n, // 异步复位 (低有效) + input [31:0] wrdata, // 总线写数据 + input wren, // 写使能 + input [24:0] rwaddr, // 地址 (Byte Address) + input rden, // 读使能 + output [31:0] rddata // 总线读数据 + +); + +// ============================================================================= +// [SECTION A] 地址偏移定义 (Localparams) +// ============================================================================= + localparam TESTR = 16'h00, DATER = 16'h04; + + +// ============================================================================= +// [SECTION B] 内部连线声明 (Wires) +// ============================================================================= + +// 寄存器选择信号 (Enable Wires) + wire sel_testr, sel_dater; + + +// 写使能信号 (Write Enable Wires) + wire we_testr, we_dater; + + +// 寄存器存储连线 (Storage Wires) + wire [31:0] testr, dater; + +// ============================================================================= +// [SECTION C] 译码逻辑 (Decoding) +// ============================================================================= + assign sel_testr = (rwaddr[15:0] == TESTR ); + assign sel_dater = (rwaddr[15:0] == DATER ); + +// 写使能分配 +assign we_testr = sel_testr & wren; +assign we_dater = sel_dater & wren; + + +// ============================================================================= +// [SECTION D] 寄存器实例化 (Storage Implementation) +// ============================================================================= + +// --- 通用与测试寄存器 --- +sirv_gnrl_dfflrd #(32) testr_dff (32'h01234567, we_testr, wrdata[31:0], testr, clk, rst_n); +sirv_gnrl_dfflrd #(32) sfrtr_dff (32'd20270403, we_dater, wrdata[31:0], dater, clk, rst_n); + + + +// ============================================================================= +// [SECTION E] 特殊业务逻辑 (Business Logic) +// ============================================================================= + +// LVDS 实时状态寄存器 +// sirv_gnrl_dffr #(8) lvdssr_inst ({link_down, train_ready, crc_error_r, phase_adj_req_r, phase_tap[2:0], prefilling}, lvdssr, clk, rst_n); + +// ============================================================================= +// [SECTION F] 读回逻辑 (Readback Mux) +// ============================================================================= +reg [31:0] rddata_reg; +always @(*) begin + rddata_reg = 32'b0; + if (sel_testr) rddata_reg = testr; + else if (sel_dater) rddata_reg = dater; +end + + sirv_gnrl_dfflr #(32) rddata_out_dff (rden, rddata_reg, rddata, clk, rst_n); + +// ============================================================================= +// [SECTION G] 输出映射 (Output Assignments) +// ============================================================================= +// assign sys_soft_rstn = sys_soft_rstn_r; +// assign sync_oen = syncr[18]; +// assign nco_clr = ncoctrlr[2]; +// assign nco_en = ncoctrlr[1] & doselr[2]; +// assign p2a_en = ncoctrlr[0] & doselr[2]; + +endmodule \ No newline at end of file diff --git a/rtl/systemregfile/sirv_gnrl_dffs.v b/rtl/systemregfile/sirv_gnrl_dffs.v new file mode 100644 index 0000000..6526cd4 --- /dev/null +++ b/rtl/systemregfile/sirv_gnrl_dffs.v @@ -0,0 +1,342 @@ + /* + Copyright 2018-2020 Nuclei System Technology, Inc. + + 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. + */ + + + +//===================================================================== +// +// Designer : Bob Hu +// +// Description: +// All of the general DFF and Latch modules +// +// ==================================================================== + +// + + +// +// =========================================================================== +// +// Description: +// Verilog module sirv_gnrl DFF with Load-enable and Reset +// Default reset value is 1 +// +// =========================================================================== +`define DISABLE_SV_ASSERTION +`define dly #0.2 +module sirv_gnrl_dfflrs # ( + parameter DW = 32 +) ( + + input lden, + input [DW-1:0] dnxt, + output [DW-1:0] qout, + + input clk, + input rst_n +); + +reg [DW-1:0] qout_r; + +always @(posedge clk or negedge rst_n) +begin : DFFLRS_PROC + if (rst_n == 1'b0) + qout_r <= {DW{1'b1}}; + else if (lden == 1'b1) + qout_r <= `dly dnxt; +end + +assign qout = qout_r; + +`ifndef FPGA_SOURCE//{ +`ifndef DISABLE_SV_ASSERTION//{ +//synopsys translate_off +sirv_gnrl_xchecker # ( + .DW(1) +) sirv_gnrl_xchecker( + .i_dat(lden), + .clk (clk) +); +//synopsys translate_on +`endif//} +`endif//} + + +endmodule +// =========================================================================== +// +// Description: +// Verilog module sirv_gnrl DFF with Load-enable and Reset +// Default reset value is 0 +// +// =========================================================================== + +module sirv_gnrl_dfflr # ( + parameter DW = 32 +) ( + + input lden, + input [DW-1:0] dnxt, + output [DW-1:0] qout, + + input clk, + input rst_n +); + +reg [DW-1:0] qout_r; + +always @(posedge clk or negedge rst_n) +begin : DFFLR_PROC + if (rst_n == 1'b0) + qout_r <= {DW{1'b0}}; + else if (lden == 1'b1) + qout_r <= `dly dnxt; +end + +assign qout = qout_r; + +`ifndef FPGA_SOURCE//{ +`ifndef DISABLE_SV_ASSERTION//{ +//synopsys translate_off +sirv_gnrl_xchecker # ( + .DW(1) +) sirv_gnrl_xchecker( + .i_dat(lden), + .clk (clk) +); +//synopsys translate_on +`endif//} +`endif//} + + +endmodule + +// =========================================================================== +// +// Description: +// Verilog module sirv_gnrl DFF with Load-enable and Reset +// Default reset value is input +// +// =========================================================================== + +module sirv_gnrl_dfflrd # ( + parameter DW = 32 +) ( + input [DW-1:0] init, + input lden, + input [DW-1:0] dnxt, + output [DW-1:0] qout, + + input clk, + input rst_n +); + +reg [DW-1:0] qout_r; + +always @(posedge clk or negedge rst_n) +begin : DFFLR_PROC + if (rst_n == 1'b0) + qout_r <= init; + else if (lden == 1'b1) + qout_r <= `dly dnxt; +end + +assign qout = qout_r; + +`ifndef FPGA_SOURCE//{ +`ifndef DISABLE_SV_ASSERTION//{ +//synopsys translate_off +sirv_gnrl_xchecker # ( + .DW(1) +) sirv_gnrl_xchecker( + .i_dat(lden), + .clk (clk) +); +//synopsys translate_on +`endif//} +`endif//} + + +endmodule + +// =========================================================================== +// +// Description: +// Verilog module sirv_gnrl DFF with Load-enable, no reset +// +// =========================================================================== + +module sirv_gnrl_dffl # ( + parameter DW = 32 +) ( + + input lden, + input [DW-1:0] dnxt, + output [DW-1:0] qout, + + input clk +); + +reg [DW-1:0] qout_r; + +always @(posedge clk) +begin : DFFL_PROC + if (lden == 1'b1) + qout_r <= `dly dnxt; +end + +assign qout = qout_r; + +`ifndef FPGA_SOURCE//{ +`ifndef DISABLE_SV_ASSERTION//{ +//synopsys translate_off +sirv_gnrl_xchecker # ( + .DW(1) +) sirv_gnrl_xchecker( + .i_dat(lden), + .clk (clk) +); +//synopsys translate_on +`endif//} +`endif//} + + +endmodule +// =========================================================================== +// +// Description: +// Verilog module sirv_gnrl DFF with Reset, no load-enable +// Default reset value is 1 +// +// =========================================================================== + +module sirv_gnrl_dffrs # ( + parameter DW = 32 +) ( + + input [DW-1:0] dnxt, + output [DW-1:0] qout, + + input clk, + input rst_n +); + +reg [DW-1:0] qout_r; + +always @(posedge clk or negedge rst_n) +begin : DFFRS_PROC + if (rst_n == 1'b0) + qout_r <= {DW{1'b1}}; + else + qout_r <= `dly dnxt; +end + +assign qout = qout_r; + +endmodule +// =========================================================================== +// +// Description: +// Verilog module sirv_gnrl DFF with Reset, no load-enable +// Default reset value is 0 +// +// =========================================================================== + +module sirv_gnrl_dffr # ( + parameter DW = 32 +) ( + + input [DW-1:0] dnxt, + output [DW-1:0] qout, + + input clk, + input rst_n +); + +reg [DW-1:0] qout_r; + +always @(posedge clk or negedge rst_n) +begin : DFFR_PROC + if (rst_n == 1'b0) + qout_r <= {DW{1'b0}}; + else + qout_r <= `dly dnxt; +end + +assign qout = qout_r; + +endmodule +// =========================================================================== +// +// Description: +// Verilog module for general latch +// +// =========================================================================== + +module sirv_gnrl_ltch # ( + parameter DW = 32 +) ( + + //input test_mode, + input lden, + input [DW-1:0] dnxt, + output [DW-1:0] qout +); + +reg [DW-1:0] qout_r; + +always @ * +begin : LTCH_PROC + if (lden == 1'b1) + qout_r <= dnxt; +end + +//assign qout = test_mode ? dnxt : qout_r; +assign qout = qout_r; + +`ifndef FPGA_SOURCE//{ +`ifndef DISABLE_SV_ASSERTION//{ +//synopsys translate_off +always_comb +begin + CHECK_THE_X_VALUE: + assert (lden !== 1'bx) + else $fatal ("\n Error: Oops, detected a X value!!! This should never happen. \n"); +end + +//synopsys translate_on +`endif//} +`endif//} + + +endmodule + +// module sirv_gnrl_edffr #(parameter type T = logic) ( +// input T dnxt, +// output T qout, +// input clk, rst_n +// ); + +// T qout_r; + +// always_ff @(posedge clk or negedge rst_n) begin +// if (!rst_n) qout_r <= T'('0); +// else qout_r <= `dly dnxt; +// end +// assign qout = qout_r; +// endmodule + diff --git a/rtl/uart_byte_rx.v b/rtl/uart_byte_rx.v new file mode 100644 index 0000000..6ecf557 --- /dev/null +++ b/rtl/uart_byte_rx.v @@ -0,0 +1,111 @@ +module uart_byte_rx #( + parameter CLOCK_FREQ = 50_000_000, + parameter BAUD = 9600 +) +( + Clk, + Reset_n, + uart_rx, + Rx_Done, + Rx_Data +); + + input Clk; + input Reset_n; + input uart_rx; + output reg Rx_Done; + output reg[7:0]Rx_Data; + + + parameter MCNT_BAUD = CLOCK_FREQ / BAUD - 1; + + reg [7:0]r_Rx_Data; + + reg [29:0]baud_div_cnt; + reg en_baud_cnt; + reg [3:0]bit_cnt; + + wire w_Rx_Done; + wire nedge_uart_rx; + + reg r_uart_rx; + + reg dff0_uart_rx,dff1_uart_rx; +//ʼ߼ + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + baud_div_cnt <= 0; + else if(en_baud_cnt)begin + if(baud_div_cnt == MCNT_BAUD) + baud_div_cnt <= 0; + else + baud_div_cnt <= baud_div_cnt + 1'd1; + end + else + baud_div_cnt <= 0; + + +//UART źűؼ߼ + always@(posedge Clk) + dff0_uart_rx <= uart_rx; + + always@(posedge Clk) + dff1_uart_rx <= dff0_uart_rx; + + always@(posedge Clk) + r_uart_rx <= dff1_uart_rx; + + assign nedge_uart_rx = (dff1_uart_rx == 0) && (r_uart_rx == 1); + +//ʼʹ߼ + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + en_baud_cnt <= 0; + else if(nedge_uart_rx) + en_baud_cnt <= 1; + else if((baud_div_cnt == MCNT_BAUD/2) && (bit_cnt == 0) && (dff1_uart_rx == 1)) + en_baud_cnt <= 0; + else if((baud_div_cnt == MCNT_BAUD/2) && (bit_cnt == 9)) + en_baud_cnt <= 0; + + +//λ߼ + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + bit_cnt <= 0; + else if((bit_cnt == 9) && (baud_div_cnt == MCNT_BAUD/2)) + bit_cnt <= 0; + else if(baud_div_cnt == MCNT_BAUD) + bit_cnt <= bit_cnt + 1'd1; + +//λ߼ + + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + r_Rx_Data <= 8'd0; + else if(baud_div_cnt == MCNT_BAUD/2)begin + case(bit_cnt) + 1:r_Rx_Data[0] <= dff1_uart_rx; + 2:r_Rx_Data[1] <= dff1_uart_rx; + 3:r_Rx_Data[2] <= dff1_uart_rx; + 4:r_Rx_Data[3] <= dff1_uart_rx; + 5:r_Rx_Data[4] <= dff1_uart_rx; + 6:r_Rx_Data[5] <= dff1_uart_rx; + 7:r_Rx_Data[6] <= dff1_uart_rx; + 8:r_Rx_Data[7] <= dff1_uart_rx; + default: r_Rx_Data <= r_Rx_Data; + endcase + end + +//ɱ־ź + assign w_Rx_Done = (baud_div_cnt == MCNT_BAUD/2) && (bit_cnt == 9); + + always@(posedge Clk) + Rx_Done <= w_Rx_Done; + + always@(posedge Clk) + if(w_Rx_Done) + Rx_Data <= r_Rx_Data; + + +endmodule diff --git a/rtl/uart_byte_tx.v b/rtl/uart_byte_tx.v new file mode 100644 index 0000000..d504445 --- /dev/null +++ b/rtl/uart_byte_tx.v @@ -0,0 +1,110 @@ +module uart_byte_tx #( + parameter BAUD = 9600, + parameter CLOCK_FREQ = 50_000_000 +) +( + Clk, + Reset_n, + Send_Go, + Data, + uart_tx, + Tx_Done +); + +// + + input Clk; + input Reset_n; + input Send_Go; + input [7:0]Data; + output reg uart_tx; + output reg Tx_Done; + + + + parameter MCNT_BAUD = CLOCK_FREQ / BAUD - 1; + + parameter MCNT_BIT = 10-1; + + reg [29:0]baud_div_cnt; + reg en_baud_cnt; + reg [3:0]bit_cnt; + reg [7:0]r_Data; + + wire w_Tx_Done; + +//ʼ 1/9600 *1000000000 / 20 - 1 + + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + baud_div_cnt <= 0; + else if(en_baud_cnt)begin + if(baud_div_cnt == MCNT_BAUD) + baud_div_cnt <= 0; + else + baud_div_cnt <= baud_div_cnt + 1'd1; + end + else + baud_div_cnt <= 0; + + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + en_baud_cnt <= 0; + else if(Send_Go) + en_baud_cnt <= 1; + else if(w_Tx_Done) + en_baud_cnt <= 0; + +//λ + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + bit_cnt <= 0; + else if(baud_div_cnt == MCNT_BAUD)begin + if(bit_cnt == MCNT_BIT) + bit_cnt <= 0; + else + bit_cnt <= bit_cnt + 1'd1; + end + + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + r_Data <= 0; + else if(Send_Go) + r_Data <= Data; + else + r_Data <= r_Data; + +// always@(posedge Clk) +// if(Send_Go) +// r_Data <= Data; + + + +//λ߼ + always@(posedge Clk or negedge Reset_n) + if(!Reset_n) + uart_tx <= 1'd1; + else if(en_baud_cnt == 0) + uart_tx <= 1'd1; + else begin + case(bit_cnt) + 0:uart_tx <= 1'd0; + 1:uart_tx <= r_Data[0]; + 2:uart_tx <= r_Data[1]; + 3:uart_tx <= r_Data[2]; + 4:uart_tx <= r_Data[3]; + 5:uart_tx <= r_Data[4]; + 6:uart_tx <= r_Data[5]; + 7:uart_tx <= r_Data[6]; + 8:uart_tx <= r_Data[7]; + 9:uart_tx <= 1'd1; + default:uart_tx <= uart_tx; + endcase + end + + assign w_Tx_Done = ((bit_cnt == 9) && (baud_div_cnt == MCNT_BAUD)); + + always@(posedge Clk) + Tx_Done <= w_Tx_Done; + +endmodule diff --git a/rtl/uart_ctrl_sysreg.v b/rtl/uart_ctrl_sysreg.v new file mode 100644 index 0000000..cf80e30 --- /dev/null +++ b/rtl/uart_ctrl_sysreg.v @@ -0,0 +1,121 @@ +`timescale 1ns / 1ps + +module uart_ctrl_sysreg #( + parameter BAUD = 115200, + parameter CLOCK_FREQ = 50_000_000 +)( + input clk + ,input rst_n + // 串口接口 + ,input uart_rx + ,output uart_tx + //5口 + ,output reg [31:0] o_wrdata //write data to sram + ,output reg [24:0] o_addr //sram address + ,output reg o_wren //write enable sram + ,output reg o_rden //rden enable sram + ,input [31:0] i_rddata //read data from sram +); + + // --- uart_top --- + wire [31:0] uart_rx_data; + wire uart_rx_done; + reg [31:0] uart_tx_data; + reg uart_tx_go; + wire uart_tx_done; + uart_top_32bit #( + .BAUD(BAUD), + .CLOCK_FREQ(CLOCK_FREQ) + ) uart_32bit_inst ( + .Clk(clk), .Reset_n(rst_n), + .Send_Go32(uart_tx_go), .Tx_Data32(uart_tx_data), .Tx_Done32(uart_tx_done), + .uart_tx(uart_tx), .uart_rx(uart_rx), + .Rx_Done32(uart_rx_done), .Rx_Data32(uart_rx_data) + ); + + + // 协议解析寄存器 + reg [63:0] cmd_reg; + reg [31:0]wr_data_buff; + reg [19:0] data_bytes_len; + + + // 状态机定义 + reg [2:0] state; + localparam S_IDLE = 3'd0, + S_RX_CMD_L = 3'd1, + S_PARSE = 3'd2, + S_RD_DATA = 3'd3, + S_WR_DATA = 3'd4; + + + + + always @(posedge clk or negedge rst_n) begin + if(!rst_n) begin + state <= 0; + cmd_reg <= 0; + o_wrdata <= 0; + o_wren <= 0; + o_rden <= 0; + uart_tx_go <= 1'b0; + uart_tx_data <= 1'b0; + end + else begin + case(state) + S_IDLE : begin //0 + uart_tx_go <= 1'b0; + if(uart_rx_done) begin + cmd_reg[63:32] <= uart_rx_data; + state <= S_RX_CMD_L; + end + end + S_RX_CMD_L : begin //1 + if(uart_rx_done)begin + cmd_reg[31:0] <= uart_rx_data; + state <= S_PARSE; + end + end + S_PARSE : begin //2 + o_addr <= cmd_reg[56:32]; + data_bytes_len <= cmd_reg[19:0]; + if(cmd_reg[63] == 1'b1) begin //读指令 + o_rden <= 1'b1; + state <= S_RD_DATA; + end + else begin //写指令 + state <= S_WR_DATA; + end + end + S_RD_DATA :begin //3 + o_rden <= 1'b0; + uart_tx_data <= i_rddata; + uart_tx_go <= 1'b1; + state <= S_IDLE; + end + S_WR_DATA : begin //4 + o_wren <= 1'b0; + if(data_bytes_len != 0)begin + if(uart_rx_done) begin + o_wrdata <= uart_rx_data; + o_wren <= 1'b1; + data_bytes_len <= data_bytes_len - 20'd4; + end + end + else begin + state <= S_IDLE; + end + + end + + + endcase + end + + end + + + + + +endmodule \ No newline at end of file diff --git a/rtl/uart_top_32bit.v b/rtl/uart_top_32bit.v new file mode 100644 index 0000000..c3d8594 --- /dev/null +++ b/rtl/uart_top_32bit.v @@ -0,0 +1,163 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: yangshenbo +// +// Create Date: 2026/03/31 10:53:24 +// Design Name: +// Module Name: uart_top_32bit +// +////////////////////////////////////////////////////////////////////////////////// +module uart_top_32bit #( + parameter BAUD = 9600, + parameter CLOCK_FREQ = 50_000_000 +) +( + input Clk, + input Reset_n, + + // 32位发送接口 + input Send_Go32, // 32位发送启动脉冲 + input [31:0] Tx_Data32, // 待发送的32位数据 + output Tx_Done32, // 32位发送完成标志 + output uart_tx, // 物理引脚TX + + // 32位接收接口 + input uart_rx, // 物理引脚RX + output reg Rx_Done32, // 32位接收完成标志 + output reg [31:0] Rx_Data32 // 接收到的32位数据 +); + + // --- 内部连线 --- + wire byte_tx_go; + wire [7:0] byte_tx_data; + wire byte_tx_done; + + wire byte_rx_done; + wire [7:0] byte_rx_data; + + // ============================================================ + // 1. 发送逻辑控制 (32-bit to 4x8-bit) + // ============================================================ + reg [3:0] tx_state; + reg [31:0] tx_data_buffer; + reg byte_tx_go_reg; + reg [7:0] byte_tx_data_reg; + + assign byte_tx_go = byte_tx_go_reg; + assign byte_tx_data = byte_tx_data_reg; + + always @(posedge Clk or negedge Reset_n) begin + if (!Reset_n) begin + tx_state <= 0; + byte_tx_go_reg <= 0; + tx_data_buffer <= 0; + end else begin + case (tx_state) + 0: begin // 等待发送触发 + if (Send_Go32) begin + tx_data_buffer <= Tx_Data32; + tx_state <= 1; + end + end + + 1, 2, 3, 4: begin // 依次发送字节0, 1, 2, 3 + byte_tx_data_reg <= tx_data_buffer[7:0]; // 优先发低位(小端) + byte_tx_go_reg <= 1; + tx_state <= tx_state + 4; // 跳转到等待状态 (利用加法偏移) + end + + // 状态 5, 6, 7, 8 用于等待 byte_tx_done + 5, 6, 7, 8: begin + byte_tx_go_reg <= 0; + if (byte_tx_done) begin + tx_data_buffer <= tx_data_buffer >> 8; // 移位,准备下一字节 + if (tx_state == 8) tx_state <= 0; // 发完4个 + else tx_state <= tx_state - 3; // 回到下一个发送状态 + end + end + endcase + end + end + + assign Tx_Done32 = (tx_state == 8 && byte_tx_done); + + // ============================================================ + // 2. 接收逻辑控制 (4x8-bit to 32-bit) + // ============================================================ + reg [1:0] rx_cnt; + reg [31:0] rx_data_buffer; + reg rx_done32_reg; + + always @(posedge Clk or negedge Reset_n) begin + if (!Reset_n) begin + rx_cnt <= 0; + rx_data_buffer <= 0; + rx_done32_reg <= 0; + end else begin + rx_done32_reg <= 0; + if (byte_rx_done) begin + // 拼接数据 (小端模式) + case(rx_cnt) + 0: rx_data_buffer[7:0] <= byte_rx_data; + 1: rx_data_buffer[15:8] <= byte_rx_data; + 2: rx_data_buffer[23:16] <= byte_rx_data; + 3: rx_data_buffer[31:24] <= byte_rx_data; + endcase + + if (rx_cnt == 3) begin + rx_cnt <= 0; + rx_done32_reg <= 1; + end else begin + rx_cnt <= rx_cnt + 1; + end + end + end + end + + + always @(posedge Clk or Reset_n) begin + if(!Reset_n) begin + Rx_Data32 <= 1'b0; + Rx_Done32 <= 1'b0; + end + else if(rx_done32_reg)begin + Rx_Data32 <= rx_data_buffer; + Rx_Done32 <= rx_done32_reg; + end + else begin + Rx_Data32 <= Rx_Data32; + Rx_Done32 <= 0; + end + end + + // ============================================================ + // 3. 模块实例化 + // ============================================================ + + // 实例化发送字节模块 + uart_byte_tx #( + .BAUD(BAUD), + .CLOCK_FREQ(CLOCK_FREQ) + ) u_uart_byte_tx ( + .Clk(Clk), + .Reset_n(Reset_n), + .Send_Go(byte_tx_go), + .Data(byte_tx_data), + .uart_tx(uart_tx), + .Tx_Done(byte_tx_done) + ); + + // 实例化接收字节模块 + uart_byte_rx #( + .BAUD(BAUD), + .CLOCK_FREQ(CLOCK_FREQ) + ) u_uart_byte_rx ( + .Clk(Clk), + .Reset_n(Reset_n), + .uart_rx(uart_rx), + .Rx_Done(byte_rx_done), + .Rx_Data(byte_rx_data) + ); + +endmodule diff --git a/tb/tb_uart_ctrl_sysreg.v b/tb/tb_uart_ctrl_sysreg.v new file mode 100644 index 0000000..fcdccb0 --- /dev/null +++ b/tb/tb_uart_ctrl_sysreg.v @@ -0,0 +1,153 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 2026/03/31 13:01:26 +// Design Name: +// Module Name: tb_uart_ctrl_sysreg +// Project Name: +// Target Devices: +// Tool Versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// + + +`timescale 1ns / 1ps + +module tb_uart_ctrl_sysreg(); + + // --- 参数与信号 --- + parameter CLK_PERIOD = 20; // 50MHz + parameter BAUD = 115200; // 提高波特率加快仿真 + localparam BIT_TIME = 1_000_000_000 / BAUD; // 计算1比特持续的ns数 + +// 端口信号 +reg clk; +reg rst_n; +reg uart_rx; // 发给 DUT 的 UART 数据 +wire uart_tx; // DUT 回发数据 +wire [31:0] o_wrdata; // DUT -> SRAM 写数据 +wire [24:0] o_addr; // DUT -> SRAM 地址 +wire o_wren; // 写使能 +wire o_rden; // 读使能 +reg [31:0] i_rddata; // SRAM -> DUT 读数据 + +// 例化待测模块 (DUT) +uart_ctrl_sysreg #( + .BAUD (BAUD), + .CLOCK_FREQ (50_000_000) +) u_dut ( + .clk (clk), + .rst_n (rst_n), + .uart_rx (uart_rx), + .uart_tx (uart_tx), + .o_wrdata (o_wrdata), + .o_addr (o_addr), + .o_wren (o_wren), + .o_rden (o_rden), + .i_rddata (i_rddata) +); + // --- 时钟产生 --- + initial clk = 0; + always #(CLK_PERIOD/2) clk = ~clk; + + // ============================================================ + // 模拟上位机:字节发送任务 (Serial UART TX) + // ============================================================ + task send_byte; + input [7:0] data; + integer i; + begin + uart_rx = 0; // 起始位 + #(BIT_TIME); + for (i = 0; i < 8; i = i + 1) begin + uart_rx = data[i]; // 数据位 (LSB first) + #(BIT_TIME); + end + uart_rx = 1; // 停止位 + #(BIT_TIME); + #(BIT_TIME); // 字节间隙 + end + endtask + + // 发送 32 位数据 (拆分为 4 个字节) + task send_32bit; + input [31:0] data; + begin + // 注意:这里发送顺序要和你的串口接收模块端序一致 + // 假设小端发送:先发 [7:0] + send_byte(data[7:0]); + send_byte(data[15:8]); + send_byte(data[23:16]); + send_byte(data[31:24]); + end + endtask + + // ============================================================ + // 主测试流程 + // ============================================================ + integer file_ptr; + integer status; + reg [63:0] temp_cmd; + reg [31:0] temp_data; + +initial begin + // 初始化 + rst_n = 0; + uart_rx = 1; + #(CLK_PERIOD * 10); + rst_n = 1; + #(CLK_PERIOD * 100); + + // 打开测试文件 + file_ptr = $fopen("D:/shortname/thermometer/try/test_cases.txt", "r"); + if (file_ptr == 0) begin + $display("====Error: can not open test_cases.txt file!==="); + $finish; + end + + $display("======= Begin Send Case ======="); + + while (!$feof(file_ptr)) begin + // 尝试读取一行(先尝试按 64 位 CMD 读取) + status = $fscanf(file_ptr, "%h\n", temp_cmd); + + if (status == 1) begin + if (temp_cmd > 64'hFFFF_FFFF) begin + // 如果读到的是 64 位,认为是 CMD + $display("[%t] Send command frame: 0x%h", $time, temp_cmd); + send_32bit(temp_cmd[63:32]); // 先发高32位 + send_32bit(temp_cmd[31:0]); // 再发低32位 + end else begin + // 如果读到的是 32 位,认为是 DATA + $display("[%t] Send data stream: 0x%h", $time, temp_cmd[31:0]); + send_32bit(temp_cmd[31:0]); + end + end + #(BIT_TIME * 20); // 指令/数据组之间的间隔 + end + + $display("======= All Cases Sent ======="); + $fclose(file_ptr); + + #(BIT_TIME * 200); + $stop; + end + + // ============================================================ + // 监听回传:捕捉 FPGA 返回的读数据 + // ============================================================ + // 简单起见,这里直接观察波形,或者你可以写一个串口接收任务 + initial begin + $display("[%t] 监听器已启动...", $time); + end + +endmodule diff --git a/tb/tb_uart_top_32bit.v b/tb/tb_uart_top_32bit.v new file mode 100644 index 0000000..be1d2f9 --- /dev/null +++ b/tb/tb_uart_top_32bit.v @@ -0,0 +1,113 @@ +`timescale 1ns / 1ps + +module tb_uart_top_32bit(); + + // --- 参数定义 --- + parameter CLK_PERIOD = 20; + parameter BAUD = 115200; // 提高波特率可以加快仿真速度 + parameter CLOCK_FREQ = 50_000_000; + + // --- 信号声明 --- + reg Clk; + reg Reset_n; + reg Send_Go32; + reg [31:0] Tx_Data32; + + wire uart_tx; + wire uart_rx; + wire Tx_Done32; + wire Rx_Done32; + wire [31:0] Rx_Data32; + + // --- 实例化 DUT --- + uart_top_32bit #( + .BAUD(BAUD), + .CLOCK_FREQ(CLOCK_FREQ) + ) dut ( + .Clk(Clk), + .Reset_n(Reset_n), + .Send_Go32(Send_Go32), + .Tx_Data32(Tx_Data32), + .Tx_Done32(Tx_Done32), + .uart_tx(uart_tx), + .uart_rx(uart_rx), + .Rx_Done32(Rx_Done32), + .Rx_Data32(Rx_Data32) + ); + + // 构造回环 + assign uart_rx = uart_tx; + + // 时钟产生 + initial Clk = 0; + always #(CLK_PERIOD/2) Clk = ~Clk; + + // ============================================================ + // 发送并校验的任务 (Task) + // ============================================================ + task send_and_check; + input [31:0] data; + begin + Tx_Data32 = data; + Send_Go32 = 1; + #(CLK_PERIOD); + Send_Go32 = 0; + + // 等待发送和接收全部完成 + fork + wait(Rx_Done32); + wait(Tx_Done32); + join + + #(CLK_PERIOD * 10); // 留一点余量 + + if (Rx_Data32 === data) + $display("[PASS] 发送: 0x%h | 接收: 0x%h", data, Rx_Data32); + else + $display("[FAIL] 发送: 0x%h | 接收: 0x%h !!! 错误 !!!", data, Rx_Data32); + + #(CLK_PERIOD * 100); // 两次发送间的间隔 + end + endtask + + // ============================================================ + // 测试流程 + // ============================================================ + integer i; + initial begin + // 初始化 + Reset_n = 0; + Send_Go32 = 0; + Tx_Data32 = 0; + + // 复位 + #(CLK_PERIOD * 10); + Reset_n = 1; + #(CLK_PERIOD * 10); + + $display("======= 开始 32位串口回环测试 ======="); + + // 1. 基础边界测试 + send_and_check(32'h0000_0000); + send_and_check(32'hFFFF_FFFF); + + // 2. 经典交替位测试 (检查串扰和采样) + send_and_check(32'hAAAA_AAAA); + send_and_check(32'h5555_5555); + + // 3. 随机/特殊数据测试 + send_and_check(32'h1234_5678); + send_and_check(32'h8765_4321); + send_and_check(32'hDEAD_BEEF); + + // 4. 循环自动测试 (测试 5 组递增数据) + for (i = 0; i < 5; i = i + 1) begin + send_and_check(32'h2024_0000 + i); + end + + $display("======= 所有测试用例执行完毕 ======="); + #(CLK_PERIOD * 200); + $stop; + end + +endmodule \ No newline at end of file diff --git a/tb/uart_byte_rx_tb.v b/tb/uart_byte_rx_tb.v new file mode 100644 index 0000000..0024e41 --- /dev/null +++ b/tb/uart_byte_rx_tb.v @@ -0,0 +1,89 @@ +`timescale 1ns / 1ps + +module uart_byte_rx_tb(); + + reg Clk; + reg Reset_n; + reg uart_rx; + wire Rx_Done; + wire [7:0]Rx_Data; + + uart_byte_rx uart_byte_rx( + .Clk(Clk), + .Reset_n(Reset_n), + .uart_rx(uart_rx), + .Rx_Done(Rx_Done), + .Rx_Data(Rx_Data) + ); + + + initial Clk = 1; + always #10 Clk= ~Clk; + + + initial begin + Reset_n = 0; + uart_rx = 1; + #201; + Reset_n = 1; + #200; + + //8'b0101_0101 + uart_rx = 0; #(5208*20); //ʼλ + uart_rx = 1; #(5208*20); //bit0 + uart_rx = 0; #(5208*20); //bit1 + uart_rx = 1; #(5208*20); //bit2 + uart_rx = 0; #(5208*20); //bit3 + uart_rx = 1; #(5208*20); //bit4 + uart_rx = 0; #(5208*20); //bit5 + uart_rx = 1; #(5208*20); //bit6 + uart_rx = 0; #(5208*20); //bit7 + uart_rx = 1; #(5208*20); //ֹͣλ + #(5208*20*10); + + //8'b1010_1010 + uart_rx = 0; #(5208*20); //ʼλ + uart_rx = 0; #(5208*20); //bit0 + uart_rx = 1; #(5208*20); //bit1 + uart_rx = 0; #(5208*20); //bit2 + uart_rx = 1; #(5208*20); //bit3 + uart_rx = 0; #(5208*20); //bit4 + uart_rx = 1; #(5208*20); //bit5 + uart_rx = 0; #(5208*20); //bit6 + uart_rx = 1; #(5208*20); //bit7 + uart_rx = 1; #(5208*20); //ֹͣλ + #(5208*20*10); + + //8'b1111_0000 + uart_rx = 0; #(5208*20); //ʼλ + uart_rx = 0; #(5208*20); //bit0 + uart_rx = 0; #(5208*20); //bit1 + uart_rx = 0; #(5208*20); //bit2 + uart_rx = 0; #(5208*20); //bit3 + uart_rx = 1; #(5208*20); //bit4 + uart_rx = 1; #(5208*20); //bit5 + uart_rx = 1; #(5208*20); //bit6 + uart_rx = 1; #(5208*20); //bit7 + uart_rx = 1; #(5208*20); //ֹͣλ + #(5208*20*10); + + //8'b0000_1111 + uart_rx = 0; #(5208*20); //ʼλ + uart_rx = 1; #(5208*20); //bit0 + uart_rx = 1; #(5208*20); //bit1 + uart_rx = 1; #(5208*20); //bit2 + uart_rx = 1; #(5208*20); //bit3 + uart_rx = 0; #(5208*20); //bit4 + uart_rx = 0; #(5208*20); //bit5 + uart_rx = 0; #(5208*20); //bit6 + uart_rx = 0; #(5208*20); //bit7 + uart_rx = 1; #(5208*20); //ֹͣλ + #(5208*20*10); + $stop; + + end + + + + +endmodule diff --git a/tb/uart_byte_tx_tb.v b/tb/uart_byte_tx_tb.v new file mode 100644 index 0000000..232c074 --- /dev/null +++ b/tb/uart_byte_tx_tb.v @@ -0,0 +1,44 @@ +`timescale 1ns / 1ps + +module uart_byte_tx_tb(); + + reg Clk; + reg Reset_n; + reg [7:0]Data; + reg Send_Go; + wire uart_tx; + wire Tx_Done; + + uart_byte_tx uart_byte_tx( + .Clk(Clk), + .Reset_n(Reset_n), + .Data(Data), + .uart_tx(uart_tx), + .Send_Go(Send_Go), + .Tx_Done(Tx_Done) + ); +// defparam uart_byte_tx.MCNT_DLY = 50_000_0 - 1; + + initial Clk = 1; + always #10 Clk = ~Clk; + + initial begin + Reset_n = 0; + #200; + Reset_n = 1; + Data = 8'b0101_0101; + Send_Go = 1 ; + #20; + Send_Go = 0; + #20; + #30000000; + Data = 8'b1010_1010; + Send_Go = 1 ; + #20; + Send_Go = 0; + #20; + #30000000; + $stop; + end + +endmodule