From cfa32e7f009128e9d4704f603d0cae469b363f4e Mon Sep 17 00:00:00 2001 From: User Date: Thu, 30 Jan 2025 13:29:07 +0500 Subject: [PATCH] source code and tt10 code is added --- rtl/alu.v | 52 +++++ rtl/branch_logic.v | 56 ++++++ rtl/cpu.v | 158 +++++++++++++++ rtl/dff_module.v | 20 ++ rtl/mux.v | 35 ++++ rtl/pc.v | 20 ++ tiny-tapeout-uart-rtl/bitty.v | 161 +++++++++++++++ tiny-tapeout-uart-rtl/fetch_instruction.v | 118 +++++++++++ tiny-tapeout-uart-rtl/lsu.v | 140 +++++++++++++ tiny-tapeout-uart-rtl/mux2to1.v | 16 ++ tiny-tapeout-uart-rtl/project_final.v | 233 ++++++++++++++++++++++ tiny-tapeout-uart-rtl/uart_module.v | 48 +++++ tiny-tapeout-uart-rtl/uart_rx.v | 149 ++++++++++++++ tiny-tapeout-uart-rtl/uart_tx.v | 147 ++++++++++++++ 14 files changed, 1353 insertions(+) create mode 100644 rtl/alu.v create mode 100644 rtl/branch_logic.v create mode 100644 rtl/cpu.v create mode 100644 rtl/dff_module.v create mode 100644 rtl/mux.v create mode 100644 rtl/pc.v create mode 100644 tiny-tapeout-uart-rtl/bitty.v create mode 100644 tiny-tapeout-uart-rtl/fetch_instruction.v create mode 100644 tiny-tapeout-uart-rtl/lsu.v create mode 100644 tiny-tapeout-uart-rtl/mux2to1.v create mode 100644 tiny-tapeout-uart-rtl/project_final.v create mode 100644 tiny-tapeout-uart-rtl/uart_module.v create mode 100644 tiny-tapeout-uart-rtl/uart_rx.v create mode 100644 tiny-tapeout-uart-rtl/uart_tx.v diff --git a/rtl/alu.v b/rtl/alu.v new file mode 100644 index 0000000..be3a175 --- /dev/null +++ b/rtl/alu.v @@ -0,0 +1,52 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +// -------------------------------------- +// This is a Arithmetic Logic Unit (ALU). +// -------------------------------------- + +module alu +( + input [ 2:0 ] select, + input [ 15:0 ] in_a, + input [ 15:0 ] in_b, + output [ 15:0 ] alu_out +); + + reg [ 15:0 ] res; + + parameter ADD = 3'b000; + parameter SUB = 3'b001; + parameter AND = 3'b010; + parameter OR = 3'b011; + parameter XOR = 3'b100; + parameter SHL = 3'b101; + parameter SHR = 3'b110; + parameter CMP = 3'b111; + + always @(*) begin + case ( select ) + ADD : res = in_a + in_b; + SUB : res = in_a - in_b; + AND : res = in_a & in_b; + OR : res = in_a | in_b; + XOR : res = in_a ^ in_b; + SHL : res = in_a << ( in_b % 16 ); + SHR : res = in_a >> ( in_b % 16 ); + CMP : begin + if ( in_a == in_b ) begin + res = 0; + end + else if ( in_a > in_b ) begin + res = 1; + end + else begin + res = 2; + end + end + default: res = 16'h0000; // Default value as 16-bit zero + endcase + end + + assign alu_out = res; + +endmodule diff --git a/rtl/branch_logic.v b/rtl/branch_logic.v new file mode 100644 index 0000000..2dba343 --- /dev/null +++ b/rtl/branch_logic.v @@ -0,0 +1,56 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +// -------------------------------------- +// This is a Branch Logic. +// -------------------------------------- + + +module branch_logic +( + input [ 7:0] address, + /* verilator lint_off UNUSED */ + input [ 15:0] instruction, + input [ 15:0] last_alu_result, + output reg [ 7:0] new_pc +); + + wire [ 1:0] branch_cond; + wire [ 7:0] immediate; + wire [ 1:0] format; + + assign branch_cond = instruction[ 3:2 ]; + assign immediate = instruction[ 11:4 ]; + assign format = instruction[ 1:0 ]; + + always @(*) begin + if (format == 2'b10) begin + case (branch_cond) + 2'b00: begin + if (last_alu_result == 0) + new_pc = immediate; + else + new_pc = address + 8'b00000001; + end + 2'b01: begin + if (last_alu_result == 1) + new_pc = immediate; + else + new_pc = address + 8'b00000001; + end + 2'b10: begin + if (last_alu_result == 2) + new_pc = immediate; + else + new_pc = address + 8'b00000001; + end + default: begin + new_pc = address + 8'b00000001; + end + endcase + end + else begin + new_pc = address + 8'b00000001; + end + end + +endmodule diff --git a/rtl/cpu.v b/rtl/cpu.v new file mode 100644 index 0000000..cd52e23 --- /dev/null +++ b/rtl/cpu.v @@ -0,0 +1,158 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +// -------------------------------------- +// This is a Control Unit (CU). +// -------------------------------------- + + +module cpu +( + input clk, + input run, + input reset, + input [15:0] d_inst, + input ls_done, + + output reg [ 3:0] mux_sel, + output reg done, + output reg [ 2:0] sel, + output reg sel_reg_c, + output reg en_s, + output reg en_c, + output reg [ 1:0] en_ls, + output reg [ 7:0] en, + output reg en_inst, + output reg [15:0] im_d +); + + parameter S0 = 2'b00; + parameter S1 = 2'b01; + parameter S2 = 2'b10; + + reg [ 1:0] cur_state; + reg [ 1:0] next_state; + wire [ 1:0] format; + wire ls_flag; + + assign format = d_inst[ 1:0 ]; + assign ls_flag = d_inst[ 2 ]; + + // Next state sequential logic + always @(posedge clk) begin + if (!reset) begin + cur_state <= S0; + end + else begin + cur_state <= next_state; + end + end + + always @(*) begin + en_inst = 1; + en_s = 0; + en_c = 0; + done = 0; + mux_sel = 4'b1001; + sel = 3'b0; + en = 8'b0; + im_d = { 8'b0, d_inst[ 12:5 ] }; + sel_reg_c = 1'b0; + en_ls = 2'b00; + + case (cur_state) + S0: begin + if (format != 2'b10) begin + en_s = 1; + mux_sel = { 1'b0, d_inst[ 15:13 ] }; + if (format == 2'b01) begin + im_d = { 8'b0, d_inst[ 12:5 ] }; + end + end + sel = 3'b0; + done = 0; + en_inst = 1; + end + + S1: begin + if (format != 2'b10) begin + if (format == 2'b00 | format == 2'b11) begin + mux_sel = { 1'b0, d_inst[ 12:10 ] }; + end + else if (format == 2'b01) begin + mux_sel = 4'b1000; + end + else begin + mux_sel = 4'b1001; + end + sel = d_inst[ 4:2 ]; + end + else begin + sel = 3'b0; + mux_sel = 4'b1001; + end + + if (format == 2'b11) begin + en_ls = (ls_flag == 0) ? 2'b01 : 2'b10; + end + + // LSU d_out loaded to reg C + if (format == 2'b11) begin + sel_reg_c = 1'b1; + end + en_c = 1'b1; + en_inst = 0; + done = 0; + end + + S2: begin + if (format != 2'b10 & format != 2'b11) begin + en[ d_inst[ 15:13 ] ] = 1; + end + else if (format == 2'b11 & ls_flag == 0) begin + en[ d_inst[ 15:13 ] ] = 1; + end + else begin + en = 8'b0; + end + sel = 3'b0; + done = 1'b1; + en_inst = 1; + end + + default: begin + en_s = 0; + en_c = 0; + done = 0; + mux_sel = 4'b1001; + sel = 3'b0; + en = 8'b0; + en_ls = 2'b00; + end + endcase + end + + // Next state combinational logic + always @(*) begin + case (cur_state) + S0: begin + if (run == 1) begin + next_state = (format == 2'b10) ? S2 : S1; + end + else begin + next_state = S0; + end + end + S1: begin + if (format == 2'b11) begin + next_state = (ls_done == 1) ? S2 : S1; + end + else begin + next_state = (en_c == 1) ? S2 : S1; + end + end + S2: next_state = (done == 1) ? S0 : S2; + default: next_state = S0; + endcase + end + +endmodule diff --git a/rtl/dff_module.v b/rtl/dff_module.v new file mode 100644 index 0000000..747666a --- /dev/null +++ b/rtl/dff_module.v @@ -0,0 +1,20 @@ +module dff_module +( + input clk, + input en, + input wire [ 15:0] d_in, + input reset, + + output reg [ 15:0] mux_out +); + + always @(posedge clk) begin + if (!reset) begin + mux_out <= 16'b0; + end + else if (en) begin + mux_out <= d_in; + end + end + +endmodule diff --git a/rtl/mux.v b/rtl/mux.v new file mode 100644 index 0000000..efc130e --- /dev/null +++ b/rtl/mux.v @@ -0,0 +1,35 @@ +module mux +( + input [ 15:0 ] reg0, + input [ 15:0 ] reg1, + input [ 15:0 ] reg2, + input [ 15:0 ] reg3, + input [ 15:0 ] reg4, + input [ 15:0 ] reg5, + input [ 15:0 ] reg6, + input [ 15:0 ] reg7, + input [ 15:0 ] im_d, + input [ 15:0 ] def_val, + + input [ 3:0 ] mux_sel, + output reg [ 15:0 ] mux_out +); + + always @(*) begin + case ( mux_sel ) + 4'b0000: mux_out = reg0; + 4'b0001: mux_out = reg1; + 4'b0010: mux_out = reg2; + 4'b0011: mux_out = reg3; + 4'b0100: mux_out = reg4; + 4'b0101: mux_out = reg5; + 4'b0110: mux_out = reg6; + 4'b0111: mux_out = reg7; + 4'b1000: mux_out = im_d; + 4'b1001: mux_out = def_val; + + default: mux_out = 16'b0; + endcase + end + +endmodule diff --git a/rtl/pc.v b/rtl/pc.v new file mode 100644 index 0000000..e7116e6 --- /dev/null +++ b/rtl/pc.v @@ -0,0 +1,20 @@ +module pc +( + input clk, + input en_pc, + input reset, + input [7:0] d_in, + + output reg [7:0] d_out +); + + always @(posedge clk) begin + if (!reset) begin + d_out <= 8'b0; + end + else if (en_pc) begin + d_out <= d_in; + end + end + +endmodule diff --git a/tiny-tapeout-uart-rtl/bitty.v b/tiny-tapeout-uart-rtl/bitty.v new file mode 100644 index 0000000..3c30f09 --- /dev/null +++ b/tiny-tapeout-uart-rtl/bitty.v @@ -0,0 +1,161 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +// -------------------------------------- +// This is a modified Bitty Core for UART communication. +// -------------------------------------- + +module bitty +( + input run, + input clk, + input reset, + input [15:0] d_instr, + + input [ 7:0] rx_data, + input rx_done, + input tx_done, + + output tx_en, + output [ 7:0] tx_data, + output [15:0] d_out, + output done +); + + genvar k; + wire [ 3:0] mux_sel; + wire [ 7:0] en; + wire [15:0] out[7:0]; + wire [15:0] out_mux; + + // ALU components + wire [15:0] alu_out; + + // CPU components + wire en_s, en_c, en_inst; + wire [ 2:0] alu_sel; + wire [15:0] instruction; + wire [15:0] im_d; + + // Additional components + wire [15:0] regs; + wire [15:0] regc; + wire [ 1:0] en_ls; + wire [15:0] data_to_ld; + wire ls_done; + wire sel_reg_c; + wire [15:0] mux2_out; + + // CPU connection + cpu cpu_inst + ( + .clk (clk ), + .run (run ), + .reset (reset ), + .d_inst (instruction), + .ls_done (ls_done ), + .mux_sel (mux_sel ), + .done (done ), + .sel (alu_sel ), + .sel_reg_c (sel_reg_c ), + .en_s (en_s ), + .en_c (en_c ), + .en_ls (en_ls ), + .en (en ), + .en_inst (en_inst ), + .im_d (im_d ) + ); + + lsu lsu_inst + ( + .clk (clk ), + .reset (reset ), + .en_ls (en_ls ), + .data_to_store(regs ), + .address (out_mux[7:0] ), + .rx_data (rx_data ), + .tx_done (tx_done ), + .rx_do (rx_done ), + .data_to_load (data_to_ld ), + .tx_start_out (tx_en ), + .tx_data_out (tx_data ), + .done_out (ls_done ) + ); + + mux2to1 for_reg_c + ( + .reg0 (alu_out ), + .reg1 (data_to_ld), + .sel (sel_reg_c ), + .out (mux2_out ) + ); + + // ALU Connection + alu alu_inst + ( + .in_a (regs ), + .in_b (out_mux ), + .select (alu_sel ), + .alu_out (alu_out ) + ); + + // MUX connection + generate + for ( k = 0; k < 8; k = k + 1 ) begin : gen_dff + dff_module reg_out + ( + .clk (clk ), + .en (en[k] ), + .d_in (regc ), + .reset (reset ), + .mux_out (out[k] ) + ); + end + endgenerate + + mux mux_inst + ( + .reg0 (out[0] ), + .reg1 (out[1] ), + .reg2 (out[2] ), + .reg3 (out[3] ), + .reg4 (out[4] ), + .reg5 (out[5] ), + .reg6 (out[6] ), + .reg7 (out[7] ), + .im_d (im_d ), + .def_val (0 ), + .mux_sel (mux_sel ), + .mux_out (out_mux ) + ); + + dff_module reg_inst + ( + .clk (clk ), + .en (en_inst ), + .d_in (d_instr ), + .reset (reset ), + .mux_out (instruction) + ); + + dff_module reg_s + ( + .clk (clk ), + .en (en_s ), + .d_in (out_mux ), + .reset (reset ), + .mux_out (regs ) + ); + + dff_module reg_c + ( + .clk (clk ), + .en (en_c ), + .d_in (mux2_out ), + .reset (reset ), + .mux_out (regc ) + ); + + // Assigning out array elements to module outputs + assign d_out = regc; + +endmodule diff --git a/tiny-tapeout-uart-rtl/fetch_instruction.v b/tiny-tapeout-uart-rtl/fetch_instruction.v new file mode 100644 index 0000000..9000ac3 --- /dev/null +++ b/tiny-tapeout-uart-rtl/fetch_instruction.v @@ -0,0 +1,118 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +// -------------------------------------- +// This is a Fetch Instruction Unit for UART communication. +// -------------------------------------- + +module fetch_instruction +( + input clk, + input reset, + // input next_instr_en, + input [7:0] address, // 8-bit address to be sent + input rx_do, // Signal indicating data received + input [7:0] rx_data, // Data received from UART + input tx_done, // Signal indicating transmission is done + input stop_for_rw, // Stop the FIU while UART works + + output [15:0] instruction_out, // 16-bit instruction received + output tx_start_out, // Signal to start UART transmission + output [7:0] tx_data_out, // Data to be transmitted over UART + output done_out // Signal indicating the operation is complete +); + + reg [15:0] instruction; // 16-bit instruction received + reg tx_start; // Signal to start UART transmission + reg [7:0] tx_data; // Data to be transmitted over UART + reg done; // Signal indicating the operation is complete + + assign done_out = done; + assign instruction_out = instruction; + assign tx_start_out = tx_start; + assign tx_data_out = tx_data; + + // State encoding + parameter IDLE = 3'b000; + parameter SEND_FLAG = 3'b001; + parameter SEND_ADDR = 3'b010; + parameter RECEIVE_INST_LOW = 3'b100; + parameter RECEIVE_INST_HIGH = 3'b101; + parameter DONE = 3'b110; + + reg [2:0] state, next_state; + + // Sequential logic for state transition + always @(posedge clk) begin + if (!reset | stop_for_rw == 1) begin + state <= IDLE; + end + else begin + state <= next_state; + end + end + + // State machine logic + /* verilator lint_off LATCH */ + always @(*) begin + // Default values + tx_start = 1; + tx_data = 8'b00000000; + done = 0; + instruction = instruction; + + case (state) + IDLE: begin + done = 0; + end + + SEND_FLAG: begin + tx_data = 8'b00000011; // Send flag byte + tx_start = 0; // Start transmission + end + + SEND_ADDR: begin + tx_data = address; // Send address byte + tx_start = 0; // Start transmission + end + + RECEIVE_INST_HIGH: begin + if (rx_do) begin + instruction[15:8] = rx_data; // Store upper 8 bits of instruction + end + end + + RECEIVE_INST_LOW: begin + if (rx_do) begin + instruction[7:0] = rx_data; // Store lower 8 bits of instruction + end + end + + DONE: begin + done = 1; // Set done signal + end + + default: begin + tx_start = 1; + tx_data = 8'b00000000; + done = 0; + instruction = instruction; + end + endcase + end + + always @(*) begin + case (state) + IDLE: next_state = SEND_FLAG; + SEND_FLAG: next_state = (tx_done == 1'b1) ? SEND_ADDR : SEND_FLAG; + SEND_ADDR: next_state = (tx_done == 1'b1) ? RECEIVE_INST_HIGH : SEND_ADDR; + RECEIVE_INST_HIGH: next_state = (rx_do == 1'b1) ? RECEIVE_INST_LOW : RECEIVE_INST_HIGH; + RECEIVE_INST_LOW: next_state = (rx_do == 1'b1) ? DONE : RECEIVE_INST_LOW; + DONE: begin + next_state = IDLE; + $display("done"); + end + default: next_state = IDLE; + endcase + end + +endmodule diff --git a/tiny-tapeout-uart-rtl/lsu.v b/tiny-tapeout-uart-rtl/lsu.v new file mode 100644 index 0000000..2779aff --- /dev/null +++ b/tiny-tapeout-uart-rtl/lsu.v @@ -0,0 +1,140 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +// -------------------------------------- +// This is a Load Store Unit for UART communication. +// -------------------------------------- + + +module lsu +( + input clk, + input reset, + + input [1:0] en_ls, + input [15:0] data_to_store, + input [7:0] address, // 8-bit address to be sent + + input rx_do, // Signal indicating data received + input [7:0] rx_data, // Data received from UART + input tx_done, // Signal indicating transmission is done + + output [15:0] data_to_load, // 16-bit instruction received + output tx_start_out, // Signal to start UART transmission + output [7:0] tx_data_out, // Data to be transmitted over UART + output done_out // Signal indicating the operation is complete +); + + reg [15:0] instruction; // 16-bit instruction received + reg tx_start; // Signal to start UART transmission + reg [7:0] tx_data; // Data to be transmitted over UART + reg done; // Signal indicating the operation is complete + + assign done_out = done; + assign data_to_load = instruction; + assign tx_start_out = tx_start; + assign tx_data_out = tx_data; + + // State encoding + parameter SEND_FLAG = 3'b001; + parameter SEND_ADDR = 3'b010; + parameter RECEIVE_INST_LOW = 3'b011; + parameter RECEIVE_INST_HIGH = 3'b100; + parameter SEND_INST_HIGH = 3'b101; + parameter SEND_INST_LOW = 3'b110; + parameter DONE = 3'b111; + + parameter LOAD = 2'b01; + parameter STORE = 2'b10; + + reg [2:0] state, next_state; + wire [1:0] en; + + assign en = en_ls; + + // Sequential logic for state transition + always @(posedge clk) begin + if (!reset) begin + state <= SEND_FLAG; + end + else begin + state <= next_state; + end + end + + // State machine logic + /* verilator lint_off LATCH */ + always @(*) begin + // Default values + tx_start = 1; + tx_data = 8'b00000000; + done = 0; + instruction = instruction; + + case (state) + SEND_FLAG: begin + if (en == 2'b01) begin + tx_data = 8'b00000001; // Send flag byte + tx_start = 0; // Start transmission + end + else if (en == 2'b10) begin + tx_data = 8'b00000010; // Send flag byte + tx_start = 0; // Start transmission + end + end + + SEND_ADDR: begin + tx_data = address; // Send address byte + tx_start = 0; // Start transmission + end + + RECEIVE_INST_HIGH: begin + if (rx_do) begin + instruction[15:8] = rx_data; // Store upper 8 bits of instruction + end + end + + RECEIVE_INST_LOW: begin + if (rx_do) begin + instruction[7:0] = rx_data; // Store lower 8 bits of instruction + end + end + + SEND_INST_HIGH: begin + tx_data = data_to_store[15:8]; // Send flag byte + tx_start = 0; // Start transmission + end + + SEND_INST_LOW: begin + tx_data = data_to_store[7:0]; // Send flag byte + tx_start = 0; // Start transmission + end + + DONE: begin + done = 1'b1; // Set done signal + end + + default: begin + tx_start = 1; + tx_data = 8'b00000000; + done = 0; + instruction = instruction; + end + endcase + end + + /* verilator lint_off LATCH */ + always @(*) begin + next_state = next_state; + case (state) + SEND_FLAG: next_state = (tx_done == 1'b1 & en_ls != 2'b0) ? SEND_ADDR : SEND_FLAG; + SEND_ADDR: next_state = (tx_done == 1'b1) ? ((en == LOAD) ? RECEIVE_INST_HIGH : SEND_INST_HIGH) : SEND_ADDR; + RECEIVE_INST_HIGH:next_state = (rx_do == 1'b1) ? RECEIVE_INST_LOW : RECEIVE_INST_HIGH; + RECEIVE_INST_LOW: next_state = (rx_do == 1'b1) ? DONE : RECEIVE_INST_LOW; + SEND_INST_HIGH: next_state = (tx_done == 1'b1) ? SEND_INST_LOW : SEND_INST_HIGH; + SEND_INST_LOW: next_state = (tx_done == 1'b1) ? DONE : SEND_INST_LOW; + DONE: next_state = SEND_FLAG; + default: next_state = SEND_FLAG; + endcase + end + +endmodule diff --git a/tiny-tapeout-uart-rtl/mux2to1.v b/tiny-tapeout-uart-rtl/mux2to1.v new file mode 100644 index 0000000..c22c512 --- /dev/null +++ b/tiny-tapeout-uart-rtl/mux2to1.v @@ -0,0 +1,16 @@ +module mux2to1 +( + input [ 15:0] reg0, + input [ 15:0] reg1, + input sel, + output reg [ 15:0] out +); + + always @(*) begin + if (sel) + out = reg1; + else + out = reg0; + end + +endmodule diff --git a/tiny-tapeout-uart-rtl/project_final.v b/tiny-tapeout-uart-rtl/project_final.v new file mode 100644 index 0000000..e92d491 --- /dev/null +++ b/tiny-tapeout-uart-rtl/project_final.v @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2024 Moldir Azhimukhanbet, Maveric Lab + * SPDX-License-Identifier: Apache-2.0 + */ + + // -------------------------------------- +// This is a Top Module for Tiny-Tapeout 10. +// -------------------------------------- + + +`default_nettype none + +module tt_um_bitty ( + /* verilator lint_off UNUSEDSIGNAL */ + input wire [7:0] ui_in, // Dedicated inputs + /* verilator lint_off UNDRIVEN */ + output wire [7:0] uo_out, // Dedicated outputs + input wire [7:0] uio_in, // IOs: Input path + /* verilator lint_off UNDRIVEN */ + output wire [7:0] uio_out, // IOs: Output path + /* verilator lint_off UNDRIVEN */ + output wire [7:0] uio_oe, // IOs: Enable path (active high: 0=input, 1=output) + input wire ena, // always 1 when the design is powered, so you can ignore it + input wire clk, // clock + input wire rst_n // reset_n - low to reset +); + + //top-module I/O ports assignment + + wire reset; + wire rx_data_bit; + wire tx_data_bit; + wire [1:0] sel_baude_rate; + + assign reset = rst_n; + assign rx_data_bit = ui_in[0]; + assign sel_baude_rate = ui_in[2:1]; + + //Unused output ports assignment to zero + assign uo_out[7:1] = 7'b0; + assign uio_out[7:0] = 8'b0; + assign uio_oe[7:0] = 8'b0; + + /* verilator lint_off UNUSED */ + wire _unused = &{ena, uio_out, uo_out[7:1], 1'b0, uio_oe, uio_in, ui_in[7:3]}; + + assign uo_out[0] = tx_data_bit; //output + + + //General ports declaration + wire [7:0] new_pc; // Declare new_pc as a wire + wire [7:0] addr; + + wire [15:0] d_out; + wire done; + + reg [3:0] cur_state, next_state; + wire tx_done; + wire rx_done; + reg en_pc; + + reg run_bitty; + reg [15:0] mem_out; + + wire [7:0] from_uart_to_modules; + wire [7:0] data_to_uart_from_fetch; + wire [7:0] from_bitty_to_uart; + wire tx_en, tx_en_fiu, tx_en_bitty; + + wire fetch_done; + wire [7:0] tx_data; + + reg uart_sel; + + parameter S0 = 4'b0000; + parameter S1 = 4'b0001; + parameter S2 = 4'b0010; + parameter S3 = 4'b0011; + parameter S4 = 4'b0100; + parameter S5 = 4'b0101; + parameter S6 = 4'b0110; + + //Use in FSM + reg stop_for_rw; + + // Fetch instruction instance + fetch_instruction fi_inst( + .clk(clk), + .reset(reset), + .address(addr), + .stop_for_rw(stop_for_rw), + .rx_do(rx_done), + .rx_data(from_uart_to_modules), + .tx_done(tx_done), + .instruction_out(mem_out), + .tx_start_out(tx_en_fiu), + .tx_data_out(data_to_uart_from_fetch), + .done_out(fetch_done) + ); + + reg [12:0] clks_per_bit; + + //Select baud rate of the external device + always@(*) begin + case (sel_baude_rate) + 2'b00:clks_per_bit = 5208; //9600 + 2'b01:clks_per_bit = 2604; //19200 + 2'b10:clks_per_bit = 868; //57600 + 2'b11:clks_per_bit = 434; //115200 + default: clks_per_bit = 5208; + endcase + + end + + // UART module instance + uart_module uart_inst( + .clk(clk), + .rst(reset), + .clks_per_bit(clks_per_bit), + .rx_data_bit(rx_data_bit), + .rx_done(rx_done), + .tx_data_bit(tx_data_bit), + .data_tx(tx_data), + .tx_en(tx_en), + .tx_done(tx_done), + .recieved_data(from_uart_to_modules) + ); + + //Branch Logic Instance + + branch_logic bl_inst( + .address(addr), + .instruction(mem_out), + .last_alu_result(d_out), + .new_pc(new_pc) // Connect new_pc here + ); + + // PC instance + pc pc_inst( + .clk(clk), + .en_pc(en_pc), + .reset(reset), + .d_in(new_pc), // Use new_pc for the input here + .d_out(addr) + ); + + wire [7:0] unused_8bit; + + //MUX to select tx_data port for UART + mux2to1 mux2to1_txdata( + .reg0({8'b0, data_to_uart_from_fetch}), + .reg1({8'b0,from_bitty_to_uart}), + .sel(uart_sel), + .out({unused_8bit,tx_data}) + ); + + wire [14:0] unused_15bit; + + //MUX to select tx_en port for UART + mux2to1 mux2to1_txen( + .reg0({15'b0, tx_en_fiu}), + .reg1({15'b0, tx_en_bitty}), + .sel(uart_sel), + .out({unused_15bit, tx_en}) + ); + + //Bitty instance + bitty bitty_inst( + .clk(clk), + .reset(reset), + .run(run_bitty), + .d_instr(mem_out), + .rx_data(from_uart_to_modules), + .rx_done(rx_done), + .tx_done(tx_done), + .tx_en(tx_en_bitty), + .tx_data(from_bitty_to_uart), + .done(done), + .d_out(d_out) + ); + + always @(posedge clk) begin + if(!reset) begin + cur_state <= S0; + end + else begin + cur_state <= next_state; + end + end + + always @(*) begin + run_bitty = 1'b0; + en_pc = 1'b0; + uart_sel = 1'b0; + stop_for_rw = 1'b0; + case (cur_state) + S0: begin + stop_for_rw = 1'b0; + end + S2: begin + en_pc = 1'b1; + end + S4: begin + run_bitty = 1'b1; + end + S5: begin + stop_for_rw = 1'b0; + end + S6: begin + uart_sel = 1'b1; + stop_for_rw = 1'b1; + end + default: begin + run_bitty = 0; + end + endcase + end + + always @(*) begin + case(cur_state) + S0: next_state = (fetch_done==1) ? S1:S0; + S1: next_state = S2; + S2: next_state = S3; + //deleted S4 -> 'latest/back-up' version before delete + S3: next_state = S4; + S4: next_state = (mem_out[1:0]==2'b11) ? S6:S5; + S5: next_state = (done==1) ? S0:S5; + S6: next_state = (done==1) ? S0:S6; + default: next_state = S0; + endcase + end + +endmodule \ No newline at end of file diff --git a/tiny-tapeout-uart-rtl/uart_module.v b/tiny-tapeout-uart-rtl/uart_module.v new file mode 100644 index 0000000..1665803 --- /dev/null +++ b/tiny-tapeout-uart-rtl/uart_module.v @@ -0,0 +1,48 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +// -------------------------------------- +// This is a top level UART module. +// -------------------------------------- + +module uart_module +#( + parameter data_width = 8 +) +( + input clk, + input rst, + input [ 12:0 ] clks_per_bit, + + input rx_data_bit, + output rx_done, + + output tx_data_bit, + input [ data_width-1:0 ] data_tx, + input tx_en, + output tx_done, + + output [ data_width-1:0 ] recieved_data +); + + uart_rx R0 + ( + .data_bit ( rx_data_bit ), + .clk ( clk ), + .rst ( rst ), + .CLKS_PER_BIT ( clks_per_bit ), + .done ( rx_done ), + .data_bus ( recieved_data ) + ); + + uart_tx T0 + ( + .data_bus ( data_tx ), + .clk ( clk ), + .rstn ( rst ), + .CLKS_PER_BIT ( clks_per_bit ), + .run ( tx_en ), // active when low + .done ( tx_done ), + .data_bit ( tx_data_bit ) + ); + +endmodule diff --git a/tiny-tapeout-uart-rtl/uart_rx.v b/tiny-tapeout-uart-rtl/uart_rx.v new file mode 100644 index 0000000..aa1754c --- /dev/null +++ b/tiny-tapeout-uart-rtl/uart_rx.v @@ -0,0 +1,149 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +module uart_rx +#( + parameter data_width = 8, + IDLE = 3'b000, + START_BIT = 3'b001, + DATA_BITS = 3'b010, + STOP_BIT = 3'b011, + DONE = 3'b101, + ERROR_ST = 3'b110 +) +( + input data_bit, + input clk, + input rst, + input [ 12:0 ] CLKS_PER_BIT, + output reg done, + output [ data_width - 1:0 ] data_bus +); + + // FSM states + reg [ 2:0 ] PS; + reg [ 2:0 ] NS; + + // Internal nets + reg [ 2:0 ] bit_counter; + reg [ 12:0 ] clk_counter; + reg [ data_width - 1:0 ] data_bus_wire; + + // Output assignments + assign data_bus = data_bus_wire; + + // FSM: PS synchronization + always @(posedge clk) begin + if ( !rst ) begin + PS <= IDLE; + end + else begin + PS <= NS; + end + end + + // FSM: Data and control logic + always @(negedge clk) begin + // Default values + done <= 1'b0; + clk_counter <= clk_counter; + bit_counter <= bit_counter; + data_bus_wire <= data_bus_wire; + + case ( PS ) + IDLE: begin + clk_counter <= 0; + bit_counter <= 0; + data_bus_wire <= 0; + end + + START_BIT: begin + if ( clk_counter < CLKS_PER_BIT / 2 ) begin + clk_counter <= clk_counter + 1; + end + else begin + clk_counter <= 0; + end + end + + DATA_BITS: begin + if ( clk_counter < CLKS_PER_BIT - 1 ) begin + clk_counter <= clk_counter + 1; + end + else begin + clk_counter <= 0; + data_bus_wire[ bit_counter ] <= data_bit; + + if ( bit_counter < 7 ) begin + bit_counter <= bit_counter + 1; + end + end + end + + STOP_BIT: begin + if ( clk_counter < CLKS_PER_BIT - 1 ) begin + clk_counter <= clk_counter + 1; + end + else begin + clk_counter <= 0; + end + end + + DONE: begin + done <= 1'b1; + end + + ERROR_ST: begin + // Remain in error state + end + + default: begin + bit_counter <= 0; + clk_counter <= 0; + data_bus_wire <= 0; + end + endcase + end + + // Next state transition logic + always @(negedge clk) begin + // Default next state + NS <= PS; + + case ( PS ) + IDLE: begin + NS <= ( data_bit == 1'b0 ) ? START_BIT : IDLE; + end + + START_BIT: begin + if ( clk_counter == CLKS_PER_BIT / 2 ) begin + NS <= ( data_bit == 1'b0 ) ? DATA_BITS : ERROR_ST; + end + end + + DATA_BITS: begin + if ( clk_counter == CLKS_PER_BIT - 1 ) begin + NS <= ( bit_counter < 7 ) ? DATA_BITS : STOP_BIT; + end + end + + STOP_BIT: begin + if ( clk_counter == CLKS_PER_BIT - 1 ) begin + NS <= DONE; + end + end + + DONE: begin + NS <= IDLE; + end + + ERROR_ST: begin + NS <= ERROR_ST; + end + + default: begin + NS <= IDLE; + end + endcase + end + +endmodule diff --git a/tiny-tapeout-uart-rtl/uart_tx.v b/tiny-tapeout-uart-rtl/uart_tx.v new file mode 100644 index 0000000..febdd0d --- /dev/null +++ b/tiny-tapeout-uart-rtl/uart_tx.v @@ -0,0 +1,147 @@ +/* Copyright (c) 2024 Maveric NU. All rights reserved. */ + +module uart_tx +#( + parameter data_width = 8, + IDLE = 3'b000, + START_BIT = 3'b001, + DATA_BITS = 3'b010, + STOP_BIT = 3'b011, + DONE = 3'b101 +) +( + input [ data_width - 1:0 ] data_bus, + input clk, + input rstn, + input [ 12:0 ] CLKS_PER_BIT, + input run, + output done, + output data_bit +); + + // FSM states + reg [ 2:0 ] PS; + reg [ 2:0 ] NS; + reg [ 12:0 ] clk_counter; + reg [ 2:0 ] bit_counter; + reg data_reg; + + // Output assignments + assign done = ( PS == DONE ); + + // FSM: PS synchronization + always @(posedge clk) begin + if ( !rstn ) begin + PS <= IDLE; + end + else begin + PS <= NS; + end + end + + // FSM: Data and control logic + always @(negedge clk) begin + // Default values + data_reg <= 1'b1; + clk_counter <= clk_counter; + bit_counter <= bit_counter; + + case ( PS ) + IDLE: begin + data_reg <= 1'b1; + bit_counter <= 0; + clk_counter <= 0; + end + + START_BIT: begin + data_reg <= 1'b0; + + if ( clk_counter < CLKS_PER_BIT - 1 ) begin + clk_counter <= clk_counter + 1'b1; + end + else begin + clk_counter <= 0; + end + end + + DATA_BITS: begin + data_reg <= data_bus[ bit_counter ]; + + if ( clk_counter < CLKS_PER_BIT - 1 ) begin + clk_counter <= clk_counter + 1'b1; + end + else begin + clk_counter <= 0; + + if ( bit_counter < 7 ) begin + bit_counter <= bit_counter + 1'b1; + end + end + end + + STOP_BIT: begin + data_reg <= 1'b1; + + if ( clk_counter < CLKS_PER_BIT - 1 ) begin + clk_counter <= clk_counter + 1'b1; + end + else begin + clk_counter <= 0; + end + end + + DONE: begin + // Reset to initial state + end + + default: begin + data_reg <= 1'b1; + clk_counter <= 0; + bit_counter <= 0; + end + endcase + end + + // Next state transition logic + always @(negedge clk) begin + // Default next state + NS <= PS; + + case ( PS ) + IDLE: begin + NS <= ( !run ) ? START_BIT : IDLE; + end + + START_BIT: begin + NS <= ( clk_counter == CLKS_PER_BIT - 1 ) ? DATA_BITS : START_BIT; + end + + DATA_BITS: begin + if ( clk_counter == CLKS_PER_BIT - 1 ) begin + if ( bit_counter < 7 ) begin + NS <= DATA_BITS; + end + else begin + NS <= STOP_BIT; + end + end + end + + STOP_BIT: begin + NS <= ( clk_counter == CLKS_PER_BIT - 1 ) ? DONE : STOP_BIT; + end + + DONE: begin + NS <= IDLE; + end + + default: begin + NS <= IDLE; + end + endcase + end + + // Output assignment + assign data_bit = data_reg; + +endmodule