├── UART ├── UART TX │ ├── input_data.txt │ ├── expected_output.txt │ ├── MUX.v │ ├── parity_calc.v │ ├── serializer.v │ ├── UART_TX.v │ ├── FSM.v │ ├── README.md │ └── UART_TX_tb.v └── UART RX │ ├── stop_check.v │ ├── start_check.v │ ├── parity_check.v │ ├── deserializer.v │ ├── edge_bit_counter.v │ ├── data_sampling.v │ ├── UART_RX.v │ ├── README.md │ └── FSM.v ├── BACKEND ├── Synthesis │ ├── constraints.rpt │ ├── clocks.rpt │ ├── power.rpt │ ├── check_design.rpt │ └── area.rpt ├── Formal Verification (POST-DFT) │ ├── aborted_points.rpt │ ├── failing_points.rpt │ └── unverified_points.rpt ├── Formal Verification (POST-SYN) │ ├── aborted_points.rpt │ ├── failing_points.rpt │ └── unverified_points.rpt ├── DFT │ ├── check_design.rpt │ ├── clocks.rpt │ ├── power.rpt │ └── area.rpt └── README.md ├── Pulse Generator ├── PULSE_GEN.v ├── README.md └── PULSE_GEN_tb.v ├── Data Synchronizer ├── PULSE_GEN.v ├── sync_bus.v ├── DS_PULSE.v ├── multi_ff.v ├── DATA_SYNC.v ├── README.md └── DATA_SYNC_tb.v ├── Clock Gate ├── ClkGate_tb.v ├── ClkGate.v └── README.md ├── Reset Synchronizer ├── RST_SYNC.v ├── README.md └── RST_SYNC_tb.v ├── Asynchronous FIFO ├── DF_SYNC.v ├── GRAY_CONV.v ├── FIFO_MEM_CNTRL.v ├── FIFO_RD.v ├── FIFO_WR.v ├── ASYNC_FIFO.v ├── ASYNC_FIFO_tb.v └── README.md ├── ALU ├── ALU.v └── README.md ├── Register File ├── RegFile.v ├── README.md └── RegFile_tb.v ├── Clock Divider ├── README.md ├── ClkDiv.v └── ClkDiv_tb.v ├── System Controller ├── README.md └── SYS_CTRL.v ├── SYS_TOP_tb.v ├── README.md └── SYS_TOP.v /UART/UART TX/input_data.txt: -------------------------------------------------------------------------------- 1 | 01111101 2 | 10100101 3 | 01001111 4 | 01011110 5 | 00101101 6 | 10000000 7 | 10011111 8 | 00010011 9 | 10001101 -------------------------------------------------------------------------------- /UART/UART TX/expected_output.txt: -------------------------------------------------------------------------------- 1 | 01011111001 2 | 01010010101 3 | 01111001011 4 | 00111101001 5 | 01011010011 6 | 00000000101 7 | 0111110011 8 | 0110010001 9 | 0101100011 -------------------------------------------------------------------------------- /BACKEND/Synthesis/constraints.rpt: -------------------------------------------------------------------------------- 1 | 2 | **************************************** 3 | Report : constraint 4 | -all_violators 5 | Design : SYS_TOP 6 | Version: K-2015.06 7 | Date : Mon Sep 25 22:32:08 2023 8 | **************************************** 9 | 10 | This design has no violated constraints. 11 | 12 | 1 13 | -------------------------------------------------------------------------------- /UART/UART RX/stop_check.v: -------------------------------------------------------------------------------- 1 | module stop_check 2 | ( input wire enable, 3 | input wire sampled_stop_bit, 4 | output reg error ); 5 | 6 | always @(*) 7 | begin 8 | if(enable && !sampled_stop_bit) 9 | error = 1'b1; 10 | else 11 | error = 1'b0; 12 | end 13 | endmodule 14 | 15 | -------------------------------------------------------------------------------- /UART/UART RX/start_check.v: -------------------------------------------------------------------------------- 1 | module start_check 2 | ( input wire enable, 3 | input wire sampled_start_bit, 4 | output reg glitch ); 5 | 6 | always @(*) 7 | begin 8 | if(enable && sampled_start_bit) 9 | glitch = 1'b1; 10 | else 11 | glitch = 1'b0; 12 | end 13 | endmodule 14 | 15 | -------------------------------------------------------------------------------- /BACKEND/Formal Verification (POST-DFT)/aborted_points.rpt: -------------------------------------------------------------------------------- 1 | ************************************************** 2 | Report : aborted_points 3 | 4 | Reference : Ref:/WORK/SYS_TOP 5 | Implementation : Imp:/WORK/SYS_TOP 6 | Version : L-2016.03-SP1 7 | Date : Mon Sep 25 23:05:17 2023 8 | ************************************************** 9 | 10 | No aborted compare points. 11 | 12 | 1 13 | -------------------------------------------------------------------------------- /BACKEND/Formal Verification (POST-DFT)/failing_points.rpt: -------------------------------------------------------------------------------- 1 | ************************************************** 2 | Report : failing_points 3 | 4 | Reference : Ref:/WORK/SYS_TOP 5 | Implementation : Imp:/WORK/SYS_TOP 6 | Version : L-2016.03-SP1 7 | Date : Mon Sep 25 23:05:17 2023 8 | ************************************************** 9 | 10 | No failing compare points. 11 | 12 | 1 13 | -------------------------------------------------------------------------------- /BACKEND/Formal Verification (POST-SYN)/aborted_points.rpt: -------------------------------------------------------------------------------- 1 | ************************************************** 2 | Report : aborted_points 3 | 4 | Reference : Ref:/WORK/SYS_TOP 5 | Implementation : Imp:/WORK/SYS_TOP 6 | Version : L-2016.03-SP1 7 | Date : Mon Sep 25 22:56:38 2023 8 | ************************************************** 9 | 10 | No aborted compare points. 11 | 12 | 1 13 | -------------------------------------------------------------------------------- /BACKEND/Formal Verification (POST-SYN)/failing_points.rpt: -------------------------------------------------------------------------------- 1 | ************************************************** 2 | Report : failing_points 3 | 4 | Reference : Ref:/WORK/SYS_TOP 5 | Implementation : Imp:/WORK/SYS_TOP 6 | Version : L-2016.03-SP1 7 | Date : Mon Sep 25 22:56:38 2023 8 | ************************************************** 9 | 10 | No failing compare points. 11 | 12 | 1 13 | -------------------------------------------------------------------------------- /BACKEND/Formal Verification (POST-DFT)/unverified_points.rpt: -------------------------------------------------------------------------------- 1 | ************************************************** 2 | Report : unverified_points 3 | 4 | Reference : Ref:/WORK/SYS_TOP 5 | Implementation : Imp:/WORK/SYS_TOP 6 | Version : L-2016.03-SP1 7 | Date : Mon Sep 25 23:05:17 2023 8 | ************************************************** 9 | 10 | No unverified compare points. 11 | 12 | 1 13 | -------------------------------------------------------------------------------- /BACKEND/Formal Verification (POST-SYN)/unverified_points.rpt: -------------------------------------------------------------------------------- 1 | ************************************************** 2 | Report : unverified_points 3 | 4 | Reference : Ref:/WORK/SYS_TOP 5 | Implementation : Imp:/WORK/SYS_TOP 6 | Version : L-2016.03-SP1 7 | Date : Mon Sep 25 22:56:38 2023 8 | ************************************************** 9 | 10 | No unverified compare points. 11 | 12 | 1 13 | -------------------------------------------------------------------------------- /BACKEND/DFT/check_design.rpt: -------------------------------------------------------------------------------- 1 | 2 | **************************************** 3 | check_design summary: 4 | Version: K-2015.06 5 | Date: Mon Sep 25 22:59:38 2023 6 | **************************************** 7 | 8 | Name Total 9 | -------------------------------------------------------------------------------- 10 | No issues found. 11 | -------------------------------------------------------------------------------- 12 | 13 | 1 14 | -------------------------------------------------------------------------------- /Pulse Generator/PULSE_GEN.v: -------------------------------------------------------------------------------- 1 | module PULSE_GEN ( 2 | input wire CLK , // Clock Signal 3 | input wire RST , // Active Low Reset 4 | input wire LVL_SIG , // Level signal 5 | output wire PULSE_SIG ); // Pulse signal 6 | 7 | // register declaration 8 | reg DFF; 9 | 10 | // shifting the input 11 | always @(posedge CLK or negedge RST) 12 | begin 13 | if(!RST) 14 | DFF <= 1'b0; 15 | else 16 | DFF <= LVL_SIG; 17 | end 18 | 19 | // pulse generation 20 | assign PULSE_SIG = (~DFF) & LVL_SIG; 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /Data Synchronizer/PULSE_GEN.v: -------------------------------------------------------------------------------- 1 | module PULSE_GEN ( 2 | input wire CLK , // Clock Signal 3 | input wire RST , // Active Low Reset 4 | input wire LVL_SIG , // Level signal 5 | output wire PULSE_SIG ); // Pulse signal 6 | 7 | // register declaration 8 | reg DFF; 9 | 10 | // shifting the input 11 | always @(posedge CLK or negedge RST) 12 | begin 13 | if(!RST) 14 | DFF <= 1'b0; 15 | else 16 | DFF <= LVL_SIG; 17 | end 18 | 19 | // pulse generation 20 | assign PULSE_SIG = (~DFF) & LVL_SIG; 21 | 22 | endmodule 23 | -------------------------------------------------------------------------------- /Data Synchronizer/sync_bus.v: -------------------------------------------------------------------------------- 1 | module sync_bus #( parameter BUS_WIDTH = 8) 2 | ( input wire RST , 3 | input wire CLK , 4 | input wire SEL , 5 | input wire [BUS_WIDTH-1:0] i_0 , 6 | input wire [BUS_WIDTH-1:0] i_1 , 7 | output reg [BUS_WIDTH-1:0] sync_bus ); 8 | 9 | wire [BUS_WIDTH-1:0] mux_out; 10 | 11 | assign mux_out = SEL? i_1 : i_0; 12 | 13 | always @(negedge RST or posedge CLK) 14 | begin 15 | if(!RST) 16 | sync_bus <= 'b0; 17 | else 18 | sync_bus <= mux_out; 19 | end 20 | 21 | endmodule -------------------------------------------------------------------------------- /Data Synchronizer/DS_PULSE.v: -------------------------------------------------------------------------------- 1 | module D 2 | ( input wire CLK , 3 | input wire RST , 4 | input wire bus_enable , 5 | output wire pulse , 6 | output reg enable_pulse ); 7 | 8 | // enable shifting 9 | PULSE_GEN inst_PULSE_GEN ( 10 | .CLK(CLK) , 11 | .RST(RST) , 12 | .LVL_SIG(bus_enable) , 13 | .PULSE_SIG(pulse) ); 14 | 15 | // passing the enable pulse 16 | always @(negedge RST or posedge CLK) 17 | begin 18 | if(!RST) 19 | enable_pulse <= 1'b0; 20 | else 21 | enable_pulse <= pulse; 22 | end 23 | 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /Clock Gate/ClkGate_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps 2 | 3 | module ClkGate_tb (); 4 | 5 | reg CLK_EN; 6 | reg CLK; 7 | wire GATED_CLK; 8 | 9 | initial 10 | begin 11 | CLK = 0; 12 | CLK_EN = 0; 13 | 14 | #10 15 | @(posedge CLK) 16 | #2 17 | CLK_EN = 1; 18 | #20 19 | CLK_EN = 0; 20 | #28 21 | 22 | @(negedge CLK) 23 | #2 24 | CLK_EN = 1; 25 | #20 26 | CLK_EN = 0; 27 | #3 28 | 29 | @(posedge CLK) 30 | #1 31 | CLK_EN = 1; 32 | #1 33 | CLK_EN = 0; 34 | #3 35 | 36 | @(negedge CLK) 37 | #1 38 | CLK_EN = 1; 39 | #1 40 | CLK_EN = 0; 41 | #3 42 | 43 | #20 $stop; 44 | 45 | end 46 | 47 | always #5 CLK = ~CLK; 48 | 49 | ClkGate DUT ( .CLK_EN(CLK_EN), 50 | .CLK(CLK), 51 | .GATED_CLK(GATED_CLK) ); 52 | 53 | 54 | endmodule -------------------------------------------------------------------------------- /UART/UART TX/MUX.v: -------------------------------------------------------------------------------- 1 | module MUX ( input wire start_bit, 2 | input wire stop_bit, 3 | input wire ser_data, 4 | input wire par_bit, 5 | input wire [1:0] mux_sel, 6 | output reg TX_OUT ); 7 | 8 | // mux selector encoding 9 | localparam mux_start = 2'b00; 10 | localparam mux_serial = 2'b01; 11 | localparam mux_parity = 2'b10; 12 | localparam mux_stop = 2'b11; 13 | 14 | always @(*) 15 | begin 16 | case(mux_sel) 17 | mux_start: TX_OUT = start_bit; 18 | mux_serial: TX_OUT = ser_data; 19 | mux_parity: TX_OUT = par_bit; 20 | mux_stop: TX_OUT = stop_bit; 21 | 22 | //default: TX_OUT = 1'b1; 23 | 24 | endcase 25 | end 26 | endmodule 27 | -------------------------------------------------------------------------------- /Reset Synchronizer/RST_SYNC.v: -------------------------------------------------------------------------------- 1 | module RST_SYNC #( parameter NUM_STAGES = 2) 2 | ( input wire CLK , // Clock Signal 3 | input wire RST , // Active Low Async Reset 4 | output wire SYNC_RST ); // Active Low synchronized Reset 5 | 6 | // intermediate synchronizer FFs 7 | reg [NUM_STAGES-1:0] sync_dff ; 8 | 9 | // generate control loop index 10 | integer i; 11 | 12 | always @(negedge RST or posedge CLK) 13 | begin 14 | if(!RST) 15 | sync_dff <= 'b0; 16 | else 17 | begin 18 | for(i = 0; i < NUM_STAGES; i = i + 1) 19 | begin 20 | if(i==0) 21 | sync_dff[i] <= 1'b1; 22 | else 23 | sync_dff[i] <= sync_dff[i-1]; 24 | end 25 | end 26 | end 27 | 28 | // output 29 | assign SYNC_RST = sync_dff[NUM_STAGES-1]; 30 | 31 | endmodule 32 | -------------------------------------------------------------------------------- /UART/UART RX/parity_check.v: -------------------------------------------------------------------------------- 1 | module parity_check #( 2 | parameter WIDTH = 8, 3 | EVEN = 0, 4 | ODD = 1) 5 | ( 6 | input [WIDTH-1:0] data, 7 | input wire par_type, 8 | input wire par_bit, 9 | input wire enable, 10 | output reg error ); 11 | 12 | wire data_xor; 13 | // calculate parity with the extracted data 14 | always @(*) 15 | begin 16 | if(enable) 17 | case(par_type) 18 | EVEN: begin 19 | if(par_bit == (data_xor)) 20 | error = 1'b0; 21 | else 22 | error = 1'b1; 23 | end 24 | ODD: begin 25 | if(par_bit == (~data_xor)) 26 | error = 1'b0; 27 | else 28 | error = 1'b1; 29 | end 30 | endcase 31 | else 32 | error = 1'b0; 33 | end 34 | 35 | assign data_xor = ^data; 36 | endmodule -------------------------------------------------------------------------------- /Clock Gate/ClkGate.v: -------------------------------------------------------------------------------- 1 | module ClkGate #( parameter POST_SYN = 0) 2 | ( input wire CLK , // Clock Signal 3 | input wire CLK_EN , // Clock Enable 4 | output wire GATED_CLK ); // Gated Clock signal 5 | 6 | // latch enable signal declaration 7 | reg CLK_EN_LATCHED; 8 | 9 | 10 | // generate block for post-syn design 11 | generate 12 | case(POST_SYN) 13 | 1'b0: 14 | begin : FOR_SIMULATION 15 | always @(CLK) 16 | begin 17 | if(!CLK) 18 | CLK_EN_LATCHED <= CLK_EN; 19 | end 20 | assign GATED_CLK = CLK & CLK_EN_LATCHED; 21 | end 22 | 23 | 1'b1: 24 | begin : FOR_SYN 25 | TLATNCAX6M U0_CLK_GATE_CELL ( 26 | .CK (CLK) , 27 | .E (CLK_EN) , 28 | .ECK (GATED_CLK) ); 29 | end 30 | endcase 31 | endgenerate 32 | endmodule -------------------------------------------------------------------------------- /Data Synchronizer/multi_ff.v: -------------------------------------------------------------------------------- 1 | module multi_ff #( parameter BUS_WIDTH = 1, NUM_STAGES = 2) 2 | ( input wire CLK , 3 | input wire RST , 4 | input wire [BUS_WIDTH-1:0] ASYNC , 5 | output wire [BUS_WIDTH-1:0] SYNC ); 6 | 7 | // intermediate synchronizer FFs 8 | reg [BUS_WIDTH-1:0] sync_dff [NUM_STAGES-1:0]; 9 | 10 | // control loop index 11 | integer i; 12 | 13 | always @(negedge RST or posedge CLK) 14 | begin 15 | if(!RST) 16 | for(i = 0; i < NUM_STAGES; i = i + 1) 17 | sync_dff[i] <= 'b0; 18 | else 19 | begin 20 | for(i = 0; i < NUM_STAGES; i = i + 1) 21 | begin 22 | if(i == 0) 23 | sync_dff[i] <= ASYNC; 24 | else 25 | sync_dff[i] <= sync_dff[i-1]; 26 | end 27 | end 28 | end 29 | 30 | // output 31 | assign SYNC = sync_dff[NUM_STAGES-1]; 32 | endmodule 33 | 34 | -------------------------------------------------------------------------------- /Asynchronous FIFO/DF_SYNC.v: -------------------------------------------------------------------------------- 1 | module DF_SYNC #( parameter BUS_WIDTH = 4, NUM_STAGES = 2) 2 | ( input wire CLK , 3 | input wire RST , 4 | input wire [BUS_WIDTH-1:0] ASYNC , 5 | output wire [BUS_WIDTH-1:0] SYNC ); 6 | 7 | // intermediate synchronizer FFs 8 | reg [BUS_WIDTH-1:0] sync_dff [NUM_STAGES-1:0]; 9 | 10 | // control loop index 11 | integer i; 12 | 13 | always @(negedge RST or posedge CLK) 14 | begin 15 | if(!RST) 16 | for(i = 0; i < NUM_STAGES; i = i + 1) 17 | sync_dff[i] <= 'b0; 18 | else 19 | begin 20 | for(i = 0; i < NUM_STAGES; i = i + 1) 21 | begin 22 | if(i == 0) 23 | sync_dff[i] <= ASYNC; 24 | else 25 | sync_dff[i] <= sync_dff[i-1]; 26 | end 27 | end 28 | end 29 | 30 | // output 31 | assign SYNC = sync_dff[NUM_STAGES-1]; 32 | endmodule 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Asynchronous FIFO/GRAY_CONV.v: -------------------------------------------------------------------------------- 1 | //******************************************************************************************// 2 | // Description: // 3 | // ------------ // 4 | // It is N-bit Bit-Gray Code Converter // 5 | // // 6 | //******************************************************************************************// 7 | 8 | module GRAY_CONV #( parameter PTR_WIDTH = 4 ) 9 | ( input wire [PTR_WIDTH-1:0] bit_ptr , 10 | output reg [PTR_WIDTH-1:0] gray_ptr ); 11 | 12 | // control loop variable 13 | integer i; 14 | 15 | // conversion always block 16 | always @(*) 17 | begin 18 | for(i = 0; i < PTR_WIDTH-1; i = i + 1) 19 | begin 20 | gray_ptr[i] = bit_ptr[i] + bit_ptr[i+1]; 21 | end 22 | gray_ptr[PTR_WIDTH-1] = bit_ptr[PTR_WIDTH-1]; // the MSB is kept the same 23 | end 24 | endmodule 25 | -------------------------------------------------------------------------------- /UART/UART TX/parity_calc.v: -------------------------------------------------------------------------------- 1 | module parity_calc #( parameter WIDTH = 8 ) 2 | ( input wire [WIDTH-1:0] P_DATA, 3 | input wire PAR_TYP, 4 | input wire CLK, 5 | input wire RST, 6 | input wire PAR_EN, 7 | input wire Data_Valid, 8 | output reg par_bit ); 9 | 10 | reg [WIDTH-1:0] data; 11 | 12 | localparam EVEN = 1'b0; 13 | localparam ODD = 1'b1; 14 | 15 | always @(posedge CLK, negedge RST) 16 | begin 17 | if(!RST) 18 | data <= 'b0; 19 | else if(Data_Valid) 20 | data <= P_DATA; 21 | end 22 | 23 | always @(*) 24 | begin 25 | if(PAR_EN) 26 | par_bit = (PAR_TYP)? ~^data : ^data; 27 | else 28 | par_bit = 1'b0; 29 | end 30 | 31 | 32 | /*always @(posedge CLK, negedge RST) 33 | begin 34 | if(!RST) 35 | begin 36 | data <= 'b0; 37 | par_bit <= 1'b0; 38 | end 39 | else if(PAR_EN) 40 | begin 41 | par_bit <= (PAR_TYP)? ~^data : ^data; 42 | end 43 | else 44 | data <= P_DATA; 45 | end */ 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /Data Synchronizer/DATA_SYNC.v: -------------------------------------------------------------------------------- 1 | module DATA_SYNC #( parameter BUS_WIDTH = 8, NUM_STAGES = 2) 2 | ( input wire dest_clk , 3 | input wire dest_rst , 4 | input wire bus_enable , 5 | input wire [BUS_WIDTH-1:0] unsync_bus , 6 | output wire [BUS_WIDTH-1:0] sync_bus , 7 | output wire enable_pulse ); 8 | 9 | // internal signal declaration 10 | wire x_sync_bus_enable; 11 | wire x_pulse_sel; 12 | 13 | multi_ff U0_multi_ff ( 14 | .CLK (dest_clk) , 15 | .RST (dest_rst) , 16 | .ASYNC (bus_enable) , 17 | .SYNC (x_sync_bus_enable) ); 18 | 19 | 20 | DS_PULSE U0_DS_PULSE ( 21 | .CLK (dest_clk) , 22 | .RST (dest_rst) , 23 | .bus_enable (x_sync_bus_enable) , 24 | .pulse (x_pulse_sel) , 25 | .enable_pulse (enable_pulse) ); 26 | 27 | sync_bus U0_sync_bus ( 28 | .CLK (dest_clk) , 29 | .RST (dest_rst) , 30 | .SEL (x_pulse_sel) , 31 | .i_0 (sync_bus) , 32 | .i_1 (unsync_bus) , 33 | .sync_bus (sync_bus) ); 34 | 35 | 36 | endmodule 37 | -------------------------------------------------------------------------------- /UART/UART RX/deserializer.v: -------------------------------------------------------------------------------- 1 | module deserializer #( 2 | parameter WIDTH = 8 ) 3 | ( 4 | input wire clk , 5 | input wire rst , 6 | input wire enable , 7 | input wire sampled_bit , 8 | input wire success , 9 | output reg data_valid , 10 | output reg [WIDTH-1:0] sampled_stream , 11 | output reg [WIDTH-1:0] parallel_data ); 12 | 13 | // shifter and counter always block 14 | always @(posedge clk, negedge rst) 15 | begin 16 | if(!rst) 17 | begin 18 | sampled_stream <= 'b0; 19 | end 20 | else if(enable) 21 | begin 22 | sampled_stream <= {sampled_bit,sampled_stream[7:1]}; 23 | end 24 | end 25 | 26 | always @(posedge clk, negedge rst) 27 | begin 28 | if(!rst) 29 | begin 30 | parallel_data <= 'b0; 31 | data_valid <= 'b0; 32 | end 33 | else if(success) 34 | begin 35 | parallel_data <= sampled_stream; 36 | data_valid <= 'b1; 37 | end 38 | else if(!success) 39 | begin 40 | data_valid <= 'b0; 41 | end 42 | end 43 | endmodule 44 | -------------------------------------------------------------------------------- /UART/UART RX/edge_bit_counter.v: -------------------------------------------------------------------------------- 1 | module edge_bit_counter #( 2 | parameter MAX_PRESCALE = 32 , 3 | PAR_MAX = 11 , 4 | PRSC_WIDTH = ($clog2(MAX_PRESCALE)+1) , 5 | FRAME_WIDTH = ($clog2(PAR_MAX) + 1) ) 6 | ( 7 | input wire clk , 8 | input wire rst , 9 | input wire enable , 10 | input wire parity_en , 11 | input wire [PRSC_WIDTH-1:0] prescale , 12 | output reg [PRSC_WIDTH-2:0] edge_cnt , 13 | output reg [FRAME_WIDTH-2:0] bit_cnt , 14 | output wire edge_max ); 15 | 16 | // counter max value declaration 17 | wire bit_max; 18 | 19 | // edge sampling counter 20 | always @(posedge clk, negedge rst) 21 | begin 22 | if(!rst) 23 | edge_cnt <= 'b0; 24 | else if(!enable || (enable && edge_max)) 25 | edge_cnt <= 'b0; 26 | else 27 | edge_cnt <= edge_cnt + 1'b1; 28 | end 29 | 30 | // bit counter 31 | always @(posedge clk, negedge rst) 32 | begin 33 | if(!rst) 34 | bit_cnt <= 'b0; 35 | else if(!enable || (enable && bit_max && edge_max)) 36 | bit_cnt <= 'b0; 37 | else if(edge_max) 38 | bit_cnt <= bit_cnt + 1'b1; 39 | end 40 | 41 | // flag assign statement 42 | assign edge_max = (edge_cnt == prescale - 1); 43 | assign bit_max = (parity_en)? (bit_cnt == 'b1010) : (bit_cnt == 'b1001); 44 | 45 | endmodule 46 | -------------------------------------------------------------------------------- /BACKEND/Synthesis/clocks.rpt: -------------------------------------------------------------------------------- 1 | 2 | **************************************** 3 | Report : clocks 4 | Design : SYS_TOP 5 | Version: K-2015.06 6 | Date : Mon Sep 25 22:32:08 2023 7 | **************************************** 8 | 9 | Attributes: 10 | d - dont_touch_network 11 | f - fix_hold 12 | p - propagated_clock 13 | G - generated_clock 14 | g - lib_generated_clock 15 | 16 | Clock Period Waveform Attrs Sources 17 | -------------------------------------------------------------------------------- 18 | ALU_CLK 10.00 {0 5} G {U0_ALU/CLK} 19 | REF_CLK 10.00 {0 5} {i_ref_clk} 20 | RX_CLK 270.00 {0 135} G {U0_UART_RX/i_clk} 21 | TX_CLK 8640.00 {0 4320} G {U0_UART_TX/CLK} 22 | UART_CLK 270.00 {0 135} {i_uart_clk} 23 | -------------------------------------------------------------------------------- 24 | 25 | Generated Master Generated Master Waveform 26 | Clock Source Source Clock Modification 27 | -------------------------------------------------------------------------------- 28 | ALU_CLK i_ref_clk {U0_ALU/CLK} REF_CLK divide_by(1) 29 | RX_CLK i_uart_clk {U0_UART_RX/i_clk} 30 | UART_CLK divide_by(1) 31 | TX_CLK i_uart_clk {U0_UART_TX/CLK} 32 | UART_CLK divide_by(32) 33 | -------------------------------------------------------------------------------- 34 | 1 35 | -------------------------------------------------------------------------------- /BACKEND/DFT/clocks.rpt: -------------------------------------------------------------------------------- 1 | 2 | **************************************** 3 | Report : clocks 4 | Design : SYS_TOP 5 | Version: K-2015.06 6 | Date : Mon Sep 25 23:00:27 2023 7 | **************************************** 8 | 9 | Attributes: 10 | d - dont_touch_network 11 | f - fix_hold 12 | p - propagated_clock 13 | G - generated_clock 14 | g - lib_generated_clock 15 | 16 | Clock Period Waveform Attrs Sources 17 | -------------------------------------------------------------------------------- 18 | ALU_CLK 10.00 {0 5} G {U0_ALU/CLK} 19 | REF_CLK 10.00 {0 5} {i_ref_clk} 20 | RX_CLK 271.27 {0 135.633} G {U0_UART_RX/i_clk} 21 | SCAN_CLK 100.00 {0 50} {scan_clk} 22 | TX_CLK 8680.54 {0 4340.27} G {U0_UART_TX/CLK} 23 | UART_CLK 271.27 {0 135.633} {i_uart_clk} 24 | -------------------------------------------------------------------------------- 25 | 26 | Generated Master Generated Master Waveform 27 | Clock Source Source Clock Modification 28 | -------------------------------------------------------------------------------- 29 | ALU_CLK i_ref_clk {U0_ALU/CLK} REF_CLK divide_by(1) 30 | RX_CLK i_uart_clk {U0_UART_RX/i_clk} 31 | UART_CLK divide_by(1) 32 | TX_CLK i_uart_clk {U0_UART_TX/CLK} 33 | UART_CLK divide_by(32) 34 | -------------------------------------------------------------------------------- 35 | 1 36 | -------------------------------------------------------------------------------- /UART/UART TX/serializer.v: -------------------------------------------------------------------------------- 1 | module serializer #( parameter WIDTH = 8, 2 | COUNT_BITS = ($clog2(WIDTH)+1) ) 3 | ( input wire [WIDTH-1:0] P_DATA, 4 | input wire ser_en, 5 | input wire CLK, 6 | input wire RST, 7 | output reg ser_data, 8 | output reg ser_done ); 9 | 10 | reg [COUNT_BITS-1:0] counter; // combinational logic output counter 11 | reg [COUNT_BITS-1:0] counter_r; // sequential logic output counter 12 | reg [WIDTH-1:0] data; 13 | 14 | // serializer sequential always block 15 | always @(posedge CLK, negedge RST) 16 | begin 17 | if(!RST) 18 | begin 19 | ser_data <= 1'b1; 20 | data <= 'b0; 21 | end 22 | else if(!ser_en) 23 | begin 24 | ser_data <= 1'b1; 25 | data <= P_DATA; 26 | end 27 | else if(ser_en && !ser_done) 28 | {data[WIDTH-2:0],ser_data} <= data; 29 | end 30 | 31 | // counter sequential always block 32 | always @(posedge CLK, negedge RST) 33 | begin 34 | if(!RST) 35 | counter_r <= WIDTH; 36 | else 37 | counter_r <= counter; 38 | end 39 | 40 | // counter combinational always block 41 | always @(*) 42 | begin 43 | if(ser_en && counter_r) 44 | begin 45 | counter = counter_r - 1'b1; 46 | ser_done = 1'b0; 47 | end 48 | else if (ser_en && !counter_r) 49 | begin 50 | counter = 1'b0; 51 | ser_done = 1'b1; 52 | end 53 | else 54 | begin 55 | counter = WIDTH; 56 | ser_done = 1'b0; 57 | end 58 | end 59 | endmodule -------------------------------------------------------------------------------- /Asynchronous FIFO/FIFO_MEM_CNTRL.v: -------------------------------------------------------------------------------- 1 | //******************************************************************************************// 2 | // Description: // 3 | // ------------ // 4 | // It's the FIFO memory buffer that is accessed by both the write and read clock domains. // 5 | // This buffer is most likely a synchronous dual-port RAM or register file // 6 | // // 7 | //******************************************************************************************// 8 | 9 | module FIFO_MEM_CNTRL #( parameter DATA_WIDTH = 8, parameter MEM_DEPTH = 8, parameter PTR_WIDTH = ($clog2(MEM_DEPTH)+1) ) 10 | ( input wire [DATA_WIDTH-1:0] W_data , 11 | input wire W_clk_en , 12 | input wire [PTR_WIDTH-2:0] W_addr , 13 | input wire [PTR_WIDTH-2:0] R_addr , 14 | input wire W_clk , 15 | input wire W_rst , 16 | output wire [DATA_WIDTH-1:0] R_data ); 17 | 18 | // FIFO Memory declaration 19 | reg [DATA_WIDTH-1:0] MEM [MEM_DEPTH-1:0]; 20 | 21 | // control loop index 22 | integer i; 23 | 24 | // write-port memory 25 | always @(posedge W_clk or negedge W_rst) 26 | begin 27 | if(!W_rst) 28 | begin 29 | for(i = 0; i < MEM_DEPTH; i = i + 1) 30 | begin 31 | MEM[i] <= 'b0; 32 | end 33 | end 34 | else if(W_clk_en) 35 | MEM[W_addr] <= W_data; 36 | end 37 | 38 | // read-port memory 39 | assign R_data = MEM[R_addr]; 40 | endmodule 41 | 42 | -------------------------------------------------------------------------------- /Reset Synchronizer/README.md: -------------------------------------------------------------------------------- 1 | # Reset Synchronizer Block 2 | 3 | ## Overview 4 | The Reset Synchronizer block is a crucial component in our Low Power Configurable Multi-Clock Digital System design. It addresses the challenges associated with asynchronous reset signals by ensuring synchronized de-assertion with respect to the clock domain. 5 | 6 | ## Block Description 7 | In digital circuits, asynchronous reset signals can pose timing challenges during de-assertion, potentially violating the recovery and removal times of Flip-Flops. The Reset Synchronizer effectively manipulates the asynchronous reset signal to achieve synchronous de-assertion, enhancing the reliability of the reset operation. 8 | 9 | ## Block Interface 10 | The Reset Synchronizer block has the following interface: 11 | 12 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/76adf338-ba66-40f4-bc4a-9126835cfdbf) 13 | 14 | - **Inputs:** 15 | - `RST`: Asynchronous reset signal that requires synchronization. 16 | - `CLK`: Clock signal for the sequential elements within the Reset Synchronizer. 17 | 18 | - **Outputs:** 19 | - `SYNC_RST`: The synchronized reset signal with controlled de-assertion timing. 20 | 21 | > For a better understanding of how the Reset Synchronizer block is implemented in RTL (Register-Transfer Level) code, please refer to the [`RESET_SYNC.v`](.RESET_SYNC.v) file in this repository. 22 | 23 | ## Parameterized Number of Synchronization Stages 24 | One notable feature of the Reset Synchronizer block is its parameterized number of synchronization stages. This flexibility allows you to adapt the block to your specific design requirements, ensuring optimal synchronization performance. 25 | 26 | ## [Testbench](./RST_SYNC_tb.v) 27 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/eef146e9-cb39-4a61-9220-9a6e7591f53e) 28 | 29 | 30 | -------------------------------------------------------------------------------- /Asynchronous FIFO/FIFO_RD.v: -------------------------------------------------------------------------------- 1 | //******************************************************************************************// 2 | // Description: // 3 | // ------------ // 4 | // It is responsible for calculation of read address (raddr) and generation of empty flag // 5 | // // 6 | //******************************************************************************************// 7 | 8 | module FIFO_RD #( parameter PTR_WIDTH = 4 ) 9 | ( input wire CLK , 10 | input wire RST , 11 | input wire rinc , 12 | input wire [PTR_WIDTH-1:0] wptr_conv , 13 | input wire [PTR_WIDTH-1:0] rptr_conv , 14 | output reg [PTR_WIDTH-1:0] rptr , 15 | output wire [PTR_WIDTH-2:0] raddr , 16 | output reg empty ); 17 | 18 | // empty flag declaration 19 | wire EMPTY_FLAG; 20 | 21 | // empty calculation always block 22 | always @(posedge CLK or negedge RST) 23 | begin 24 | if(!RST) 25 | empty <= 1'b1; 26 | else if(EMPTY_FLAG) 27 | empty <= 1'b1; 28 | else 29 | empty <= 1'b0; 30 | end 31 | 32 | // read address increment always block 33 | always @(posedge CLK or negedge RST) 34 | begin 35 | if(!RST) 36 | rptr <= 'b0; 37 | else if(!empty && rinc) 38 | rptr <= rptr + 1'b1; 39 | end 40 | 41 | // the read address is the LSBs of the pointer 42 | assign raddr = rptr[PTR_WIDTH-2:0]; 43 | 44 | // empty flag condition 45 | assign EMPTY_FLAG = (rptr_conv == wptr_conv); //when both pointers, including the MSBs are equal 46 | endmodule 47 | -------------------------------------------------------------------------------- /UART/UART RX/data_sampling.v: -------------------------------------------------------------------------------- 1 | module data_sampling #( 2 | parameter MAX_PRESCALE = 32 , 3 | PRSC_WIDTH = ($clog2(MAX_PRESCALE)+1) ) 4 | ( 5 | input wire clk , 6 | input wire rst , 7 | input wire enable , 8 | input wire serial_data , 9 | input wire [PRSC_WIDTH-1:1] prescale , 10 | input wire [PRSC_WIDTH-2:0] counter , 11 | output wire sampled_bit ); 12 | 13 | // internal signals 14 | reg first_sample, second_sample, third_sample; // sampled data 15 | wire [PRSC_WIDTH-1:0] sampling_1, sampling_2, sampling_3 ; // sampling time 16 | 17 | // sampling always block 18 | always @(posedge clk, negedge rst) 19 | begin 20 | if(!rst) 21 | begin 22 | first_sample <= 1'b0; 23 | second_sample <= 1'b0; 24 | third_sample <= 1'b0; 25 | end 26 | else if(enable) 27 | begin 28 | case(counter) 29 | sampling_1: first_sample <= serial_data; 30 | sampling_2: second_sample <= serial_data; 31 | sampling_3: third_sample <= serial_data; 32 | endcase 33 | end 34 | else 35 | begin 36 | first_sample <= 1'b0; 37 | second_sample <= 1'b0; 38 | third_sample <= 1'b0; 39 | end 40 | end 41 | 42 | // sampled data using Karnaugh map 43 | assign sampled_bit = (second_sample & third_sample) | 44 | (first_sample & third_sample) | 45 | (first_sample & second_sample); 46 | 47 | // calculate sampling time 48 | assign sampling_1 = (prescale)-1'b1; 49 | assign sampling_2 = (prescale) ; 50 | assign sampling_3 = (prescale)+1'b1; 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /Pulse Generator/README.md: -------------------------------------------------------------------------------- 1 | # Pulse Generator Block 2 | 3 | ## Overview 4 | The Pulse Generator block is a fundamental component in our Low Power Configurable Multi-Clock Digital System design. It serves the essential function of generating precise pulses based on control signals, enabling synchronized actions within our digital system. 5 | 6 | ## Block Description 7 | In digital systems, generating accurate and controlled pulses is crucial for synchronizing various operations. The Pulse Generator block efficiently creates pulses based on specific control signals, facilitating precise timing and coordination within the system. 8 | 9 | ## Block Interface 10 | The Pulse Generator block has the following interface: 11 | 12 |

13 | Block Interface 14 |

15 | 16 | - **Inputs:** 17 | - `CLK`: Clock signal for the sequential elements within the Pulse Generator. 18 | - `RST`: Asynchronous active-low reset signal to initialize and clear the pulse generation process. 19 | - `LVL_SIGNAL`: Control signal that determines the pulse characteristics. 20 | 21 | - **Outputs:** 22 | - `PULSE_SIGNAL`: The generated pulse signal with controlled characteristics based on the `LVL_SIGNAL` input. 23 | 24 | > For a better understanding of how the Pulse Generator block is implemented in RTL (Register-Transfer Level) code, please refer to the [`PULSE_GEN.v`](.PULSE_GEN.v) file in this repository. 25 | 26 | ## Key Functionality 27 | The Pulse Generator block's primary function is to create precise pulses based on the `LVL_SIGNAL` input. It offers flexibility and control over pulse characteristics, making it an essential component for coordinating actions within our digital system. 28 | 29 | ## [Testbench](./PULSE_GEN_tb.v) 30 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/2e8fe5f4-412b-481a-8430-4ee73543a09b) 31 | -------------------------------------------------------------------------------- /Asynchronous FIFO/FIFO_WR.v: -------------------------------------------------------------------------------- 1 | //******************************************************************************************// 2 | // Description: // 3 | // ------------ // 4 | // It is responsible for calculation of write address (raddr) and generation of full flag // 5 | // // 6 | //******************************************************************************************// 7 | 8 | module FIFO_WR #( parameter PTR_WIDTH = 4 ) 9 | ( input wire CLK , 10 | input wire RST , 11 | input wire winc , 12 | input wire [PTR_WIDTH-1:0] wptr_conv , 13 | input wire [PTR_WIDTH-1:0] rptr_conv , 14 | output reg [PTR_WIDTH-1:0] wptr , 15 | output wire [PTR_WIDTH-2:0] waddr , 16 | output reg full ); 17 | 18 | // full flag declaration 19 | wire FULL_FLAG; 20 | 21 | // full calculation always block 22 | always @(posedge CLK or negedge RST) 23 | begin 24 | if(!RST) 25 | full <= 1'b0; 26 | else if(FULL_FLAG) 27 | full <= 1'b1; 28 | else 29 | full <= 1'b0; 30 | end 31 | 32 | // write address increment always block 33 | always @(posedge CLK or negedge RST) 34 | begin 35 | if(!RST) 36 | wptr <= 'b0; 37 | else if(winc) 38 | wptr <= wptr + 1'b1; 39 | end 40 | 41 | // the write address is the LSBs of the pointer 42 | assign waddr = wptr[PTR_WIDTH-2:0]; 43 | 44 | // empty flag condition 45 | assign FULL_FLAG = (rptr_conv[PTR_WIDTH-1] != wptr_conv[PTR_WIDTH-1]) 46 | && 47 | (rptr_conv[PTR_WIDTH-2] != wptr_conv[PTR_WIDTH-2]) 48 | && 49 | (rptr_conv[PTR_WIDTH-3:0] == wptr_conv[PTR_WIDTH-3:0]); //when both pointers, except the MSBs, are equal 50 | endmodule 51 | -------------------------------------------------------------------------------- /UART/UART TX/UART_TX.v: -------------------------------------------------------------------------------- 1 | module UART_TX #( parameter WIDTH = 8 ) 2 | ( input wire [WIDTH-1:0] P_DATA, 3 | input wire DATA_VALID, 4 | input wire PAR_EN, 5 | input wire PAR_TYP, 6 | input wire CLK, 7 | input wire RST, 8 | output wire TX_OUT, 9 | output wire Busy ); 10 | 11 | // internal signals declaration 12 | wire ser_done; 13 | wire ser_data; 14 | wire ser_en; 15 | wire par_bit; 16 | wire [1:0] mux_sel; 17 | 18 | 19 | // module instantiations 20 | serializer U0_serializer ( .P_DATA(P_DATA), 21 | .ser_en(ser_en), 22 | .CLK(CLK), 23 | .RST(RST), 24 | .ser_data(ser_data), 25 | .ser_done(ser_done) ); 26 | 27 | FSM U0_FSM ( .Data_Valid(DATA_VALID), 28 | .PAR_EN(PAR_EN), 29 | .ser_done(ser_done), 30 | .CLK(CLK), 31 | .RST(RST), 32 | .ser_en(ser_en), 33 | .busy(Busy), 34 | .mux_sel(mux_sel) ); 35 | 36 | 37 | parity_calc U0_parity_calc ( .P_DATA(P_DATA), 38 | .PAR_TYP(PAR_TYP), 39 | .CLK(CLK), 40 | .RST(RST), 41 | .Data_Valid(!Busy), 42 | .PAR_EN(PAR_EN), 43 | .par_bit(par_bit) ); 44 | 45 | MUX U0_MUX ( .start_bit(1'b0), 46 | .stop_bit(1'b1), 47 | .ser_data(ser_data), 48 | .par_bit(par_bit), 49 | .mux_sel(mux_sel), 50 | .TX_OUT(TX_OUT) ); 51 | endmodule -------------------------------------------------------------------------------- /ALU/ALU.v: -------------------------------------------------------------------------------- 1 | 2 | module ALU #( parameter OPRND_WIDTH = 8, OUT_WIDTH = 2 * OPRND_WIDTH, CTRL_WIDTH = 4) 3 | ( input wire CLK , // Clock Signal 4 | input wire RST , // Active Low Reset 5 | input wire Enable , // ALU Enable 6 | input wire [OPRND_WIDTH-1:0] A , // Operand A 7 | input wire [OPRND_WIDTH-1:0] B , // Operand B 8 | input wire [ CTRL_WIDTH-1:0] ALU_FUN , // ALU Function 9 | output reg [ OUT_WIDTH-1:0] ALU_OUT , // ALU Result 10 | output reg OUT_VALID ); // ALU Result Valid 11 | 12 | // calculated result 13 | reg [OUT_WIDTH-1:0] ALU_RESULT; 14 | 15 | // combinational always block implementing gate-level ALU 16 | always @(*) 17 | begin 18 | if(Enable) 19 | case(ALU_FUN) 20 | // arithmatic cases 21 | 4'b0000: ALU_RESULT = A + B; // adition 22 | 4'b0001: ALU_RESULT = A - B; // subtraction 23 | 4'b0010: ALU_RESULT = A * B; // multiplication 24 | 4'b0011: ALU_RESULT = A / B; // division 25 | 26 | // logical cases 27 | 4'b0100: ALU_RESULT = A & B; // AND 28 | 4'b0101: ALU_RESULT = A | B; // OR 29 | 4'b0110: ALU_RESULT = ~(A & B); // NAND 30 | 4'b0111: ALU_RESULT = ~(A | B); // NOR 31 | 32 | // comparsion cases 33 | 4'b1000: ALU_RESULT = 'b0; 34 | 4'b1001: ALU_RESULT = (A==B)? 'd1:'d0; 35 | 4'b1010: ALU_RESULT = (A>B)? 'd2:'d0; 36 | 4'b1011: ALU_RESULT = (A>1; // shift A right 40 | 4'b1101: ALU_RESULT = A<<1; // shift A left 41 | 4'b1110: ALU_RESULT = B>>1; // shift B right 42 | 4'b1111: ALU_RESULT = B<<1; // shift B left 43 | 44 | default: ALU_RESULT = 'b0; 45 | endcase 46 | else 47 | ALU_RESULT = 'b0; 48 | end 49 | 50 | // registering the alu out 51 | always @(posedge CLK or negedge RST) 52 | begin 53 | if(!RST) 54 | begin 55 | ALU_OUT <= 'b0; 56 | OUT_VALID <= 1'b0; 57 | end 58 | else if(Enable) 59 | begin 60 | ALU_OUT <= ALU_RESULT; 61 | OUT_VALID <= 1'b1; 62 | end 63 | end 64 | endmodule 65 | -------------------------------------------------------------------------------- /Pulse Generator/PULSE_GEN_tb.v: -------------------------------------------------------------------------------- 1 | module PULSE_GEN_tb (); 2 | 3 | /*******************************************************************/ 4 | ///////////////////// TB Signals Declaration //////////////////////// 5 | /*******************************************************************/ 6 | parameter CLK_PERIOD = 10, HALF_PERIOD = 5; 7 | parameter HIGH = 1, LOW = 0; 8 | 9 | 10 | // interface ports 11 | reg CLK ; 12 | reg RST ; 13 | reg LVL_SIG ; 14 | wire PULSE_SIG ; 15 | 16 | /*******************************************************************/ 17 | ////////////////////////// Initial Block //////////////////////////// 18 | /*******************************************************************/ 19 | initial 20 | begin 21 | $dumpfile(".vcd"); 22 | $dumpvars; 23 | 24 | initialize(); 25 | reset(); 26 | 27 | LVL_SIG = HIGH; 28 | 29 | #(3*CLK_PERIOD); 30 | LVL_SIG = LOW; 31 | #CLK_PERIOD 32 | #2 33 | LVL_SIG = HIGH; 34 | 35 | #(3*CLK_PERIOD); 36 | LVL_SIG = LOW; 37 | #CLK_PERIOD 38 | #5 39 | LVL_SIG = HIGH; 40 | #(3*CLK_PERIOD) $stop; 41 | end 42 | 43 | /*******************************************************************/ 44 | ////////////////////////////// TASKS //////////////////////////////// 45 | /*******************************************************************/ 46 | task reset; 47 | begin 48 | RST = LOW; 49 | #HALF_PERIOD 50 | RST = HIGH; 51 | #HALF_PERIOD; 52 | end 53 | endtask 54 | /********************************/ 55 | task initialize; 56 | begin 57 | CLK = LOW; 58 | RST = LOW; 59 | LVL_SIG = LOW; 60 | end 61 | endtask 62 | /********************************/ 63 | 64 | /*******************************************************************/ 65 | ///////////////////////// Clock Generator /////////////////////////// 66 | /*******************************************************************/ 67 | always #HALF_PERIOD CLK = ~CLK; 68 | 69 | /*******************************************************************/ 70 | //////////////////////// DUT Instantiation ////////////////////////// 71 | /*******************************************************************/ 72 | PULSE_GEN DUT ( 73 | .CLK(CLK) , 74 | .RST(RST) , 75 | .LVL_SIG(LVL_SIG) , 76 | .PULSE_SIG(PULSE_SIG) ); 77 | 78 | endmodule 79 | -------------------------------------------------------------------------------- /Clock Gate/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Clock Gate Block 3 | 4 | ## Overview 5 | The Clock Gate block plays a pivotal role in my Low Power Configurable Multi-Clock Digital System design. It employs the widely adopted technique of Clock Gating to efficiently reduce dynamic power consumption by selectively disabling the clock signal during idle periods. 6 | 7 | ## Block Description 8 | In modern digital systems, optimizing power consumption is paramount. The Clock Gate block offers an effective solution by allowing me to control the clock signal, turning it off when a specific block is in an idle state. 9 | 10 | ## Block Interface 11 | The Clock Gate block has the following interface: 12 | 13 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/ac110b9a-378f-47f9-961e-033e6067a5da) 14 | 15 | - **Inputs:** 16 | - `CLK_EN`: Clock Enable signal, determining whether the clock should be gated or not. 17 | - `CLK`: The primary clock signal. 18 | 19 | - **Outputs:** 20 | - `GATED_CLK`: The clock signal, gated or disabled when `CLK_EN` indicates an idle state. 21 | 22 | > To gain a deeper insight into how the Clock Gate block is implemented in RTL (Register-Transfer Level) code, please refer to the [`ClkGate.v`](.ClkGate.v) file in this repository. 23 | 24 | ## Key Functionality 25 | The Clock Gate block's primary function is to efficiently manage power consumption by controlling the clock signal based on the `CLK_EN` input. This enables me to reduce dynamic power consumption during idle periods of specific blocks within my digital system. 26 | 27 | ## Understanding the RTL code 28 | For a detailed understanding of how the Clock Gate is implemented in Verilog, please refer to the [`ClkGate.v`](.ClkGate.v) file in this repository. 29 | - the Clock Gating Cell is implemented using a LATCH and an AND gate, but due to wire delay, it might cause errors. thus, the RTL code is used only in simulation as there's no wire delay in simulation. but during synthesis this design is replaced by ICG (integrated clock gating) full custom standard cell, which resolves the problem of wire delay 30 | - My code uses generated case statement to define the modelling of the cell, depending on the current stage of the flow, whether we're at the RTL designing phase or we're at the synthesis phase 31 | 32 | ## [Testbench](./ClkGate_tb.v) 33 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/dabfe29b-83cf-4eec-9229-f882a7fb2e12) 34 | -------------------------------------------------------------------------------- /Register File/RegFile.v: -------------------------------------------------------------------------------- 1 | module RegFile #( parameter BUS_WIDTH = 8, DEPTH = 8, ADDR_WIDTH = 4, PAR_EN = 1, PAR_TYPE = 0, PRESCALE = 32, DIV_RATIO = 32 ) 2 | ( input wire CLK , // Clock Signal 3 | input wire RST , // Active Low Reset 4 | input wire WrEn , // Write Enable 5 | input wire RdEn , // Read Enable 6 | input wire [ADDR_WIDTH-1:0] Address , // Address bus 7 | input wire [BUS_WIDTH-1 :0] WrData , // Write Data Bus 8 | output wire [BUS_WIDTH-1 :0] REG0 , // Register at Address 0x0 9 | output wire [BUS_WIDTH-1 :0] REG1 , // Register at Address 0x1 10 | output wire [BUS_WIDTH-1 :0] REG2 , // Register at Address 0x2 11 | output wire [BUS_WIDTH-1 :0] REG3 , // Register at Address 0x3 12 | output reg [BUS_WIDTH-1 :0] RdData , // Read Data Bus 13 | output reg RdData_Valid ); // Read Data Valid 14 | 15 | // Memory declaration 16 | reg [BUS_WIDTH-1:0] MEM [DEPTH-1:0]; 17 | 18 | // control loop index 19 | integer i; 20 | 21 | // sequential always block 22 | always @(posedge CLK or negedge RST) 23 | begin 24 | if(!RST) 25 | begin : MEMORY_CLEARING 26 | for(i = 0; i < DEPTH; i = i + 1) 27 | begin 28 | if(i == 2) 29 | begin 30 | MEM[i][0] <= PAR_EN; 31 | MEM[i][1] <= PAR_TYPE; 32 | MEM[i][7:2] <= PRESCALE; 33 | end 34 | else if(i == 3) 35 | MEM[i][7:0] <= DIV_RATIO; 36 | else 37 | MEM[i] <= 'b0; 38 | end 39 | RdData <= 'b0; 40 | RdData_Valid <= 1'b0; 41 | end 42 | 43 | else if (WrEn && !RdEn) 44 | begin : WRITING 45 | MEM[Address] <= WrData; 46 | end 47 | 48 | else if (!WrEn && RdEn) 49 | begin : READING 50 | RdData <= MEM[Address]; 51 | RdData_Valid <= 1'b1; 52 | end 53 | 54 | else 55 | begin : NOT_READING 56 | RdData_Valid <= 1'b0; 57 | end 58 | end 59 | 60 | // assign statements 61 | assign REG0 = MEM['h0]; 62 | assign REG1 = MEM['h1]; 63 | assign REG2 = MEM['h2]; 64 | assign REG3 = MEM['h3]; 65 | 66 | endmodule -------------------------------------------------------------------------------- /Clock Divider/README.md: -------------------------------------------------------------------------------- 1 | # Clock Divider (Frequency Divider) Block 2 | 3 | ## Overview 4 | The Clock Divider (Frequency Divider) block is a vital component within our Low Power Configurable Multi-Clock Digital System. Its purpose is to take an input clock signal of a certain frequency and generate an output clock signal with a different frequency, achieving frequency division as needed. 5 | 6 | ## Block Description 7 | In digital systems, managing clock frequencies is crucial for proper operation. The Clock Divider block provides the capability to divide the input clock frequency to match the specific requirements of our digital design. 8 | 9 | ## Block Interface 10 | The Clock Divider block has the following interface: 11 | 12 |

13 | Block Interface 14 |

15 | 16 | - **Inputs:** 17 | - `I_ref_clk`: Reference clock frequency input. 18 | - `I_rst_n`: Active-low asynchronous reset signal. 19 | - `I_clk_en`: Clock Divider Block Enable signal. 20 | - `I_div_ratio`: The desired divided ratio (an integer value). 21 | 22 | - **Output:** 23 | - `o_div_clk`: The generated clock signal with the divided or multiplied frequency. 24 | 25 | > For a detailed look at the Verilog implementation of the Clock Divider block, please refer to the [`ClkDiv.v`](./ClkDiv.v) file in this repository. 26 | 27 | ## Key Functionality 28 | The Clock Divider block's primary function is to adjust the clock period based on the input divided ratio. This flexibility ensures that our digital system operates with the precise timing required for its various components. 29 | 30 | ## Expected Waveforms 31 | ![clkdiv](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/6942cecb-4e00-481d-a55b-ebc55aa40a01) 32 | 33 | ## [Testbench](./ClkDiv_tb.v) 34 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/ddf7df87-f36a-45f0-a0e7-d21a36a19b91) 35 | 36 | ``` 37 | # [PASSED]: div ratio = 0, clock period = 10ns, div clock period = 10ns 38 | # [PASSED]: div ratio = 1, clock period = 10ns, div clock period = 10ns 39 | # [PASSED]: div ratio = 2, clock period = 10ns, div clock period = 20ns 40 | # [PASSED]: div ratio = 3, clock period = 10ns, div clock period = 30ns 41 | # [PASSED]: div ratio = 4, clock period = 10ns, div clock period = 40ns 42 | # [PASSED]: div ratio = 5, clock period = 10ns, div clock period = 50ns 43 | # [PASSED]: div ratio = 6, clock period = 10ns, div clock period = 60ns 44 | # [PASSED]: div ratio = 7, clock period = 10ns, div clock period = 70ns 45 | # [PASSED]: div ratio = 8, clock period = 10ns, div clock period = 80ns 46 | # [PASSED]: div ratio = 9, clock period = 10ns, div clock period = 90ns 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /Reset Synchronizer/RST_SYNC_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/10ps 2 | /*******************************************************************/ 3 | // To try different No. of Stages, 4 | // you can changes the parameter values in line 15 and re-run 5 | /*******************************************************************/ 6 | 7 | module RST_SYNC_tb(); 8 | 9 | 10 | /*******************************************************************/ 11 | ///////////////////// TB Signals Declaration //////////////////////// 12 | /*******************************************************************/ 13 | parameter CLK_PERIOD = 10 , HALF_PERIOD = 5; 14 | parameter HIGH = 1 , LOW = 0; 15 | parameter NUM_STAGES = 2; 16 | 17 | defparam DUT.NUM_STAGES = NUM_STAGES; 18 | 19 | 20 | // interface ports 21 | reg CLK ; 22 | reg RST ; 23 | wire SYNC_RST ; 24 | 25 | /*******************************************************************/ 26 | ////////////////////////// Initial Block //////////////////////////// 27 | /*******************************************************************/ 28 | initial 29 | begin 30 | $dumpfile("BIT_SYNC.vcd"); 31 | $dumpvars; 32 | 33 | initialize(); 34 | reset(); 35 | 36 | latency_test(); 37 | 38 | #(2*CLK_PERIOD) $stop; 39 | end 40 | 41 | /*******************************************************************/ 42 | ////////////////////////////// TASKS //////////////////////////////// 43 | /*******************************************************************/ 44 | task reset; 45 | begin 46 | RST = LOW; 47 | #HALF_PERIOD 48 | RST = HIGH; 49 | #HALF_PERIOD; 50 | end 51 | endtask 52 | /********************************/ 53 | task initialize; 54 | begin 55 | CLK = LOW; 56 | RST = HIGH; 57 | end 58 | endtask 59 | /********************************/ 60 | task latency_test; 61 | integer first_time, second_time, period; 62 | begin 63 | #(3*CLK_PERIOD) 64 | @(posedge CLK) 65 | //#(0.2*CLK_PERIOD) 66 | RST = LOW; 67 | @(negedge CLK) 68 | #(0.9*HALF_PERIOD); 69 | RST = HIGH; 70 | end 71 | endtask 72 | 73 | /*******************************************************************/ 74 | ///////////////////////// Clock Generator /////////////////////////// 75 | /*******************************************************************/ 76 | always #HALF_PERIOD CLK = ~CLK; 77 | 78 | /*******************************************************************/ 79 | //////////////////////// DUT Instantiation ////////////////////////// 80 | /*******************************************************************/ 81 | RST_SYNC DUT ( .CLK (CLK) , 82 | .RST (RST) , 83 | .SYNC_RST (SYNC_RST) ); 84 | 85 | endmodule -------------------------------------------------------------------------------- /Clock Divider/ClkDiv.v: -------------------------------------------------------------------------------- 1 | module ClkDiv #( parameter RATIO_WIDTH = 8 ) 2 | ( input wire i_ref_clk , 3 | input wire i_rst_n , 4 | input wire i_clk_en , 5 | input wire [RATIO_WIDTH-1:0] i_div_ratio , 6 | output reg o_div_clk ); 7 | 8 | reg flag; // for non-50% duty cycle in case of odd ratio 9 | reg div_clk; 10 | reg [RATIO_WIDTH-1:0] counter; 11 | 12 | wire [RATIO_WIDTH-1:0] half; 13 | wire CLK_DIV_EN; // the actual enable signal for the divider 14 | wire odd; // defining the type of the ratio 15 | wire even_toggle; // condition when the even ratio toggles 16 | wire odd_toggle_high; // condition when the odd ratio toggles HL 17 | wire odd_toggle_low; // condition when the odd ratio toggles LH 18 | wire toggling_conditions; // conditions of toggeling combined 19 | 20 | 21 | // generating for ratio = 0 or 1 22 | always @(*) 23 | begin 24 | if(CLK_DIV_EN) 25 | o_div_clk = div_clk; 26 | else 27 | o_div_clk = i_ref_clk; 28 | end 29 | 30 | // sequential always block 31 | always @(posedge i_ref_clk, negedge i_rst_n) 32 | begin 33 | // reset state 34 | if(!i_rst_n) begin 35 | div_clk <= 0; 36 | counter <= 0; 37 | flag <= 0; 38 | end 39 | // enabled state 40 | else if(CLK_DIV_EN) 41 | begin 42 | if(toggling_conditions) 43 | begin 44 | div_clk <= ~div_clk; 45 | flag <= ~flag; 46 | counter <= 'b0; 47 | end 48 | else 49 | begin 50 | counter <= counter+1'b1; 51 | end 52 | end 53 | 54 | // not enabled state 55 | else 56 | begin 57 | div_clk <= 'b0; 58 | end 59 | end 60 | 61 | // corner case resolve 62 | assign CLK_DIV_EN = (i_clk_en && // if clock divider is enabled 63 | (i_div_ratio != 'b0) && // if the divider ratio not equal zero 64 | (i_div_ratio != 'b1) ); // if the divider ratio not equal one 65 | 66 | // whether the ratio odd or even 67 | assign odd = (i_div_ratio[0]); 68 | 69 | // whether the counter reaches half of the ratio 70 | assign half = (i_div_ratio/2) - 'b1; 71 | 72 | assign even_toggle = (!odd) && (counter == half); 73 | assign odd_toggle_high = (odd) && (flag) && (counter == half); 74 | assign odd_toggle_low = (odd) && (!flag) &&( counter == (half+'b1)); 75 | assign toggling_conditions = even_toggle || odd_toggle_high || odd_toggle_low; 76 | 77 | endmodule 78 | 79 | 80 | -------------------------------------------------------------------------------- /Asynchronous FIFO/ASYNC_FIFO.v: -------------------------------------------------------------------------------- 1 | module ASYNC_FIFO #( parameter DATA_WIDTH = 8, parameter MEM_DEPTH = 8, parameter PTR_WIDTH = ($clog2(MEM_DEPTH)+1) ) 2 | ( input wire i_Wclk , 3 | input wire i_Wrst_n , 4 | input wire i_Winc , 5 | input wire i_Rclk , 6 | input wire i_Rrst_n , 7 | input wire i_Rinc , 8 | input wire [DATA_WIDTH-1:0] i_Wdata , 9 | output wire o_full , 10 | output wire [DATA_WIDTH-1:0] o_Rdata , 11 | output wire o_empty ); 12 | 13 | // internal signal declaration 14 | wire [PTR_WIDTH-2:0] x_waddr , x_raddr; 15 | wire [PTR_WIDTH-1:0] x_wptr , x_rptr; 16 | wire [PTR_WIDTH-1:0] x_wptr_conv , x_rptr_conv; 17 | wire [PTR_WIDTH-1:0] x_wq2_rptr , x_rq2_wptr; 18 | 19 | // FIFO memory buffer 20 | FIFO_MEM_CNTRL #( .DATA_WIDTH(DATA_WIDTH), .MEM_DEPTH(MEM_DEPTH), .PTR_WIDTH(PTR_WIDTH) ) U0_FIFO_MEM_CNTRL ( 21 | .W_clk_en ((!o_full)&i_Winc) , 22 | .W_data (i_Wdata) , 23 | .W_addr (x_waddr) , 24 | .W_clk (i_Wclk) , 25 | .W_rst (i_Wrst_n) , 26 | .R_data (o_Rdata) , 27 | .R_addr (x_raddr) ); 28 | 29 | // FIFO empty and read address generator 30 | FIFO_RD #( .PTR_WIDTH(PTR_WIDTH) ) U0_FIFO_RD ( 31 | .CLK (i_Rclk) , 32 | .RST (i_Rrst_n) , 33 | .rinc (i_Rinc) , 34 | .wptr_conv (x_rq2_wptr) , 35 | .rptr_conv (x_rptr_conv) , 36 | .rptr (x_rptr) , 37 | .raddr (x_raddr) , 38 | .empty (o_empty) ); 39 | 40 | // FIFO full and write address generator 41 | FIFO_WR #( .PTR_WIDTH(PTR_WIDTH) ) U0_FIFO_WR ( 42 | .CLK (i_Wclk) , 43 | .RST (i_Wrst_n) , 44 | .winc (i_Winc) , 45 | .wptr_conv (x_wptr_conv) , 46 | .rptr_conv (x_wq2_rptr) , 47 | .wptr (x_wptr) , 48 | .waddr (x_waddr) , 49 | .full (o_full) ); 50 | 51 | // Write-to-Read Synchronizer 52 | DF_SYNC #(.BUS_WIDTH(PTR_WIDTH)) U0_DF_SYNC ( 53 | .CLK (i_Rclk) , 54 | .RST (i_Rrst_n) , 55 | .ASYNC (x_wptr_conv) , 56 | .SYNC (x_rq2_wptr) ); 57 | 58 | // Read-to-Write Synchronizer 59 | DF_SYNC #(.BUS_WIDTH(PTR_WIDTH)) U1_DF_SYNC ( 60 | .CLK (i_Wclk) , 61 | .RST (i_Wrst_n) , 62 | .ASYNC (x_rptr_conv) , 63 | .SYNC (x_wq2_rptr) ); 64 | 65 | // Write-PTR Gray Converter 66 | GRAY_CONV #(.PTR_WIDTH(PTR_WIDTH)) U0_GRAY_CONV ( 67 | .bit_ptr (x_wptr) , 68 | .gray_ptr (x_wptr_conv) ); 69 | 70 | // Read-PTR Gray Converter 71 | GRAY_CONV #(.PTR_WIDTH(PTR_WIDTH)) U1_GRAY_CONV ( 72 | .bit_ptr (x_rptr) , 73 | .gray_ptr (x_rptr_conv) ); 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /Data Synchronizer/README.md: -------------------------------------------------------------------------------- 1 | # Data Synchronizer Block 2 | 3 | ## Overview 4 | The Data Synchronizer block is a critical component in our multi-clock domain mini-processor design. It plays a vital role in managing data synchronization across different clock domains, solving the complex challenge of Clock Domain Crossing (CDC). 5 | 6 | ## Block Description 7 | The Data Synchronizer employs a Synchronized MUX-Select Synchronization Scheme, which effectively synchronizes multiple bits and ensures reliable data transfer between asynchronous clock domains. 8 | 9 | ## Block Interface 10 | The Data Synchronizer block has the following interface: 11 | 12 |

13 | Block Interface 14 |

15 | 16 | - **Inputs:** 17 | - `unsync_bus`: The unsynchronized data bus to be synchronized across clock domains. 18 | - `bus_enable`: Control signal indicating when data synchronization is required. 19 | - `CLK`: Clock signal for the sequential elements within the Data Synchronizer. 20 | - `RST`: Asynchronous active-low reset signal to clear the internal state. 21 | 22 | - **Outputs:** 23 | - `sync_bus`: The synchronized data bus, ensuring that data arrives reliably in the destination clock domain. 24 | - `enable_pulse`: Control signal indicating the synchronization process has occurred, enabling subsequent actions in the design. 25 | 26 | > For a better understanding of how the Data Synchronizer block is implemented in RTL (Register-Transfer Level) code, please refer to the [`DATA_SYNC.v`](.DATA_SYNC.v) file in this repository. 27 | 28 | ## Elaborated Design 29 | The Data Synchronizer block comprises the following key components: 30 | 31 | ### Multi Flip-Flop Enable Synchronizer ([multi_ff.v](./multi_ff.v)) 32 | This component ensures that data is correctly synchronized across clock domains while minimizing metastability issues. 33 | 34 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/c6213b85-e7b5-4ce9-afc1-73b150846e64) 35 | 36 | ### Pulse Generator Block ([DS_PULSE.v](./DS_PULSE.v)) 37 | Responsible for generating a pulse signal (`enable_pulse`) that signifies the successful synchronization of data. 38 | 39 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/9fdcf169-9dfc-446a-a482-d4231a1cc87c) 40 | 41 | ## Synchronized MUX-Select Synchronization Scheme ([sync_bus.v](./sync_bus.v)) 42 | The Data Synchronizer employs a unique synchronization scheme that overcomes Clock Domain Crossing challenges. This scheme ensures data integrity and consistency between different clock domains, making it a crucial component in our design. 43 | 44 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/88633b99-573b-430d-83b5-ba01889e551f) 45 | 46 | ## [Testbench](./DATA_SYNC_tb.v) 47 | 48 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/561ab148-fd5c-4b52-afff-a646835774e1) 49 | 50 | ``` 51 | [PASSED] Bus Width = 8, No. of Stages = 2 52 | ``` 53 | -------------------------------------------------------------------------------- /UART/UART TX/FSM.v: -------------------------------------------------------------------------------- 1 | module FSM #( parameter WIDTH = 8 ) 2 | ( input wire Data_Valid, 3 | input wire PAR_EN, 4 | input wire ser_done, 5 | input wire CLK, 6 | input wire RST, 7 | output reg ser_en, 8 | output reg busy, 9 | output reg [1:0] mux_sel ); 10 | 11 | // FSM States Registers 12 | reg [2:0] current_state, next_state; 13 | 14 | // state encoding 15 | localparam IDLE = 3'b000; 16 | localparam start_bit = 3'b001; 17 | localparam ser_data = 3'b010; 18 | localparam parity_bit = 3'b011; 19 | localparam stop_bit = 3'b100; 20 | 21 | // mux selector encoding 22 | localparam mux_start = 2'b00; 23 | localparam mux_serial = 2'b01; 24 | localparam mux_parity = 2'b10; 25 | localparam mux_stop = 2'b11; 26 | 27 | // state transition always block 28 | always @(posedge CLK, negedge RST) 29 | begin 30 | if(!RST) 31 | current_state <= IDLE; 32 | else 33 | current_state <= next_state; 34 | end 35 | 36 | // next state logic always block 37 | always @(*) 38 | begin 39 | case(current_state) 40 | IDLE: begin 41 | if(Data_Valid) 42 | next_state = start_bit; 43 | else 44 | next_state = IDLE; 45 | end 46 | start_bit: begin 47 | next_state = ser_data; 48 | end 49 | ser_data: begin 50 | if(ser_done) 51 | begin 52 | if(PAR_EN) 53 | next_state = parity_bit; 54 | else 55 | next_state = stop_bit; 56 | end 57 | else 58 | next_state = ser_data; 59 | end 60 | parity_bit: begin 61 | next_state = stop_bit; 62 | end 63 | stop_bit: begin 64 | // This condition allows the UART TX to receive two successive bytes or more without returning to IDLE 65 | /*if(Data_Valid): 66 | next_state = start_bit; 67 | else*/ 68 | next_state = IDLE; 69 | end 70 | default begin 71 | next_state = IDLE; 72 | end 73 | endcase 74 | end 75 | 76 | // output logic always block 77 | always @(*) 78 | begin 79 | case(current_state) 80 | IDLE: begin 81 | busy = 1'b0; 82 | ser_en = 1'b0; 83 | mux_sel = mux_stop; 84 | end 85 | start_bit: begin 86 | busy = 1'b1; 87 | ser_en = 1'b1; 88 | mux_sel = mux_start; 89 | end 90 | ser_data: begin 91 | busy = 1'b1; 92 | ser_en = 1'b1; 93 | mux_sel = mux_serial; 94 | end 95 | parity_bit: begin 96 | busy = 1'b1; 97 | ser_en = 1'b0; 98 | mux_sel = mux_parity; 99 | end 100 | stop_bit: begin 101 | busy = 1'b1; 102 | ser_en = 1'b0; 103 | mux_sel = mux_stop; 104 | end 105 | default begin 106 | busy = 1'b0; 107 | ser_en = 1'b0; 108 | mux_sel = mux_stop; 109 | end 110 | endcase 111 | end 112 | endmodule 113 | -------------------------------------------------------------------------------- /Data Synchronizer/DATA_SYNC_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | /*******************************************************************/ 3 | // To try different Bus Width & No. of Stages, 4 | // you can changes the parameter values in line 15 and re-run 5 | /*******************************************************************/ 6 | 7 | module DATA_SYNC_tb(); 8 | 9 | 10 | /*******************************************************************/ 11 | ///////////////////// TB Signals Declaration //////////////////////// 12 | /*******************************************************************/ 13 | parameter CLK_PERIOD = 10 , HALF_PERIOD = 5; 14 | parameter HIGH = 1 , LOW = 0; 15 | parameter BUS_WIDTH = 8 , NUM_STAGES = 2; 16 | 17 | defparam DUT.BUS_WIDTH = BUS_WIDTH; 18 | defparam DUT.NUM_STAGES = NUM_STAGES; 19 | 20 | 21 | // interface ports 22 | reg CLK ; 23 | reg RST ; 24 | reg bus_enable ; 25 | reg [BUS_WIDTH-1:0] unsync_bus ; 26 | wire [BUS_WIDTH-1:0] sync_bus ; 27 | wire enable_bus ; 28 | 29 | // test value 30 | reg [BUS_WIDTH-1:0] test_var; 31 | 32 | 33 | /*******************************************************************/ 34 | ////////////////////////// Initial Block //////////////////////////// 35 | /*******************************************************************/ 36 | initial 37 | begin 38 | $dumpfile("BIT_SYNC.vcd"); 39 | $dumpvars; 40 | 41 | initialize(); 42 | reset(); 43 | 44 | test_var = 'haa; 45 | latency_test(test_var); 46 | 47 | #(2*CLK_PERIOD) $stop; 48 | end 49 | 50 | /*******************************************************************/ 51 | ////////////////////////////// TASKS //////////////////////////////// 52 | /*******************************************************************/ 53 | task reset; 54 | begin 55 | RST = LOW; 56 | #HALF_PERIOD 57 | RST = HIGH; 58 | #HALF_PERIOD; 59 | end 60 | endtask 61 | /********************************/ 62 | task initialize; 63 | begin 64 | CLK = HIGH; 65 | RST = HIGH; 66 | bus_enable = LOW; 67 | unsync_bus = LOW; 68 | end 69 | endtask 70 | /********************************/ 71 | task latency_test; 72 | input [BUS_WIDTH-1:0] test_value; 73 | 74 | begin 75 | reset(); 76 | @(posedge CLK) 77 | //#(0.3*CLK_PERIOD) 78 | unsync_bus = test_value; 79 | bus_enable = HIGH; 80 | #CLK_PERIOD 81 | #(NUM_STAGES*CLK_PERIOD) 82 | #HALF_PERIOD 83 | 84 | if(sync_bus == test_value) 85 | $display("[PASSED] Bus Width = %0d, No. of Stages = %0d",BUS_WIDTH,NUM_STAGES); 86 | else 87 | $display("[FAILED] Bus Width = %0d, No. of Stages = %0d",BUS_WIDTH,NUM_STAGES); 88 | end 89 | endtask 90 | 91 | /*******************************************************************/ 92 | ///////////////////////// Clock Generator /////////////////////////// 93 | /*******************************************************************/ 94 | always #HALF_PERIOD CLK = ~CLK; 95 | 96 | /*******************************************************************/ 97 | //////////////////////// DUT Instantiation ////////////////////////// 98 | /*******************************************************************/ 99 | DATA_SYNC DUT ( 100 | .dest_clk (CLK) , 101 | .dest_rst (RST) , 102 | .bus_enable (bus_enable) , 103 | .unsync_bus (unsync_bus) , 104 | .sync_bus (sync_bus) , 105 | .enable_pulse (enable_bus) ); 106 | 107 | endmodule 108 | -------------------------------------------------------------------------------- /System Controller/README.md: -------------------------------------------------------------------------------- 1 | # System Controller Block 2 | 3 | ## Overview 4 | The System Controller is the central hub of our Low Power Configurable Multi-Clock Digital System. It orchestrates various operations based on commands received from the master via the UART_RX interface and ensures the results are communicated back to the master through the UART_TX interface. This versatile component handles a wide range of operations, including ALU and Register File operations. 5 | 6 | ## Block Description 7 | The System Controller is the brain behind our digital system, responsible for interpreting and executing a multitude of commands from the master. These commands encompass ALU operations, Register File operations, and more. 8 | 9 | ## Supported Operations 10 | The System Controller supports a comprehensive set of operations, including but not limited to: 11 | - Arithmetic and Logic Unit (ALU) Operations: 12 | - Addition 13 | - Subtraction 14 | - Multiplication 15 | - Division 16 | - Logical Operations (AND, OR, NAND, NOR, XOR, XNOR) 17 | - Comparisons (A = B, A > B) 18 | - Bit Shifting (A >> 1, A << 1) 19 | - Register File Operations: 20 | - Register File Write 21 | - Register File Read 22 | 23 | ## Supported Commands 24 | To execute these operations, the System Controller interprets various commands, including: 25 | 1. Register File Write Command (3 frames) 26 | 2. Register File Read Command (2 frames) 27 | 3. ALU Operation Command with Operand (4 frames) 28 | 4. ALU Operation Command with No Operand (2 frames) 29 | 30 | ## Operation Workflow 31 | The workflow of the System Controller is as follows: 32 | 1. The master (testbench) sends different commands (Register File Operations, ALU Operations) via UART_RX. 33 | 2. The System Controller receives these command frames. 34 | 3. The System Controller processes the commands, performing the requested operations using the ALU and Register File. 35 | 4. Once the operation is completed, the System Controller sends the result back to the master through UART_TX. 36 | 37 | ## Block Interface 38 | 39 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/52fd0d94-32a6-4a23-ad48-1a7345c30097) 40 | > Not all the ports are included in the photo 41 | 42 | ### Inputs 43 | 44 | The System Controller block receives the following inputs: 45 | 46 | - **Clock and Reset Signals:** 47 | - `CLK`: The Clock Signal. 48 | - `RST`: Active Low Reset. 49 | 50 | - **ALU Inputs:** 51 | - `ALU_OUT`: ALU Result Bus (Width: ALU_WIDTH). 52 | - `OUT_Valid`: ALU Result Valid Signal. 53 | 54 | - **UART_RX Inputs:** 55 | - `RX_P_Data`: UART_RX Data Bus (Width: DATA_BUS_WIDTH). 56 | - `RX_D_VLD`: RX Data Valid Signal. 57 | 58 | - **Register File Inputs:** 59 | - `RdData`: Read Data Bus (Width: DATA_BUS_WIDTH). 60 | - `RdData_Valid`: Read Data Valid Signal. 61 | 62 | - **Clock Divider and Prescale Configuration:** 63 | - `Prescale_RX`: Configuration for Prescale Values (Width: DATA_BUS_WIDTH-3). 64 | - `FIFO_FULL`: FIFO Full Flag Signal. 65 | 66 | - **ALU Control Signals:** 67 | - `ALU_EN`: ALU Enable Signal. 68 | - `ALU_FUN`: ALU Function Signal (Width: ALUFN_WIDTH). 69 | 70 | - **Clock Management:** 71 | - `CLK_EN`: Clock Gate Enable Signal. 72 | 73 | - **Address and Memory Access:** 74 | - `Address`: Address Bus (Width: ADDR_WIDTH). 75 | - `WrEn`: Write Enable Signal. 76 | - `RdEn`: Read Enable Signal. 77 | 78 | ### Outputs 79 | 80 | The System Controller block provides the following outputs: 81 | 82 | - **Data Transfer:** 83 | - `WrData`: Write Data Bus (Width: DATA_BUS_WIDTH). 84 | - `TX_P_Data`: UART_TX Data Bus (Width: DATA_BUS_WIDTH). 85 | - `TX_D_VLD`: TX Data Valid Signal. 86 | 87 | - **Clock Divider Control:** 88 | - `clk_div_en`: Clock Divider Enable Signal. 89 | 90 | - **Clock Divider Output:** 91 | - `ClkDiv_RX`: Clock Divider Ratio for RX (Width: DATA_BUS_WIDTH-3). 92 | -------------------------------------------------------------------------------- /Clock Divider/ClkDiv_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ns 2 | 3 | module ClkDiv_tb (); 4 | 5 | /*******************************************/ 6 | /*************** PARAMETERS ****************/ 7 | /*******************************************/ 8 | parameter MAX_RATIO = 10; 9 | parameter RATIO_BIT = ($clog2(MAX_RATIO)+1); 10 | parameter CLK_PERIOD = 10; 11 | parameter HALF_PERIOD = 5; 12 | parameter HIGH = 1; 13 | parameter LOW = 0; 14 | 15 | /*******************************************************/ 16 | /*************** TB SIGNAL DECLARATIONS ****************/ 17 | /*******************************************************/ 18 | reg [RATIO_BIT-1:0] DIV_RATIO; 19 | reg CLK; 20 | reg RST; 21 | reg ENABLE; 22 | wire CLK_OUT; 23 | wire CLK_NEG; 24 | 25 | integer i; 26 | 27 | assign CLK_NEG = ~CLK_OUT; 28 | 29 | /**********************************************/ 30 | /*************** INITIAL BLOCK ****************/ 31 | /**********************************************/ 32 | initial 33 | begin 34 | $dumpfile("ClkDiv.vcd"); 35 | $dumpvars; 36 | initialize; 37 | reset; 38 | 39 | repeat(MAX_RATIO) 40 | begin 41 | divide_by(i); 42 | i = i + 1; 43 | end 44 | 45 | #(5*CLK_PERIOD) $stop; 46 | end 47 | 48 | /**************************************/ 49 | /*************** TASKS ****************/ 50 | /**************************************/ 51 | 52 | ///////////// 53 | task reset; 54 | begin 55 | RST = LOW; 56 | #HALF_PERIOD; 57 | RST = HIGH; 58 | #HALF_PERIOD; 59 | end 60 | endtask 61 | 62 | ////////////////// 63 | task initialize; 64 | begin 65 | DIV_RATIO = LOW; 66 | CLK = LOW; 67 | ENABLE = LOW; 68 | i = LOW; 69 | end 70 | endtask 71 | 72 | /////////////////// 73 | task divide_by; 74 | input [RATIO_BIT-1:0] ratio; 75 | begin 76 | reset; 77 | DIV_RATIO = ratio; 78 | ENABLE = HIGH; 79 | #(ratio*CLK_PERIOD); 80 | calc_period; 81 | #(ratio*CLK_PERIOD); 82 | ENABLE = LOW; 83 | end 84 | endtask 85 | /////////////////// 86 | task calc_period; 87 | real period,first,last; 88 | begin 89 | first = 0; 90 | last = 0; 91 | period = 0; 92 | if( (DIV_RATIO == 0 || DIV_RATIO == 1) ) 93 | begin 94 | @(posedge CLK_OUT) 95 | first = $realtime; 96 | @(posedge CLK_OUT) 97 | last = $realtime; 98 | @(negedge CLK_OUT) 99 | period = last - first; 100 | $display("[PASSED]: div ratio = %0d, clock period = %0dns, div clock period = %0dns",DIV_RATIO,CLK_PERIOD,period); 101 | end 102 | 103 | else 104 | begin 105 | wait(CLK_OUT); 106 | first = $realtime; 107 | wait(!CLK_OUT); 108 | wait(CLK_OUT); 109 | last = $realtime; 110 | wait(!CLK_OUT); 111 | period = last - first; 112 | 113 | if(period == DIV_RATIO*CLK_PERIOD) 114 | $display("[PASSED]: div ratio = %0d, clock period = %0dns, div clock period = %0dns",DIV_RATIO,CLK_PERIOD,period); 115 | else 116 | $display("[FAILED]: div ratio = %0d",DIV_RATIO); 117 | end 118 | end 119 | endtask 120 | 121 | /************************************************/ 122 | /*************** CLOCK GENERATOR ****************/ 123 | /************************************************/ 124 | always #HALF_PERIOD CLK = ~CLK; 125 | 126 | /**************************************************/ 127 | /*************** DUT INSTANTIATION ****************/ 128 | /**************************************************/ 129 | ClkDiv #(.RATIO_WIDTH(RATIO_BIT)) DUT ( .i_ref_clk(CLK), 130 | .i_rst_n(RST), 131 | .i_clk_en(ENABLE), 132 | .i_div_ratio(DIV_RATIO), 133 | .o_div_clk(CLK_OUT) ); 134 | endmodule 135 | 136 | 137 | -------------------------------------------------------------------------------- /Register File/README.md: -------------------------------------------------------------------------------- 1 | # Register File Block 2 | 3 | ## Overview 4 | The Register File is a critical component of our multi-clock domain mini-processor system. It serves as the primary storage for our processor's registers, enabling efficient data retrieval and manipulation during program execution. 5 | The Register File consists of 8 registers, each register of 16-bit width. 6 | 7 | 8 | ## Block Description 9 | The Register File block is responsible for the following key functions: 10 | 11 | - **Register Storage:** It provides storage for a set of registers, each capable of holding data of a specific width. 12 | 13 | - **Read Access:** The block supports read operations, allowing the processor to access the contents of registers as needed for computations. 14 | 15 | - **Write Access:** It also enables write operations, allowing the processor to update the contents of registers when required. 16 | 17 | - **Register Indexing:** The block accepts register address inputs, indicating the target registers for read or write operations. 18 | 19 | ## Block Interface 20 | The Register File block has the following interface: 21 | 22 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/6eaceccb-6479-44e3-a62a-c417cd7c46ff) 23 | 24 | - **Inputs:** 25 | - `WrData`: 8-bits Data input for write operations. 26 | - `WrEn`: Control signal enabling write operations. 27 | - `RdEn`: Control signal enabling read operations. 28 | - `Address`: Register address input for read or write operations. 29 | - `CLK`: Clock signal for sequential elements. 30 | - `RST`: Active-low asynchronous reset signal to clear the sequential elements. 31 | 32 | - **Outputs:** 33 | - `RdData`: Data output for read operations. 34 | - `RdData_Valid`: Status flag indicating that the data read from the register is valid. 35 | - `REG0`: The register contents at address 0x0, used by the system to store ALU Operand A 36 | - `REG1`: The register contents at address 0x1, used by the system to store ALU Operand B 37 | - `REG2`: The register contents at address 0x2, used by the system to store UART Config 38 | - `REG3`: The register contents at address 0x3, used by the system to store Div Ratio 39 | 40 | > For a better understanding of how the Rgister File block is implemented in RTL (Register-Transfer Level) code, please refer to the [`RegFile.v`](./RegFile.v) file in this repository. 41 | 42 | 43 | ## Usage 44 | To effectively utilize the Register File block within our system, follow these steps: 45 | 46 | 1. Use the `Address` input to specify which registers you want to read data from or write data into. 47 | 48 | 2. The `RdData` output will provide the data stored in the specified register when the `RdEn` signal is asserted. 49 | 50 | 3. To update the contents of a register, set the `Address` input to the target register, provide the data to be written in `WrData`, and assert the `WrEn` signal. 51 | 52 | 4. Only one operation (read or write) can be evaluated at a time. 53 | 54 | ## Elaborated Design 55 | 56 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/5fc04b56-df8f-46d0-8ee3-ed82ba8c4ff3) 57 | 58 | ## [Testbench](./RegFile_tb.v) 59 | 60 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/da78748f-1381-44da-b3cf-c388d6be6760) 61 | 62 | ``` 63 | /******************** Writing Testcases **************************/ 64 | [PASSED]: Write in Address 000 65 | [PASSED]: Write in Address 001 66 | [PASSED]: Write in Address 010 67 | [PASSED]: Write in Address 011 68 | [PASSED]: Write in Address 100 69 | [PASSED]: Write in Address 101 70 | [PASSED]: Write in Address 110 71 | [PASSED]: Write in Address 111 72 | /******************** Reading Testcases **************************/ 73 | [PASSED]: Read from Address 000 74 | [PASSED]: Read from Address 001 75 | [PASSED]: Read from Address 010 76 | [PASSED]: Read from Address 011 77 | [PASSED]: Read from Address 100 78 | [PASSED]: Read from Address 101 79 | [PASSED]: Read from Address 110 80 | [PASSED]: Read from Address 111 81 | /******************** Enables Testcases **************************/ 82 | [PASSED]: Writing rejected when WrEn = 1 RdEn = 1 83 | [PASSED]: Reading rejected when WrEn = 1 RdEn = 1 84 | [PASSED]: Writing rejected when WrEn = 0 RdEn = 0 85 | [PASSED]: Reading rejected when WrEn = 0 RdEn = 0 86 | ``` 87 | 88 | 89 | -------------------------------------------------------------------------------- /UART/UART RX/UART_RX.v: -------------------------------------------------------------------------------- 1 | module UART_RX #(parameter WIDTH = 8 , 2 | PAR_MAX = 11 , 3 | MAX_PRESCALE = 32 , 4 | FRAME_WIDTH = ($clog2(PAR_MAX) + 1) , 5 | PRSC_WIDTH = ($clog2(MAX_PRESCALE)+1) )( 6 | 7 | input wire i_clk , 8 | input wire i_rst_n , 9 | input wire [PRSC_WIDTH-1:0] i_prescale , 10 | input wire i_serial_data , 11 | input wire i_parity_enable , 12 | input wire i_parity_type , 13 | output wire o_data_valid , 14 | output wire o_parity_error , 15 | output wire o_stop_error , 16 | output wire [WIDTH-1:0] o_parallel_data ); 17 | 18 | // internal signal declaration 19 | wire [FRAME_WIDTH-2:0] x_bit_cnt ; // from edge_bit_counter to FSM 20 | wire [PRSC_WIDTH-2:0] x_edge_cnt ; // from edge_bit_counter to data_sampling 21 | wire x_samp_done ; // from edge_bit_counter to FSM 22 | wire x_sampled_bit ; // from data_sampling to parity_check, start_check, stop_check & deserializer 23 | //wire o_parity_error ; // from parity_check to FSM 24 | //wire o_stop_error ; // from stop_check to FSM 25 | wire x_strt_glitch ; // from start_check to FSM 26 | wire x_samp_cnt_en ; // from FSM to data_sampling & edge_bit_counter 27 | wire x_deser_en ; // from FSM to deserializer 28 | wire x_success_sig ; // from FSM to deserializer 29 | wire x_par_chk_en ; // from FSM to parity_check 30 | wire x_strt_chk_en ; // from FSM to start_check 31 | wire x_stp_chk_en ; // from FSM to stop_check 32 | wire [WIDTH-1:0] x_sampled_data; // from deserializer to parity_check 33 | 34 | UART_RX_FSM U0_FSM ( 35 | .clk (i_clk) , 36 | .rst (i_rst_n) , 37 | .RX_IN (i_serial_data) , 38 | .bit_cnt (x_bit_cnt) , 39 | .done_sampling (x_samp_done) , 40 | .par_en (i_parity_enable) , 41 | .par_err (o_parity_error) , 42 | .start_glitch (x_strt_glitch) , 43 | .stop_err (o_stop_error) , 44 | .par_check_en (x_par_chk_en) , 45 | .start_check_en (x_strt_chk_en) , 46 | .stop_check_en (x_stp_chk_en) , 47 | .samp_cnt_en (x_samp_cnt_en) , 48 | .deser_en (x_deser_en) , 49 | .data_valid (x_success_sig) ); 50 | 51 | edge_bit_counter U0_edge_bit_counter ( 52 | .clk (i_clk) , 53 | .rst (i_rst_n) , 54 | .enable (x_samp_cnt_en) , 55 | .prescale (i_prescale) , 56 | .parity_en (i_parity_enable) , 57 | .bit_cnt (x_bit_cnt) , 58 | .edge_max (x_samp_done) , 59 | .edge_cnt (x_edge_cnt) ); 60 | 61 | data_sampling U0_data_sampling ( 62 | .clk (i_clk) , 63 | .rst (i_rst_n) , 64 | .serial_data (i_serial_data) , 65 | .counter (x_edge_cnt) , 66 | .enable (x_samp_cnt_en) , 67 | .sampled_bit (x_sampled_bit) , 68 | .prescale (i_prescale[PRSC_WIDTH-1:1])); 69 | 70 | 71 | deserializer U0_deserializer ( 72 | .clk (i_clk) , 73 | .rst (i_rst_n) , 74 | .sampled_bit (x_sampled_bit) , 75 | .enable (x_deser_en) , 76 | .success (x_success_sig) , 77 | .data_valid (o_data_valid) , 78 | .sampled_stream (x_sampled_data) , 79 | .parallel_data (o_parallel_data) ); 80 | 81 | 82 | start_check U0_start_check ( 83 | .enable (x_strt_chk_en) , 84 | .sampled_start_bit (x_sampled_bit) , 85 | .glitch (x_strt_glitch) ); 86 | 87 | stop_check U0_stop_check ( 88 | .enable (x_stp_chk_en) , 89 | .sampled_stop_bit (x_sampled_bit) , 90 | .error (o_stop_error) ); 91 | 92 | parity_check U0_parity_check ( 93 | .data (x_sampled_data) , 94 | .par_type (i_parity_type) , 95 | .par_bit (x_sampled_bit) , 96 | .enable (x_par_chk_en) , 97 | .error (o_parity_error) ); 98 | 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /Asynchronous FIFO/ASYNC_FIFO_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps 2 | 3 | module ASYNC_FIFO_tb (); 4 | 5 | /*******************************************************************/ 6 | ///////////////////// TB Signals Declaration //////////////////////// 7 | /*******************************************************************/ 8 | parameter DATA_WIDTH = 8 , MEM_in_DEPTH = 8 , PTR_WIDTH = ($clog2(MEM_in_DEPTH)+1); 9 | parameter W_CLK_PERIOD = 10 , W_HALF_PERIOD = 5 ; 10 | parameter R_CLK_PERIOD = 25 , R_HALF_PERIOD = 12.5 ; 11 | parameter HIGH = 1 , LOW = 0 ; 12 | 13 | defparam DUT.MEM_DEPTH = MEM_in_DEPTH; 14 | // interface ports 15 | reg W_CLK ; 16 | reg W_RST ; 17 | reg W_INC ; 18 | reg R_CLK ; 19 | reg R_RST ; 20 | reg R_INC ; 21 | reg [DATA_WIDTH-1:0] W_DATA ; 22 | wire FULL ; 23 | wire [DATA_WIDTH-1:0] R_DATA ; 24 | wire EMPTY ; 25 | 26 | // testing MEM_inory 27 | reg [DATA_WIDTH-1:0] MEM_in [2*MEM_in_DEPTH-1:0]; 28 | reg [DATA_WIDTH-1:0] MEM_out [2*MEM_in_DEPTH-1:0]; 29 | integer i,j,o; 30 | 31 | /*******************************************************************/ 32 | ////////////////////////// Initial Block //////////////////////////// 33 | /*******************************************************************/ 34 | initial 35 | begin 36 | $dumpfile("ASYNC_FIFO.vcd"); 37 | $dumpvars; 38 | 39 | initialize(); 40 | for(i = 0; i < 2*MEM_in_DEPTH; i = i + 1) 41 | begin 42 | MEM_in[i] = $random %(2**DATA_WIDTH - 1); 43 | end 44 | end 45 | 46 | // read initial block 47 | initial 48 | begin 49 | r_reset(); 50 | for(j = 0; j < 2*MEM_in_DEPTH; j = j + 1) 51 | begin 52 | wait(!EMPTY) 53 | @(negedge R_CLK) 54 | MEM_out[j] = R_DATA; 55 | R_INC = HIGH; 56 | #R_CLK_PERIOD 57 | R_INC = LOW; 58 | #R_CLK_PERIOD; 59 | end 60 | #(R_CLK_PERIOD) 61 | for(o = 0; o < 2*MEM_in_DEPTH; o = o + 1) 62 | begin 63 | if(MEM_out[o] == MEM_in[o]) 64 | $display("MEMORY[%2d]: CAPTURE PASSED",o); 65 | else 66 | $display("MEMORY[%2d]: CAPTURE FAILED",o); 67 | end 68 | #(10*R_CLK_PERIOD) $stop; 69 | end 70 | 71 | // write initial block 72 | initial 73 | begin 74 | w_reset(); 75 | for(i = 0; i < 2*MEM_in_DEPTH; i = i + 1) 76 | begin 77 | wait(!FULL) 78 | @(negedge W_CLK) 79 | W_INC = HIGH; 80 | W_DATA = MEM_in[i]; 81 | #W_CLK_PERIOD 82 | W_INC = LOW; 83 | #W_CLK_PERIOD; 84 | end 85 | end 86 | 87 | /*******************************************************************/ 88 | ////////////////////////////// TASKS //////////////////////////////// 89 | /*******************************************************************/ 90 | task w_reset; 91 | begin 92 | W_RST = LOW; 93 | #W_HALF_PERIOD 94 | W_RST = HIGH; 95 | #W_HALF_PERIOD; 96 | end 97 | endtask 98 | /********************************/ 99 | task r_reset; 100 | begin 101 | R_RST = LOW; 102 | #R_HALF_PERIOD 103 | R_RST = HIGH; 104 | #R_HALF_PERIOD; 105 | end 106 | endtask 107 | /********************************/ 108 | task initialize; 109 | begin 110 | W_CLK = LOW; 111 | W_RST = LOW; 112 | W_INC = LOW; 113 | R_CLK = LOW; 114 | R_RST = LOW; 115 | R_INC = LOW; 116 | W_DATA = LOW; 117 | end 118 | endtask 119 | /********************************/ 120 | 121 | /*******************************************************************/ 122 | ///////////////////////// Clock Generator /////////////////////////// 123 | /*******************************************************************/ 124 | always #W_HALF_PERIOD W_CLK = ~W_CLK; 125 | always #R_HALF_PERIOD R_CLK = ~R_CLK; 126 | 127 | /*******************************************************************/ 128 | //////////////////////// DUT Instantiation ////////////////////////// 129 | /*******************************************************************/ 130 | 131 | ASYNC_FIFO DUT ( 132 | .i_Wclk (W_CLK) , 133 | .i_Wrst_n (W_RST) , 134 | .i_Winc (W_INC) , 135 | .i_Rclk (R_CLK) , 136 | .i_Rrst_n (R_RST) , 137 | .i_Rinc (R_INC) , 138 | .i_Wdata (W_DATA) , 139 | .o_full (FULL) , 140 | .o_Rdata (R_DATA) , 141 | .o_empty (EMPTY) ); 142 | 143 | endmodule 144 | -------------------------------------------------------------------------------- /BACKEND/Synthesis/power.rpt: -------------------------------------------------------------------------------- 1 | Loading db file '/home/IC/tsmc_fb_cl013g_sc/aci/sc-m/synopsys/scmetro_tsmc_cl013g_rvt_ss_1p08v_125c.db' 2 | Information: Propagating switching activity (low effort zero delay simulation). (PWR-6) 3 | Warning: Design has unannotated primary inputs. (PWR-414) 4 | Warning: Design has unannotated sequential cell outputs. (PWR-415) 5 | 6 | **************************************** 7 | Report : power 8 | -hier 9 | -analysis_effort low 10 | Design : SYS_TOP 11 | Version: K-2015.06 12 | Date : Mon Sep 25 22:32:08 2023 13 | **************************************** 14 | 15 | 16 | Library(s) Used: 17 | 18 | scmetro_tsmc_cl013g_rvt_ss_1p08v_125c (File: /home/IC/tsmc_fb_cl013g_sc/aci/sc-m/synopsys/scmetro_tsmc_cl013g_rvt_ss_1p08v_125c.db) 19 | 20 | 21 | Operating Conditions: scmetro_tsmc_cl013g_rvt_ss_1p08v_125c Library: scmetro_tsmc_cl013g_rvt_ss_1p08v_125c 22 | Wire Load Model Mode: top 23 | 24 | 25 | Global Operating Voltage = 1.08 26 | Power-specific unit information : 27 | Voltage Units = 1V 28 | Capacitance Units = 1.000000pf 29 | Time Units = 1ns 30 | Dynamic Power Units = 1mW (derived from V,C,T units) 31 | Leakage Power Units = 1pW 32 | 33 | 34 | -------------------------------------------------------------------------------- 35 | Switch Int Leak Total 36 | Hierarchy Power Power Power Power % 37 | -------------------------------------------------------------------------------- 38 | SYS_TOP 1.01e-02 0.302 1.35e+07 0.326 100.0 39 | U0_ClkGate (ClkGate) 3.07e-03 5.07e-03 2.04e+04 8.16e-03 2.5 40 | U0_UART_TX (UART_TX) 2.04e-04 1.58e-04 5.95e+05 9.58e-04 0.3 41 | U0_MUX (MUX) 0.000 0.000 2.27e+04 2.27e-05 0.0 42 | U0_parity_calc (parity_calc) 0.000 4.67e-05 2.20e+05 2.67e-04 0.1 43 | U0_FSM (FSM) 0.000 1.75e-05 1.01e+05 1.18e-04 0.0 44 | U0_serializer (serializer) 0.000 7.53e-05 2.43e+05 3.18e-04 0.1 45 | U0_PULSE_GEN (PULSE_GEN_0) 0.000 5.85e-06 1.35e+04 1.93e-05 0.0 46 | U1_ClkDiv (ClkDiv) 7.22e-05 7.99e-04 6.32e+05 1.50e-03 0.5 47 | add_74 (ClkDiv_DW01_inc_1) 0.000 0.000 8.96e+04 8.96e-05 0.0 48 | add_50 (ClkDiv_DW01_inc_0) 5.44e-06 1.93e-05 9.73e+04 1.22e-04 0.0 49 | U0_ClkDiv (ClkDiv_RATIO_WIDTH6) 2.18e-04 5.31e-04 4.95e+05 1.24e-03 0.4 50 | U1_RST_SYNC (RST_SYNC_1) 8.12e-06 2.66e-04 2.35e+04 2.98e-04 0.1 51 | U0_RST_SYNC (RST_SYNC_0) 2.59e-05 4.49e-03 2.53e+04 4.54e-03 1.4 52 | U0_ASYNC_FIFO (ASYNC_FIFO_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4) 53 | 2.22e-03 0.112 2.14e+06 0.116 35.7 54 | U1_GRAY_CONV (GRAY_CONV_PTR_WIDTH4_1) 55 | 0.000 0.000 3.94e+04 3.94e-05 0.0 56 | U0_GRAY_CONV (GRAY_CONV_PTR_WIDTH4_0) 57 | 0.000 0.000 3.94e+04 3.94e-05 0.0 58 | U1_DF_SYNC (DF_SYNC_BUS_WIDTH4_1) 0.000 1.16e-02 8.27e+04 1.17e-02 3.6 59 | U0_DF_SYNC (DF_SYNC_BUS_WIDTH4_0) 0.000 4.68e-05 7.19e+04 1.19e-04 0.0 60 | U0_FIFO_WR (FIFO_WR_PTR_WIDTH4) 0.000 7.23e-03 1.72e+05 7.41e-03 2.3 61 | U0_FIFO_RD (FIFO_RD_PTR_WIDTH4) 0.000 2.89e-05 1.79e+05 2.08e-04 0.1 62 | U0_FIFO_MEM_CNTRL (FIFO_MEM_CNTRL_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4) 63 | 1.82e-03 9.30e-02 1.54e+06 9.63e-02 29.6 64 | U0_RegFile (RegFile_BUS_WIDTH8_DEPTH8_ADDR_WIDTH4_PAR_EN1_PAR_TYPE0_PRESCALE32_DIV_RATIO32) 65 | 1.92e-03 0.116 1.78e+06 0.120 36.8 66 | U0_ALU (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4) 67 | 0.000 2.47e-02 5.69e+06 3.04e-02 9.3 68 | div_24 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW_div_uns_1) 69 | 0.000 0.000 2.53e+06 2.53e-03 0.8 70 | mult_23 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW02_mult_0) 71 | 0.000 0.000 1.65e+06 1.65e-03 0.5 72 | add_21 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_add_0) 73 | 0.000 0.000 2.17e+05 2.17e-04 0.1 74 | sub_22 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_sub_0) 75 | 0.000 0.000 2.43e+05 2.43e-04 0.1 76 | U0_SYS_CTRL (SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4) 77 | 0.000 1.80e-02 6.22e+05 1.86e-02 5.7 78 | U0_DATA_SYNC (DATA_SYNC_BUS_WIDTH8) 0.000 1.74e-02 1.72e+05 1.75e-02 5.4 79 | U0_sync_bus (sync_bus) 0.000 1.16e-02 1.26e+05 1.17e-02 3.6 80 | U0_DS_pulse (DS_pulse) 0.000 2.89e-03 2.52e+04 2.92e-03 0.9 81 | inst_PULSE_GEN (PULSE_GEN_1) 0.000 1.45e-03 1.48e+04 1.46e-03 0.4 82 | U0_multi_ff (multi_ff) 0.000 2.89e-03 2.07e+04 2.91e-03 0.9 83 | U0_UART_RX (UART_RX_WIDTH8) 8.38e-04 2.66e-03 1.25e+06 4.75e-03 1.5 84 | U0_parity_check (parity_check) 0.000 0.000 1.15e+05 1.15e-04 0.0 85 | U0_stop_check (stop_check) 0.000 0.000 1.32e+04 1.32e-05 0.0 86 | U0_start_check (start_check) 0.000 0.000 2.78e+03 2.78e-06 0.0 87 | U0_deserializer (deserializer) 0.000 9.74e-04 2.37e+05 1.21e-03 0.4 88 | U0_data_sampling (data_sampling) 5.76e-05 2.82e-04 3.67e+05 7.06e-04 0.2 89 | U0_edge_bit_counter (edge_bit_counter) 90 | 2.09e-04 8.11e-04 3.37e+05 1.36e-03 0.4 91 | U0_FSM (UART_RX_FSM) 2.80e-04 5.77e-04 1.73e+05 1.03e-03 0.3 92 | 1 93 | -------------------------------------------------------------------------------- /SYS_TOP_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | 3 | module SYS_TOP_tb (); 4 | 5 | /*******************************************************************/ 6 | ///////////////////// TB Signals Declaration //////////////////////// 7 | /*******************************************************************/ 8 | parameter PRESCALE = 32; 9 | parameter BUS_WIDTH = 8 , FRAME = 11; 10 | parameter REF_CLK_PERIOD = 20, REF_HALF_PERIOD = (REF_CLK_PERIOD/2); 11 | parameter RX_CLK_PERIOD = 271.267, RX_HALF_PERIOD = (RX_CLK_PERIOD/2); 12 | parameter TX_CLK_PERIOD = (PRESCALE*RX_CLK_PERIOD), TX_HALF_PERIOD = (TX_CLK_PERIOD/2); 13 | parameter HIGH = 1, LOW = 0; 14 | 15 | // interface ports 16 | reg REF_CLK ; 17 | reg URX_CLK ; 18 | reg UTX_CLK ; 19 | reg RST ; 20 | reg RX_IN ; 21 | wire TX_OUT ; 22 | wire PAR_ERR ; 23 | wire STP_ERR ; 24 | 25 | // integers 26 | integer i,j; 27 | 28 | // registers 29 | reg [BUS_WIDTH-1:0] read_data; 30 | reg [FRAME-1:0] test_out; 31 | 32 | /*******************************************************************/ 33 | ////////////////////////// Initial Block //////////////////////////// 34 | /*******************************************************************/ 35 | initial 36 | begin 37 | $dumpfile("SYS_TOP.vcd"); 38 | $dumpvars; 39 | 40 | initialize(); 41 | reset(); 42 | 43 | @(negedge UTX_CLK) 44 | 45 | /**************************** CONFIG TESTCASE ***************************/ 46 | 47 | /************************ REG FILE WRITE TESTCASE ***********************/ 48 | // testcase (1) 49 | write_test('b10101010100,'b11000001000,'b11100011110); // 0xAA - 0x4 - 0x8F 50 | // testcase (2) 51 | write_test('b10101010100,'b10000001010,'b10101001010); // 0xAA - 0x5 - 0xA5 52 | // testcase (3) 53 | write_test('b10101010100,'b11000001110,'b11101111000); // 0xAA - 0x7 - 0xBC 54 | 55 | 56 | /************************ REG FILE READ TESTCASE ************************/ 57 | // testcase (1) 58 | read_test('b10101110110,'b11000001000); // 0xBB - 0x4 59 | // testcase (2) 60 | read_test('b10101110110,'b10000001010); // 0xBB - 0x5 61 | // testcase (3) 62 | read_test('b10101110110,'b11000001110); // 0xBB - 0x7 63 | 64 | /******** ALU OPERATION WITH OPERAND TESTCASE ********/ 65 | ALU_O_test('b10110011000,'b11011001000,'b11001100100,'b10000000000); // 0xCC - 100 - 50 - 0x0 66 | 67 | /***************** ALU OPERATION WITH NO OPERAND TESTCASE ****************/ 68 | ALU_NO_test('b10110111010, 'b11000000010); // 0xDD - 0x1 69 | ALU_NO_test('b10110111010, 'b11000000100); // 0xDD - 0x2 70 | ALU_NO_test('b10110111010, 'b10000000110); // 0xDD - 0x3 71 | 72 | #(50*TX_CLK_PERIOD) $stop; 73 | 74 | end 75 | 76 | /*******************************************************************/ 77 | ////////////////////////////// TASKS //////////////////////////////// 78 | /*******************************************************************/ 79 | task reset; 80 | begin 81 | RST = LOW; 82 | #RX_HALF_PERIOD 83 | RST = HIGH; 84 | #RX_HALF_PERIOD; 85 | end 86 | endtask 87 | /********************************/ 88 | task initialize; 89 | begin 90 | REF_CLK = LOW; 91 | URX_CLK = LOW; 92 | UTX_CLK = LOW; 93 | RST = LOW; 94 | RX_IN = HIGH; 95 | end 96 | endtask 97 | /********************************/ 98 | task write_test; 99 | input [FRAME-1:0] CMD,addr,data; 100 | begin 101 | passing_input(CMD); 102 | passing_input(addr); 103 | passing_input(data); 104 | end 105 | endtask 106 | /********************************/ 107 | task read_test; 108 | input [FRAME-1:0] CMD,addr; 109 | begin 110 | passing_input(CMD); 111 | passing_input(addr); 112 | end 113 | endtask 114 | /********************************/ 115 | task passing_input; 116 | input [FRAME-1:0] frame; 117 | begin 118 | for(i = 0; i < FRAME; i = i + 1) 119 | begin 120 | RX_IN = frame[i]; 121 | #(TX_CLK_PERIOD); 122 | end 123 | end 124 | endtask 125 | /********************************/ 126 | task ALU_O_test; 127 | input [FRAME-1:0] CMD,Operand_A,Operand_B,ALU_FUNC; 128 | begin 129 | passing_input(CMD); 130 | passing_input(Operand_A); 131 | passing_input(Operand_B); 132 | passing_input(ALU_FUNC); 133 | end 134 | endtask 135 | /********************************/ 136 | task ALU_NO_test; 137 | input [FRAME-1:0] CMD,ALU_FUNC; 138 | begin 139 | passing_input(CMD); 140 | passing_input(ALU_FUNC); 141 | end 142 | endtask 143 | /*******************************************************************/ 144 | ///////////////////////// Clock Generator /////////////////////////// 145 | /*******************************************************************/ 146 | always #REF_HALF_PERIOD REF_CLK = ~REF_CLK; 147 | always #RX_HALF_PERIOD URX_CLK =~URX_CLK; 148 | always #TX_HALF_PERIOD UTX_CLK =~UTX_CLK; 149 | 150 | /*******************************************************************/ 151 | //////////////////////// DUT Instantiation ////////////////////////// 152 | /*******************************************************************/ 153 | 154 | SYS_TOP #() DUT ( 155 | .i_ref_clk (REF_CLK) , 156 | .i_uart_clk (URX_CLK) , 157 | .i_rst_n (RST) , 158 | .i_rx_in (RX_IN) , 159 | .o_parity_err (PAR_ERR) , 160 | .o_stop_err (STP_ERR) , 161 | .o_tx_out (TX_OUT) ); 162 | 163 | endmodule 164 | -------------------------------------------------------------------------------- /UART/UART TX/README.md: -------------------------------------------------------------------------------- 1 | # UART TX (Transmitter) Block 2 | 3 | ## Overview 4 | The UART TX (Transmitter) block is a crucial part of our multi-clock domain system. It's responsible for transmitting data to a master device through the UART interface. Whether it's sending commands, results, or any other information, the UART TX block ensures efficient and accurate data transmission. 5 | 6 | ## Block Description 7 | The UART TX block performs the following key functions: 8 | 9 | - **Data Transmission:** It receives data to be transmitted on the `P_DATA` bus when the `DATA_VALID` signal is high. 10 | 11 | - **Configuration:** The block allows for configuration of frame parity bit generation (`PAR_EN`) and parity type (`PAR_TYP`) for data integrity. 12 | 13 | - **Status Indication:** It provides a `TX_OUT` serial data output signal to transmit data and a `BUSY` signal to indicate ongoing transmission. 14 | 15 | ## Block Interface 16 | The UART TX block has the following interface: 17 | 18 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/8614ac50-6430-41bc-9b1b-9562b4de9f8e) 19 | 20 | - **Inputs:** 21 | - `CLK`: Clock signal for sequential elements. 22 | - `RST`: Active-low asynchronous reset signal to clear registers. 23 | - `PAR_TYPE`: Configuration signal for parity type (0 for even, 1 for odd). 24 | - `PAR_EN`: Configuration signal to enable/disable the frame parity bit (0 for disable, 1 for enable). 25 | - `P_DATA`: Parallel 8-bits Data to be transmitted. 26 | - `DATA_VALID`: Signal indicating that `P_DATA` contains valid data for transmission. 27 | 28 | - **Outputs:** 29 | - `TX_OUT`: Serial data output signal for transmitting data. (high when idle) 30 | - `BUSY`: Output signal indicating ongoing transmission (high for transmission, low for idle). 31 | 32 | > For a better understanding of how the UART TX block is implemented in RTL (Register-Transfer Level) code, please refer to the [`UART_TX.v`](./UART_TX.v) file in this repository. 33 | 34 | ## Specifications 35 | To effectively use the UART TX block, consider the following specifications: 36 | 37 | - UART TX only accepts new data on the `P_DATA` bus when the `DATA_VALID` signal is high. 38 | 39 | - The block is cleared using the asynchronous active low reset signal `RST`. 40 | 41 | - The `DATA_VALID` signal remains high for only 1 clock cycle to indicate valid data. 42 | 43 | - The `BUSY` signal is high as long as the UART TX block is transmitting a frame; otherwise, it's low. 44 | 45 | - During UART TX processing, no new data is accepted on the `P_DATA` bus, even if `DATA_VALID` is high. 46 | 47 | - `TX_OUT` is high in the IDLE case when no transmission is occurring. 48 | 49 | - Configuration: 50 | - `PAR_EN` (Parity Configuration): 51 | - 0: Disables the frame parity bit. 52 | - 1: Enables the frame parity bit. 53 | - `PAR_TYP` (Parity Type Configuration): 54 | - 0: Specifies even parity. 55 | - 1: Specifies odd parity. 56 | 57 | ## Elaborated Design 58 | The UART TX block is composed of four primary blocks, each serving a unique function: 59 | 60 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/f261060e-718b-4ba0-b429-9600d08de267) 61 | 62 | ### 1. Serializer ([serializer.v](./serializer.v)) 63 | The Serializer block is responsible for converting parallel data received on the `P_DATA` bus into a serial frame for transmission. It performs the task of serializing the data efficiently. 64 | 65 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/534fdc9d-12ae-4b58-81b7-31c727dc5100) 66 | 67 | ### 2. Parity Calculator ([parity_calc.v](./parity_calc.v)) 68 | The Parity Calculator block determines the parity bit for the serial frame, ensuring data integrity during transmission. Depending on the configuration, it calculates and inserts either an even or odd parity bit into the frame. 69 | 70 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/4e539160-5e00-49f8-bb66-b420275fd3b2) 71 | 72 | ### 3. MUX (Multiplexer) ([MUX.v](./MUX.v)) 73 | The MUX block selects the appropriate bit from the serial frame for output, facilitating the serial data transmission. It plays a critical role in the serialization process. 74 | 75 |

76 | Block Interface 77 |

78 | 79 | ### 4. FSM (Finite State Machine) ([FSM.v](./FSM.v)) 80 | The FSM block controls the flow of data transmission, ensuring that data is sent in the correct order and at the right time. It orchestrates the operation of the entire UART TX block. 81 | 82 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/2fd8fb14-f818-4590-8b4d-56cfbaf6c690) 83 | 84 | 85 | ## [Testbench](./UART_TX_tb.v) 86 | 87 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/c799d6f1-91df-410e-8d11-56f71768f413) 88 | 89 | ``` 90 | # /********** Even Parity Testcases **********/ 91 | # MISMATCH: 00000000000 -> EVEN PARITY TESTCASE [PASSED] 92 | # MISMATCH: 00000000000 -> EVEN PARITY TESTCASE [PASSED] 93 | # MISMATCH: 00000000000 -> EVEN PARITY TESTCASE [PASSED] 94 | # /********** Odd Parity Testcases **********/ 95 | # MISMATCH: 00000000000 -> ODD PARITY TESTCASE [PASSED] 96 | # MISMATCH: 00000000000 -> ODD PARITY TESTCASE [PASSED] 97 | # MISMATCH: 00000000000 -> ODD PARITY TESTCASE [PASSED] 98 | # /********** NO Parity Testcases **********/ 99 | # MISMATCH: 0000000000 -> NO PARITY TESTCASE [PASSED] 100 | # MISMATCH: 0000000000 -> NO PARITY TESTCASE [PASSED] 101 | # MISMATCH: 0000000000 -> NO PARITY TESTCASE [PASSED] 102 | # /**** Passing New Data While Transmission ****/ 103 | # MISMATCH: 00000000000 -> IGNORING INPUT TESTCASE [PASSED] 104 | ``` 105 | 106 | 107 | -------------------------------------------------------------------------------- /ALU/README.md: -------------------------------------------------------------------------------- 1 | # Arithmetic Logic Unit (ALU) Block 2 | 3 | ## Overview 4 | The Arithmetic Logic Unit (ALU) is a fundamental component of our multi-clock domain system. It plays a critical role in executing various arithmetic and logic operations, enabling the processor to perform tasks such as addition, subtraction, logical AND, logical OR, and more. 5 | 6 | ## Block Description 7 | The ALU block is responsible for the following key functions: 8 | 9 | - **Arithmetic Operations:** It performs basic arithmetic operations like addition and subtraction on input data. 10 | 11 | - **Logical Operations:** It executes logical operations, including AND, OR, NAND, and NOR, to manipulate data. 12 | 13 | - **Comparison:** The ALU compares input values and generates flags to indicate conditions such as equality, less than, and greater than. 14 | 15 | - **Shift Operations** the ALU also supports shift operations. These operations allow for the movement of bits within data operands. These shift operations are valuable for tasks such as data manipulation and scaling within the processor. 16 | 17 | ## Block Interface 18 | The ALU block has the following interface: 19 | 20 |

21 | Block Interface 22 |

23 | 24 | - **Inputs:** 25 | - `A` and `B`: Input 8-bits data operands for the selected operation. 26 | - `ALU Func`: 4-bits Control signal specifying the operation to be performed. 27 | - `Enable`: Control signal enabling the ALU to function and accept the inputs. 28 | - `CLK`: Clock Signal for sequential elements. 29 | - `RST`: Active-low Asynchronous reset signal to clear the sequential elements. 30 | 31 | - **Outputs:** 32 | - `ALU OUT`: The 16-bits result of the operation. 33 | - `OUT_VALID`: Status flag to indicate that the `ALU OUT` is ready 34 | 35 | > For a better understanding of how the ALU block is implemented in RTL (Register-Transfer Level) code, please refer to the [`ALU.v`](./ALU.v) file in this repository. 36 | 37 | ## ALU Function Table 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 |
ALU_FUNOPERATIONALU_OUT
0000Arithmetic
AdditionA+B
0001SubtractionA-B
0010MultiplicationA*B
0011DivisionA/B
0100Logic
ANDA&B
0101ORA|B
0110NAND~(A&B)
0111NOR~(A|B)
1000Compare
NOP0
1001if A==B ?1 : 0
1010if A > B ?2 : 0
1011if A < B ?3 : 0
1100Shift
LSR to AA >> 1
1101LSL to AA << 1
1110LSR to BB >> 1
1111LSL to BB << 1
140 | 141 | ## Elaborated Design 142 | 143 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/d219f61f-0da8-4ba6-9685-c7f2138eacec) 144 | 145 | ## [Testbench](./ALU_tb.v) 146 | ![TB](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/63fb826a-7104-49c0-b27f-9dce27a377f7) 147 | 148 | ``` 149 | [PASSED] TESTCASE- 1: ADDITION 150 | [PASSED] TESTCASE- 2: SUBTRACTION 151 | [PASSED] TESTCASE- 3: MULTIPLICATION 152 | [PASSED] TESTCASE- 4: DIVISION 153 | [PASSED] TESTCASE- 5: LOGICAL AND 154 | [PASSED] TESTCASE- 6: LOGICAL OR 155 | [PASSED] TESTCASE- 7: LOGICAL NAND 156 | [PASSED] TESTCASE- 8: LOGICAL NOR 157 | [PASSED] TESTCASE- 9: NOP 158 | [PASSED] TESTCASE-10: EQUALITY 159 | [PASSED] TESTCASE-11: GREATER THAN 160 | [PASSED] TESTCASE-12: LESS THAN 161 | [PASSED] TESTCASE-13: A-SHIFT RIGHT 162 | [PASSED] TESTCASE-14: A-SHIFT LEFT 163 | [PASSED] TESTCASE-15: B-SHIFT RIGHT 164 | [PASSED] TESTCASE-16: B-SHIFT LEFT 165 | [PASSED] TESTCASE-17: RESET 166 | ``` 167 | -------------------------------------------------------------------------------- /BACKEND/Synthesis/check_design.rpt: -------------------------------------------------------------------------------- 1 | 2 | **************************************** 3 | check_design summary: 4 | Version: K-2015.06 5 | Date: Mon Sep 25 22:31:48 2023 6 | **************************************** 7 | 8 | Name Total 9 | -------------------------------------------------------------------------------- 10 | Inputs/Outputs 14 11 | Feedthrough (LINT-29) 1 12 | Shorted outputs (LINT-31) 9 13 | Constant outputs (LINT-52) 4 14 | 15 | Cells 25 16 | Cells do not drive (LINT-1) 15 17 | Connected to power or ground (LINT-32) 2 18 | Nets connected to multiple pins on same cell (LINT-33) 8 19 | -------------------------------------------------------------------------------- 20 | 21 | Warning: In design 'ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4', cell 'C352' does not drive any nets. (LINT-1) 22 | Warning: In design 'ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4', cell 'C353' does not drive any nets. (LINT-1) 23 | Warning: In design 'ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4', cell 'C354' does not drive any nets. (LINT-1) 24 | Warning: In design 'ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4', cell 'C355' does not drive any nets. (LINT-1) 25 | Warning: In design 'ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4', cell 'C372' does not drive any nets. (LINT-1) 26 | Warning: In design 'ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4', cell 'C374' does not drive any nets. (LINT-1) 27 | Warning: In design 'ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4', cell 'C376' does not drive any nets. (LINT-1) 28 | Warning: In design 'ClkDiv_RATIO_WIDTH6', cell 'C112' does not drive any nets. (LINT-1) 29 | Warning: In design 'ClkDiv', cell 'C126' does not drive any nets. (LINT-1) 30 | Warning: In design 'edge_bit_counter', cell 'C98' does not drive any nets. (LINT-1) 31 | Warning: In design 'edge_bit_counter', cell 'C110' does not drive any nets. (LINT-1) 32 | Warning: In design 'data_sampling', cell 'C66' does not drive any nets. (LINT-1) 33 | Warning: In design 'FIFO_RD_PTR_WIDTH4', cell 'C54' does not drive any nets. (LINT-1) 34 | Warning: In design 'FIFO_WR_PTR_WIDTH4', cell 'C54' does not drive any nets. (LINT-1) 35 | Warning: In design 'serializer', cell 'B_4' does not drive any nets. (LINT-1) 36 | Warning: In design 'GRAY_CONV_PTR_WIDTH4', input port 'bit_ptr[3]' is connected directly to output port 'gray_ptr[3]'. (LINT-29) 37 | Warning: In design 'SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4', output port 'ClkDiv_RX[5]' is connected directly to output port 'ClkDiv_RX[3]'. (LINT-31) 38 | Warning: In design 'SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4', output port 'ClkDiv_RX[5]' is connected directly to output port 'ClkDiv_RX[4]'. (LINT-31) 39 | Warning: In design 'SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4', output port 'ALU_EN' is connected directly to output port 'CLK_EN'. (LINT-31) 40 | Warning: In design 'FIFO_RD_PTR_WIDTH4', output port 'rptr[2]' is connected directly to output port 'raddr[2]'. (LINT-31) 41 | Warning: In design 'FIFO_RD_PTR_WIDTH4', output port 'rptr[1]' is connected directly to output port 'raddr[1]'. (LINT-31) 42 | Warning: In design 'FIFO_RD_PTR_WIDTH4', output port 'rptr[0]' is connected directly to output port 'raddr[0]'. (LINT-31) 43 | Warning: In design 'FIFO_WR_PTR_WIDTH4', output port 'wptr[2]' is connected directly to output port 'waddr[2]'. (LINT-31) 44 | Warning: In design 'FIFO_WR_PTR_WIDTH4', output port 'wptr[1]' is connected directly to output port 'waddr[1]'. (LINT-31) 45 | Warning: In design 'FIFO_WR_PTR_WIDTH4', output port 'wptr[0]' is connected directly to output port 'waddr[0]'. (LINT-31) 46 | Warning: In design 'UART_TX', a pin on submodule 'U0_MUX' is connected to logic 1 or logic 0. (LINT-32) 47 | Pin 'start_bit' is connected to logic 0. 48 | Warning: In design 'UART_TX', a pin on submodule 'U0_MUX' is connected to logic 1 or logic 0. (LINT-32) 49 | Pin 'stop_bit' is connected to logic 1. 50 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 51 | Net 'sync_bus[7]' is connected to pins 'i_0[7]', 'sync_bus[7]''. 52 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 53 | Net 'sync_bus[6]' is connected to pins 'i_0[6]', 'sync_bus[6]''. 54 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 55 | Net 'sync_bus[5]' is connected to pins 'i_0[5]', 'sync_bus[5]''. 56 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 57 | Net 'sync_bus[4]' is connected to pins 'i_0[4]', 'sync_bus[4]''. 58 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 59 | Net 'sync_bus[3]' is connected to pins 'i_0[3]', 'sync_bus[3]''. 60 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 61 | Net 'sync_bus[2]' is connected to pins 'i_0[2]', 'sync_bus[2]''. 62 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 63 | Net 'sync_bus[1]' is connected to pins 'i_0[1]', 'sync_bus[1]''. 64 | Warning: In design 'DATA_SYNC_BUS_WIDTH8', the same net is connected to more than one pin on submodule 'U0_sync_bus'. (LINT-33) 65 | Net 'sync_bus[0]' is connected to pins 'i_0[0]', 'sync_bus[0]''. 66 | Warning: In design 'SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4', output port 'ClkDiv_RX[5]' is connected directly to 'logic 0'. (LINT-52) 67 | Warning: In design 'SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4', output port 'ClkDiv_RX[4]' is connected directly to 'logic 0'. (LINT-52) 68 | Warning: In design 'SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4', output port 'ClkDiv_RX[3]' is connected directly to 'logic 0'. (LINT-52) 69 | Warning: In design 'SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4', output port 'clk_div_en' is connected directly to 'logic 1'. (LINT-52) 70 | 1 71 | -------------------------------------------------------------------------------- /BACKEND/Synthesis/area.rpt: -------------------------------------------------------------------------------- 1 | 2 | **************************************** 3 | Report : area 4 | Design : SYS_TOP 5 | Version: K-2015.06 6 | Date : Mon Sep 25 22:32:07 2023 7 | **************************************** 8 | 9 | Library(s) Used: 10 | 11 | scmetro_tsmc_cl013g_rvt_ss_1p08v_125c (File: /home/IC/tsmc_fb_cl013g_sc/aci/sc-m/synopsys/scmetro_tsmc_cl013g_rvt_ss_1p08v_125c.db) 12 | 13 | Number of ports: 777 14 | Number of nets: 2599 15 | Number of cells: 1797 16 | Number of combinational cells: 1449 17 | Number of sequential cells: 306 18 | Number of macros/black boxes: 0 19 | Number of buf/inv: 325 20 | Number of references: 16 21 | 22 | Combinational area: 13563.821097 23 | Buf/Inv area: 1342.614725 24 | Noncombinational area: 7436.743919 25 | Macro/Black Box area: 0.000000 26 | Net Interconnect area: undefined (No wire load specified) 27 | 28 | Total cell area: 21000.565016 29 | Total area: undefined 30 | 31 | Hierarchical area distribution 32 | ------------------------------ 33 | 34 | Global cell area Local cell area 35 | ------------------- ----------------------------- 36 | Hierarchical cell Absolute Percent Combi- Noncombi- Black- 37 | Total Total national national boxes Design 38 | -------------------------------- ---------- ------- ---------- --------- ------ ------------------------------------------------------------------------------ 39 | SYS_TOP 21000.5650 100.0 24.7107 0.0000 0.0000 SYS_TOP 40 | U0_ALU 7034.3127 33.5 1361.4419 441.2625 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4 41 | U0_ALU/add_21 244.7536 1.2 244.7536 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_add_0 42 | U0_ALU/div_24 2558.1458 12.2 2558.1458 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW_div_uns_1 43 | U0_ALU/mult_23 2159.2445 10.3 1918.0210 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW02_mult_0 44 | U0_ALU/mult_23/FS_1 241.2235 1.1 241.2235 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_add_1 45 | U0_ALU/sub_22 269.4643 1.3 269.4643 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_sub_0 46 | U0_ASYNC_FIFO 3919.5877 18.7 12.9437 0.0000 0.0000 ASYNC_FIFO_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4 47 | U0_ASYNC_FIFO/U0_DF_SYNC 207.0992 1.0 0.0000 207.0992 0.0000 DF_SYNC_BUS_WIDTH4_0 48 | U0_ASYNC_FIFO/U0_FIFO_MEM_CNTRL 2885.2684 13.7 1228.4748 1656.7936 0.0000 FIFO_MEM_CNTRL_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4 49 | U0_ASYNC_FIFO/U0_FIFO_RD 267.1109 1.3 137.6739 129.4370 0.0000 FIFO_RD_PTR_WIDTH4 50 | U0_ASYNC_FIFO/U0_FIFO_WR 260.0507 1.2 130.6137 129.4370 0.0000 FIFO_WR_PTR_WIDTH4 51 | U0_ASYNC_FIFO/U0_GRAY_CONV 40.0078 0.2 40.0078 0.0000 0.0000 GRAY_CONV_PTR_WIDTH4_0 52 | U0_ASYNC_FIFO/U1_DF_SYNC 207.0992 1.0 0.0000 207.0992 0.0000 DF_SYNC_BUS_WIDTH4_1 53 | U0_ASYNC_FIFO/U1_GRAY_CONV 40.0078 0.2 40.0078 0.0000 0.0000 GRAY_CONV_PTR_WIDTH4_1 54 | U0_ClkDiv 747.2045 3.6 540.1053 207.0992 0.0000 ClkDiv_RATIO_WIDTH6 55 | U0_ClkGate 24.7107 0.1 0.0000 24.7107 0.0000 ClkGate 56 | U0_DATA_SYNC 395.3712 1.9 0.0000 0.0000 0.0000 DATA_SYNC_BUS_WIDTH8 57 | U0_DATA_SYNC/U0_DS_pulse 57.6583 0.3 0.0000 25.8874 0.0000 DS_pulse 58 | U0_DATA_SYNC/U0_DS_pulse/inst_PULSE_GEN 59 | 31.7709 0.2 5.8835 25.8874 0.0000 PULSE_GEN_1 60 | U0_DATA_SYNC/U0_multi_ff 51.7748 0.2 0.0000 51.7748 0.0000 multi_ff 61 | U0_DATA_SYNC/U0_sync_bus 285.9381 1.4 78.8389 207.0992 0.0000 sync_bus 62 | U0_PULSE_GEN 31.7709 0.2 5.8835 25.8874 0.0000 PULSE_GEN_0 63 | U0_RST_SYNC 51.7748 0.2 0.0000 51.7748 0.0000 RST_SYNC_0 64 | U0_RegFile 3344.1814 15.9 1400.2730 1943.9084 0.0000 RegFile_BUS_WIDTH8_DEPTH8_ADDR_WIDTH4_PAR_EN1_PAR_TYPE0_PRESCALE32_DIV_RATIO32 65 | U0_SYS_CTRL 1061.3834 5.1 746.0278 315.3556 0.0000 SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4 66 | U0_UART_RX 2179.2484 10.4 7.0602 0.0000 0.0000 UART_RX_WIDTH8 67 | U0_UART_RX/U0_FSM 327.1226 1.6 223.5730 103.5496 0.0000 UART_RX_FSM 68 | U0_UART_RX/U0_data_sampling 511.8645 2.4 434.2023 77.6622 0.0000 data_sampling 69 | U0_UART_RX/U0_deserializer 603.6471 2.9 163.5613 440.0858 0.0000 deserializer 70 | U0_UART_RX/U0_edge_bit_counter 594.2335 2.8 361.2469 232.9866 0.0000 edge_bit_counter 71 | U0_UART_RX/U0_parity_check 114.1399 0.5 114.1399 0.0000 0.0000 parity_check 72 | U0_UART_RX/U0_start_check 5.8835 0.0 5.8835 0.0000 0.0000 start_check 73 | U0_UART_RX/U0_stop_check 15.2971 0.1 15.2971 0.0000 0.0000 stop_check 74 | U0_UART_TX 1163.7563 5.5 10.5903 0.0000 0.0000 UART_TX 75 | U0_UART_TX/U0_FSM 180.0351 0.9 102.3729 77.6622 0.0000 FSM 76 | U0_UART_TX/U0_MUX 36.4777 0.2 36.4777 0.0000 0.0000 MUX 77 | U0_UART_TX/U0_parity_calc 394.1945 1.9 187.0953 207.0992 0.0000 parity_calc 78 | U0_UART_TX/U0_serializer 542.4587 2.6 205.9225 336.5362 0.0000 serializer 79 | U1_ClkDiv 970.7775 4.6 494.2140 258.8740 0.0000 ClkDiv 80 | U1_ClkDiv/add_50 107.0797 0.5 107.0797 0.0000 0.0000 ClkDiv_DW01_inc_0 81 | U1_ClkDiv/add_74 110.6098 0.5 110.6098 0.0000 0.0000 ClkDiv_DW01_inc_1 82 | U1_RST_SYNC 51.7748 0.2 0.0000 51.7748 0.0000 RST_SYNC_1 83 | -------------------------------- ---------- ------- ---------- --------- ------ ------------------------------------------------------------------------------ 84 | Total 13563.8211 7436.7439 0.0000 85 | 86 | 1 87 | -------------------------------------------------------------------------------- /BACKEND/DFT/power.rpt: -------------------------------------------------------------------------------- 1 | Information: Propagating switching activity (low effort zero delay simulation). (PWR-6) 2 | Warning: Design has unannotated primary inputs. (PWR-414) 3 | Warning: Design has unannotated sequential cell outputs. (PWR-415) 4 | 5 | **************************************** 6 | Report : power 7 | -hier 8 | -analysis_effort low 9 | Design : SYS_TOP 10 | Version: K-2015.06 11 | Date : Mon Sep 25 23:00:26 2023 12 | **************************************** 13 | 14 | 15 | Library(s) Used: 16 | 17 | scmetro_tsmc_cl013g_rvt_ss_1p08v_125c (File: /home/IC/tsmc_fb_cl013g_sc/aci/sc-m/synopsys/scmetro_tsmc_cl013g_rvt_ss_1p08v_125c.db) 18 | 19 | 20 | Operating Conditions: scmetro_tsmc_cl013g_rvt_ss_1p08v_125c Library: scmetro_tsmc_cl013g_rvt_ss_1p08v_125c 21 | Wire Load Model Mode: top 22 | 23 | 24 | Global Operating Voltage = 1.08 25 | Power-specific unit information : 26 | Voltage Units = 1V 27 | Capacitance Units = 1.000000pf 28 | Time Units = 1ns 29 | Dynamic Power Units = 1mW (derived from V,C,T units) 30 | Leakage Power Units = 1pW 31 | 32 | 33 | -------------------------------------------------------------------------------- 34 | Switch Int Leak Total 35 | Hierarchy Power Power Power Power % 36 | -------------------------------------------------------------------------------- 37 | SYS_TOP 2.51e-02 0.112 1.32e+07 0.150 100.0 38 | U0_ClkGate (ClkGate) 3.79e-05 4.61e-04 2.09e+04 5.20e-04 0.3 39 | U0_UART_TX (UART_TX_test_1) 2.11e-04 3.00e-03 7.08e+05 3.92e-03 2.6 40 | U0_MUX (MUX) 1.26e-07 4.22e-07 2.28e+04 2.33e-05 0.0 41 | U0_parity_calc (parity_calc_test_1) 42 | 6.83e-06 1.00e-03 2.56e+05 1.27e-03 0.8 43 | U0_FSM (FSM_test_1) 1.79e-06 3.77e-04 1.16e+05 4.96e-04 0.3 44 | U0_serializer (serializer_test_1) 2.02e-04 1.62e-03 3.10e+05 2.13e-03 1.4 45 | U0_PULSE_GEN (PULSE_GEN_test_1) 2.29e-08 1.20e-04 1.80e+04 1.38e-04 0.1 46 | U1_ClkDiv (ClkDiv_test_1) 5.25e-04 4.15e-03 6.83e+05 5.35e-03 3.6 47 | add_74 (ClkDiv_DW01_inc_1) 3.12e-05 4.66e-05 8.90e+04 1.67e-04 0.1 48 | add_50 (ClkDiv_DW01_inc_0) 2.97e-05 4.32e-05 9.67e+04 1.70e-04 0.1 49 | U0_ClkDiv (ClkDiv_RATIO_WIDTH6_test_1) 50 | 2.95e-04 3.64e-03 5.37e+05 4.47e-03 3.0 51 | U1_RST_SYNC (RST_SYNC_test_1) 1.10e-05 7.77e-04 2.88e+04 8.17e-04 0.5 52 | U0_RST_SYNC (RST_SYNC_test_0) 8.60e-06 7.06e-04 2.86e+04 7.43e-04 0.5 53 | U0_ASYNC_FIFO (ASYNC_FIFO_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4_test_1) 54 | 9.71e-04 2.31e-02 2.39e+06 2.65e-02 17.6 55 | U1_GRAY_CONV (GRAY_CONV_PTR_WIDTH4_1) 56 | 0.000 0.000 3.94e+04 3.94e-05 0.0 57 | U0_GRAY_CONV (GRAY_CONV_PTR_WIDTH4_0) 58 | 5.11e-06 1.05e-05 3.96e+04 5.52e-05 0.0 59 | U1_DF_SYNC (DF_SYNC_BUS_WIDTH4_test_1) 60 | 3.29e-06 2.23e-03 1.05e+05 2.34e-03 1.6 61 | U0_DF_SYNC (DF_SYNC_BUS_WIDTH4_test_0) 62 | 3.00e-07 1.04e-03 1.08e+05 1.15e-03 0.8 63 | U0_FIFO_WR (FIFO_WR_PTR_WIDTH4_test_1) 64 | 1.23e-04 1.83e-03 1.88e+05 2.14e-03 1.4 65 | U0_FIFO_RD (FIFO_RD_PTR_WIDTH4_test_1) 66 | 5.54e-07 6.36e-04 2.05e+05 8.41e-04 0.6 67 | U0_FIFO_MEM_CNTRL (FIFO_MEM_CNTRL_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4_test_1) 68 | 8.40e-04 1.74e-02 1.69e+06 1.99e-02 13.2 69 | U0_RegFile (RegFile_BUS_WIDTH8_DEPTH8_ADDR_WIDTH4_PAR_EN1_PAR_TYPE0_PRESCALE32_DIV_RATIO32_test_1) 70 | 1.83e-03 2.21e-02 1.92e+06 2.59e-02 17.2 71 | U0_ALU (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_test_1) 72 | 4.64e-04 3.27e-02 4.35e+06 3.75e-02 24.9 73 | mult_23 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW02_mult_0) 74 | 4.11e-05 2.36e-05 1.66e+06 1.72e-03 1.1 75 | add_21 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_add_0) 76 | 6.28e-06 5.78e-05 2.10e+05 2.74e-04 0.2 77 | sub_22 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_sub_0) 78 | 7.50e-06 5.80e-05 2.48e+05 3.13e-04 0.2 79 | div_24 (ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW_div_uns_0) 80 | 5.08e-05 2.38e-04 1.24e+06 1.53e-03 1.0 81 | U0_SYS_CTRL (SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4_test_1) 82 | 1.05e-03 4.80e-03 6.67e+05 6.51e-03 4.3 83 | U0_DATA_SYNC (DATA_SYNC_BUS_WIDTH8_test_1) 84 | 2.21e-05 3.29e-03 2.07e+05 3.52e-03 2.3 85 | U0_sync_bus (sync_bus_test_1) 1.23e-05 2.17e-03 1.49e+05 2.33e-03 1.5 86 | U0_DS_pulse (DS_pulse_test_1) 8.21e-06 5.58e-04 3.13e+04 5.97e-04 0.4 87 | inst_PULSE_GEN (PULSE_GEN_test_0) 88 | 3.94e-06 2.77e-04 1.77e+04 2.99e-04 0.2 89 | U0_multi_ff (multi_ff_test_1) 1.62e-06 5.68e-04 2.64e+04 5.96e-04 0.4 90 | U0_UART_RX (UART_RX_WIDTH8_test_1) 1.18e-03 9.97e-03 1.46e+06 1.26e-02 8.4 91 | U0_parity_check (parity_check) 2.31e-05 8.48e-05 1.14e+05 2.22e-04 0.1 92 | U0_stop_check (stop_check) 0.000 0.000 1.31e+04 1.31e-05 0.0 93 | U0_start_check (start_check) 0.000 0.000 2.93e+03 2.93e-06 0.0 94 | U0_deserializer (deserializer_test_1) 95 | 7.00e-05 4.24e-03 3.49e+05 4.65e-03 3.1 96 | U0_data_sampling (data_sampling_test_1) 97 | 2.15e-04 1.23e-03 3.82e+05 1.83e-03 1.2 98 | U0_edge_bit_counter (edge_bit_counter_test_1) 99 | 5.20e-04 3.01e-03 4.05e+05 3.93e-03 2.6 100 | U0_FSM (UART_RX_FSM_test_1) 3.56e-04 1.41e-03 1.89e+05 1.96e-03 1.3 101 | U7_mux2X1 (mux2X1_7) 2.45e-03 2.02e-04 2.35e+04 2.67e-03 1.8 102 | U6_mux2X1 (mux2X1_0) 5.18e-03 2.59e-04 2.35e+04 5.46e-03 3.6 103 | U5_mux2X1 (mux2X1_2) 1.11e-04 8.75e-05 1.15e+04 2.10e-04 0.1 104 | U4_mux2X1 (mux2X1_3) 3.66e-03 1.84e-03 1.15e+04 5.52e-03 3.7 105 | U3_mux2X1 (mux2X1_4) 2.67e-04 7.03e-05 1.14e+04 3.49e-04 0.2 106 | U2_mux2X1 (mux2X1_5) 9.64e-06 2.21e-06 1.29e+04 2.47e-05 0.0 107 | U1_mux2X1 (mux2X1_6) 5.21e-04 1.93e-04 1.15e+04 7.26e-04 0.5 108 | U0_mux2X1 (mux2X1_1) 4.01e-03 2.66e-04 1.14e+04 4.29e-03 2.8 109 | 1 110 | -------------------------------------------------------------------------------- /Register File/RegFile_tb.v: -------------------------------------------------------------------------------- 1 | module RegFile_tb (); 2 | 3 | /*******************************************************************/ 4 | ///////////////////// TB Signals Declaration //////////////////////// 5 | /*******************************************************************/ 6 | parameter BUS_WIDTH = 16 , DEPTH = 8, ADDR_WIDTH = ($clog2(DEPTH)+1); 7 | parameter CLK_PERIOD = 10 , HALF_PERIOD = (CLK_PERIOD/2); 8 | parameter HIGH = 1 , LOW = 0; 9 | 10 | defparam DUT.BUS_WIDTH = BUS_WIDTH; 11 | defparam DUT.ADDR_WIDTH = ADDR_WIDTH; 12 | defparam DUT.DEPTH = DEPTH; 13 | 14 | // interface ports 15 | reg CLK ; // Clock Signal 16 | reg RST ; // Active Low Reset 17 | reg WrEn ; // Write Enable 18 | reg RdEn ; // Read Enable 19 | reg [ADDR_WIDTH-1:0] Address ; // Address bus 20 | reg [BUS_WIDTH-1 :0] WrData ; // Write Data Bus 21 | wire [BUS_WIDTH-1 :0] REG0 ; // Register at Address 0x0 22 | wire [BUS_WIDTH-1 :0] REG1 ; // Register at Address 0x1 23 | wire [BUS_WIDTH-1 :0] REG2 ; // Register at Address 0x2 24 | wire [BUS_WIDTH-1 :0] REG3 ; // Register at Address 0x3 25 | wire [BUS_WIDTH-1 :0] RdData ; // Read Data Bus 26 | wire RdData_Valid ; // Read Data Valid 27 | 28 | // test memory declaration 29 | reg [BUS_WIDTH-1:0] TEST_MEM [DEPTH-1:0]; 30 | 31 | /*******************************************************************/ 32 | ////////////////////////// Initial Block //////////////////////////// 33 | /*******************************************************************/ 34 | initial 35 | begin 36 | $dumpfile("RegFile.vcd"); 37 | $dumpvars; 38 | initialize(); 39 | init_mem(); 40 | reset(); 41 | 42 | $display("/******************** Writing Testcases **************************/"); 43 | write_data(); 44 | 45 | $display("/******************** Reading Testcases **************************/"); 46 | read_data(); 47 | 48 | $display("/******************** Enables Testcases **************************/"); 49 | no_write_no_read(); 50 | #(3*CLK_PERIOD) $stop; 51 | end 52 | 53 | /*******************************************************************/ 54 | ////////////////////////////// TASKS //////////////////////////////// 55 | /*******************************************************************/ 56 | task reset; 57 | begin 58 | RST = LOW; 59 | #HALF_PERIOD 60 | RST = HIGH; 61 | #HALF_PERIOD; 62 | end 63 | endtask 64 | /********************************/ 65 | task initialize; 66 | begin 67 | CLK = LOW; 68 | RST = LOW; 69 | WrEn = LOW; 70 | RdEn = LOW; 71 | Address = LOW; 72 | WrData = LOW; 73 | end 74 | endtask 75 | /********************************/ 76 | task init_mem; 77 | integer i; 78 | begin 79 | for(i = 0; i < DEPTH; i = i + 1) 80 | begin 81 | TEST_MEM[i] = ($random %(2**BUS_WIDTH-1)); 82 | end 83 | end 84 | endtask 85 | /********************************/ 86 | task write_data; 87 | integer i; 88 | begin 89 | @(negedge CLK) 90 | WrEn = HIGH; 91 | RdEn = LOW; 92 | 93 | // writing in a memory for loop 94 | for(i = 0; i < DEPTH; i = i + 1) 95 | begin 96 | Address = i; 97 | WrData = TEST_MEM[i]; 98 | #CLK_PERIOD; 99 | end 100 | 101 | #CLK_PERIOD 102 | 103 | // checking the memory contents for loop 104 | for(i = 0; i < DEPTH; i = i + 1) 105 | begin 106 | if(DUT.MEM[i] == TEST_MEM[i]) 107 | $display("[PASSED]: Write in Address %3b",i); 108 | else 109 | $display("[FAILED]: Write in Address %3b",i); 110 | end 111 | 112 | end 113 | endtask 114 | /********************************/ 115 | task read_data; 116 | integer i; 117 | begin 118 | @(negedge CLK) 119 | WrEn = LOW; 120 | RdEn = HIGH; 121 | 122 | // checking the memory contents for loop 123 | for(i = 0; i < DEPTH; i = i + 1) 124 | begin 125 | Address = i; 126 | #CLK_PERIOD 127 | if((RdData == TEST_MEM[i]) && RdData_Valid) 128 | $display("[PASSED]: Read from Address %3b",i); 129 | else 130 | $display("[FAILED]: Read from Address %3b",i); 131 | #CLK_PERIOD; 132 | end 133 | end 134 | endtask 135 | /********************************/ 136 | task no_write_no_read; 137 | begin 138 | WrEn = LOW; 139 | RdEn = LOW; 140 | reset(); 141 | #(2*CLK_PERIOD) 142 | 143 | WrEn = HIGH; 144 | RdEn = HIGH; 145 | Address = 'h0; 146 | WrData = 'ha1b2; 147 | #CLK_PERIOD 148 | if(DUT.MEM[Address] == 'ha1b2) 149 | $display("[FAILED]: Writing accepted when WrEn = %0b RdEn = %0b",WrEn,RdEn); 150 | else 151 | $display("[PASSED]: Writing rejected when WrEn = %0b RdEn = %0b",WrEn,RdEn); 152 | 153 | #CLK_PERIOD 154 | if(RdData_Valid) 155 | $display("[FAILED]: Reading accepted when WrEn = %0b RdEn = %0b",WrEn,RdEn); 156 | else 157 | $display("[PASSED]: Reading rejected when WrEn = %0b RdEn = %0b",WrEn,RdEn); 158 | 159 | #CLK_PERIOD 160 | WrEn = LOW; 161 | RdEn = LOW; 162 | Address = 'h1; 163 | WrData = 'hb1a2; 164 | #CLK_PERIOD 165 | if(DUT.MEM[Address] == 'hb1a2) 166 | $display("[FAILED]: Writing accepted when WrEn = %0b RdEn = %0b",WrEn,RdEn); 167 | else 168 | $display("[PASSED]: Writing rejected when WrEn = %0b RdEn = %0b",WrEn,RdEn); 169 | 170 | #CLK_PERIOD 171 | if(RdData_Valid) 172 | $display("[FAILED]: Reading accepted when WrEn = %0b RdEn = %0b",WrEn,RdEn); 173 | else 174 | $display("[PASSED]: Reading rejected when WrEn = %0b RdEn = %0b",WrEn,RdEn); 175 | 176 | end 177 | endtask 178 | 179 | /*******************************************************************/ 180 | ///////////////////////// Clock Generator /////////////////////////// 181 | /*******************************************************************/ 182 | always #HALF_PERIOD CLK = ~CLK; 183 | 184 | /*******************************************************************/ 185 | //////////////////////// DUT Instantiation ////////////////////////// 186 | /*******************************************************************/ 187 | RegFile DUT ( 188 | .CLK (CLK) , 189 | .RST (RST) , 190 | .WrEn (WrEn) , 191 | .RdEn (RdEn) , 192 | .Address (Address) , 193 | .WrData (WrData) , 194 | .REG0 (REG0) , 195 | .REG1 (REG1) , 196 | .REG2 (REG2) , 197 | .REG3 (REG3) , 198 | .RdData (RdData) , 199 | .RdData_Valid (RdData_Valid) ); 200 | 201 | endmodule -------------------------------------------------------------------------------- /BACKEND/DFT/area.rpt: -------------------------------------------------------------------------------- 1 | 2 | **************************************** 3 | Report : area 4 | Design : SYS_TOP 5 | Version: K-2015.06 6 | Date : Mon Sep 25 23:00:26 2023 7 | **************************************** 8 | 9 | Library(s) Used: 10 | 11 | scmetro_tsmc_cl013g_rvt_ss_1p08v_125c (File: /home/IC/tsmc_fb_cl013g_sc/aci/sc-m/synopsys/scmetro_tsmc_cl013g_rvt_ss_1p08v_125c.db) 12 | 13 | Number of ports: 894 14 | Number of nets: 2652 15 | Number of cells: 1705 16 | Number of combinational cells: 1351 17 | Number of sequential cells: 304 18 | Number of macros/black boxes: 0 19 | Number of buf/inv: 275 20 | Number of references: 27 21 | 22 | Combinational area: 12354.173486 23 | Buf/Inv area: 1119.041721 24 | Noncombinational area: 9419.483751 25 | Macro/Black Box area: 0.000000 26 | Net Interconnect area: undefined (No wire load specified) 27 | 28 | Total cell area: 21773.657238 29 | Total area: undefined 30 | 31 | Hierarchical area distribution 32 | ------------------------------ 33 | 34 | Global cell area Local cell area 35 | ------------------- ----------------------------- 36 | Hierarchical cell Absolute Percent Combi- Noncombi- Black- 37 | Total Total national national boxes Design 38 | -------------------------------- ---------- ------- ---------- --------- ------ ------------------------------------------------------------------------------------- 39 | SYS_TOP 21773.6572 100.0 131.7904 0.0000 0.0000 SYS_TOP 40 | U0_ALU 5832.9020 26.8 1177.8767 560.1092 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_test_1 41 | U0_ALU/add_21 235.3400 1.1 235.3400 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_add_0 42 | U0_ALU/div_24 1434.3973 6.6 1434.3973 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW_div_uns_0 43 | U0_ALU/mult_23 2159.2445 9.9 1918.0210 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW02_mult_0 44 | U0_ALU/mult_23/FS_1 241.2235 1.1 241.2235 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_add_1 45 | U0_ALU/sub_22 265.9342 1.2 265.9342 0.0000 0.0000 ALU_OPRND_WIDTH8_OUT_WIDTH16_CTRL_WIDTH4_DW01_sub_0 46 | U0_ASYNC_FIFO 4544.4156 20.9 27.0641 0.0000 0.0000 ASYNC_FIFO_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4_test_1 47 | U0_ASYNC_FIFO/U0_DF_SYNC 263.5808 1.2 0.0000 263.5808 0.0000 DF_SYNC_BUS_WIDTH4_test_0 48 | U0_ASYNC_FIFO/U0_FIFO_MEM_CNTRL 3313.5873 15.2 1204.9408 2108.6465 0.0000 FIFO_MEM_CNTRL_DATA_WIDTH8_MEM_DEPTH8_PTR_WIDTH4_test_1 49 | U0_ASYNC_FIFO/U0_FIFO_RD 301.2352 1.4 137.6739 163.5613 0.0000 FIFO_RD_PTR_WIDTH4_test_1 50 | U0_ASYNC_FIFO/U0_FIFO_WR 295.3517 1.4 130.6137 164.7380 0.0000 FIFO_WR_PTR_WIDTH4_test_1 51 | U0_ASYNC_FIFO/U0_GRAY_CONV 40.0078 0.2 40.0078 0.0000 0.0000 GRAY_CONV_PTR_WIDTH4_0 52 | U0_ASYNC_FIFO/U1_DF_SYNC 263.5808 1.2 0.0000 263.5808 0.0000 DF_SYNC_BUS_WIDTH4_test_1 53 | U0_ASYNC_FIFO/U1_GRAY_CONV 40.0078 0.2 40.0078 0.0000 0.0000 GRAY_CONV_PTR_WIDTH4_1 54 | U0_ClkDiv 803.6861 3.7 540.1053 263.5808 0.0000 ClkDiv_RATIO_WIDTH6_test_1 55 | U0_ClkGate 24.7107 0.1 0.0000 24.7107 0.0000 ClkGate 56 | U0_DATA_SYNC 480.0936 2.2 0.0000 0.0000 0.0000 DATA_SYNC_BUS_WIDTH8_test_1 57 | U0_DATA_SYNC/U0_DS_pulse 71.7787 0.3 0.0000 32.9476 0.0000 DS_pulse_test_1 58 | U0_DATA_SYNC/U0_DS_pulse/inst_PULSE_GEN 59 | 38.8311 0.2 5.8835 32.9476 0.0000 PULSE_GEN_test_0 60 | U0_DATA_SYNC/U0_multi_ff 65.8952 0.3 0.0000 65.8952 0.0000 multi_ff_test_1 61 | U0_DATA_SYNC/U0_sync_bus 342.4197 1.6 78.8389 263.5808 0.0000 sync_bus_test_1 62 | U0_PULSE_GEN 38.8311 0.2 5.8835 32.9476 0.0000 PULSE_GEN_test_1 63 | U0_RST_SYNC 65.8952 0.3 0.0000 65.8952 0.0000 RST_SYNC_test_0 64 | U0_RegFile 3757.2032 17.3 1352.0283 2405.1749 0.0000 RegFile_BUS_WIDTH8_DEPTH8_ADDR_WIDTH4_PAR_EN1_PAR_TYPE0_PRESCALE32_DIV_RATIO32_test_1 65 | U0_SYS_CTRL 1159.0495 5.3 760.1482 398.9013 0.0000 SYS_CTRL_ALU_WIDTH16_ADDR_WIDTH4_DATA_BUS_WIDTH8_ALUFN_WIDTH4_test_1 66 | U0_UART_RX 2386.3476 11.0 0.0000 0.0000 0.0000 UART_RX_WIDTH8_test_1 67 | U0_UART_RX/U0_FSM 345.9498 1.6 209.4526 136.4972 0.0000 UART_RX_FSM_test_1 68 | U0_UART_RX/U0_data_sampling 529.5150 2.4 427.1421 102.3729 0.0000 data_sampling_test_1 69 | U0_UART_RX/U0_deserializer 714.2569 3.3 135.3205 578.9364 0.0000 deserializer_test_1 70 | U0_UART_RX/U0_edge_bit_counter 661.3054 3.0 354.1867 307.1187 0.0000 edge_bit_counter_test_1 71 | U0_UART_RX/U0_parity_check 114.1399 0.5 114.1399 0.0000 0.0000 parity_check 72 | U0_UART_RX/U0_start_check 5.8835 0.0 5.8835 0.0000 0.0000 start_check 73 | U0_UART_RX/U0_stop_check 15.2971 0.1 15.2971 0.0000 0.0000 stop_check 74 | U0_UART_TX 1330.8477 6.1 3.5301 0.0000 0.0000 UART_TX_test_1 75 | U0_UART_TX/U0_FSM 201.2157 0.9 102.3729 98.8428 0.0000 FSM_test_1 76 | U0_UART_TX/U0_MUX 36.4777 0.2 36.4777 0.0000 0.0000 MUX 77 | U0_UART_TX/U0_parity_calc 450.6761 2.1 187.0953 263.5808 0.0000 parity_calc_test_1 78 | U0_UART_TX/U0_serializer 638.9481 2.9 212.9827 425.9654 0.0000 serializer_test_1 79 | U0_mux2X1 12.9437 0.1 12.9437 0.0000 0.0000 mux2X1_1 80 | U1_ClkDiv 1041.3795 4.8 494.2140 329.4760 0.0000 ClkDiv_test_1 81 | U1_ClkDiv/add_50 107.0797 0.5 107.0797 0.0000 0.0000 ClkDiv_DW01_inc_0 82 | U1_ClkDiv/add_74 110.6098 0.5 110.6098 0.0000 0.0000 ClkDiv_DW01_inc_1 83 | U1_RST_SYNC 65.8952 0.3 0.0000 65.8952 0.0000 RST_SYNC_test_1 84 | U1_mux2X1 11.7670 0.1 11.7670 0.0000 0.0000 mux2X1_6 85 | U2_mux2X1 11.7670 0.1 11.7670 0.0000 0.0000 mux2X1_5 86 | U3_mux2X1 11.7670 0.1 11.7670 0.0000 0.0000 mux2X1_4 87 | U4_mux2X1 11.7670 0.1 11.7670 0.0000 0.0000 mux2X1_3 88 | U5_mux2X1 11.7670 0.1 11.7670 0.0000 0.0000 mux2X1_2 89 | U6_mux2X1 16.4738 0.1 16.4738 0.0000 0.0000 mux2X1_0 90 | U7_mux2X1 22.3573 0.1 22.3573 0.0000 0.0000 mux2X1_7 91 | -------------------------------- ---------- ------- ---------- --------- ------ ------------------------------------------------------------------------------------- 92 | Total 12354.1735 9419.4838 0.0000 93 | 94 | 1 95 | -------------------------------------------------------------------------------- /Asynchronous FIFO/README.md: -------------------------------------------------------------------------------- 1 | # Asynchronous FIFO Block 2 | 3 | ## Overview 4 | The Asynchronous FIFO (First-In, First-Out) block is a crucial component in our system, designed to efficiently manage data storage and retrieval between two asynchronous clock domains. It serves as a 2-port memory with a specified depth, allowing for asynchronous write and read operations. 5 | 6 | ## Block Description 7 | The Asynchronous FIFO block is characterized by the following key features: 8 | 9 | - **Dual Clocks:** It operates with two clocks: 10 | - `W_CLK` (Write Clock): Used for write operations. 11 | - `R_CLK` (Read Clock): Used for read operations. 12 | 13 | - **Dual Addresses:** The FIFO has two address ports: 14 | - Write Address: Determines the location for write operations. 15 | - Read Address: Determines the location for read operations. 16 | 17 | - **Write Operation:** Data is written into the FIFO at the location specified by the write address (`W_INC` and `WR_DATA` inputs). 18 | 19 | - **Read Operation:** Data is read from the FIFO at the location specified by the read address (`R_INC` output and `RD_DATA` output). 20 | 21 | ## Block Interface 22 | The Asynchronous FIFO block has the following interface: 23 | 24 |

25 | Your Image Description 26 |

27 | 28 | - **Inputs:** 29 | - `W_CLK`: Write clock signal. 30 | - `W_RST`: Asynchronous active-low write reset signal. 31 | - `W_INC`: Write address increment signal. 32 | - `R_CLK`: Read clock signal. 33 | - `R_RST`: Asynchronous active-low read reset signal. 34 | - `R_INC`: Read address increment signal. 35 | - `WR_DATA`: Data input for write operations. 36 | 37 | - **Outputs:** 38 | - `FULL`: Signal indicating that the FIFO is full. 39 | - `RD_DATA`: Data output for read operations. 40 | - `EMPTY`: Signal indicating that the FIFO is empty. 41 | 42 | ## Specifications 43 | The Asynchronous FIFO block operates according to the following specifications: 44 | 45 | - Data can be written into the FIFO using the `W_CLK`, `W_RST`, `W_INC`, and `WR_DATA` inputs. 46 | 47 | - Data can be read from the FIFO using the `R_CLK`, `R_RST`, `R_INC`, and `RD_DATA` outputs. 48 | 49 | - The `FULL` signal indicates that the FIFO is full and cannot accept further write operations. 50 | 51 | - The `EMPTY` signal indicates that the FIFO is empty, and no data can be read from it. 52 | 53 | - Asynchronous reset signals `W_RST` and `R_RST` are used to clear the FIFO's state. 54 | 55 | ## Additional Information 56 | The design of this Asynchronous FIFO block is based on the principles outlined in Clifford E. Cummings' paper: "Simulation and Synthesis Techniques for Asynchronous FIFO Design."[^1] 57 | 58 | ## The Block Diagram for FIFO 59 | 60 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/42ca8d2a-883f-4acc-bbaf-e7713042b7f1) 61 | 62 | To facilitate static timing analysis of the style #1 FIFO design, the design has been partitioned into the following six 63 | Verilog modules with the following functionality and clock domains: 64 | 65 | ### 1. Wrapper Module ([ASYNC_FIFO.v](./ASYNC_FIFO.v)) 66 | - This top-level wrapper module includes all clock domains and serves as a wrapper to instantiate other FIFO modules. 67 | - In a larger ASIC or FPGA design, this top-level wrapper may be discarded to group FIFO modules into their respective clock domains for improved synthesis and static timing analysis. 68 | 69 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/e4eb84e4-5819-4d2b-b293-8be99cabbe56) 70 | 71 | ### 2. FIFO Memory Buffer ([FIFO_MEM_CNTRL.v](./FIFO_MEM_CNTRL.v)) 72 | - The FIFO memory buffer is accessed by both the write and read clock domains. 73 | - Typically, this buffer is implemented as a synchronous dual-port RAM, although other memory styles can be adapted for use as the FIFO buffer. 74 | 75 |

76 | Block Interface 77 |

78 | 79 | ### 3. Read-to-Write Synchronizer ([DF_SYNC.v](./DF_SYNC.v)) 80 | - This module synchronizes the read pointer into the write-clock domain. 81 | - The synchronized read pointer is used by the `FIFO_WR` module to generate the FIFO full condition. 82 | - This module contains flip-flops synchronized to the write clock, without additional logic. 83 | 84 |

85 | Block Interface 86 |

87 | 88 | ### 4. Write-to-Read Synchronizer ([DF_SYNC.v](./DF_SYNC.v)) 89 | - This module synchronizes the write pointer into the read-clock domain. 90 | - The synchronized write pointer is used by the `FIFO_RD` module to generate the FIFO empty condition. 91 | - Similar to `sync_r2w.v`, this module contains flip-flops synchronized to the read clock, without additional logic. 92 | 93 |

94 | Block Interface 95 |

96 | 97 | ### 5. Read Pointer and Empty-Flag Logic ([FIFO_RD.v](./FIFO_RD.v)) 98 | - This module operates entirely within the read-clock domain. 99 | - It contains the FIFO read pointer and logic for generating the empty condition. 100 | 101 |

102 | Block Interface 103 |

104 | 105 | ### 6. Write Pointer and Full-Flag Logic ([FIFO_WR.v](./FIFO_WR.v)) 106 | - This module operates entirely within the write-clock domain. 107 | - It contains the FIFO write pointer and logic for generating the full condition. 108 | 109 |

110 | Block Interface 111 |

112 | 113 | ### 7. Gray Code Converter ([GRAY_CONV.v](./GRAY_CONV.v)) 114 | - The `GRAY_CONV.v` module is responsible for converting binary pointers into Gray encoded pointers. 115 | - Gray encoding is used to decrease synchronization errors when passing pointers between clock domains, ensuring reliable calculation of empty and full flags. 116 | 117 |

118 | Block Interface 119 |

120 | 121 | ## [Testbench](./ASYNC_FIFO_tb.v) 122 | 123 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/5ff86d80-e1f6-40b8-9f8f-069a776561d2) 124 | 125 | ``` 126 | MEMORY[ 0]: CAPTURE PASSED 127 | MEMORY[ 1]: CAPTURE PASSED 128 | MEMORY[ 2]: CAPTURE PASSED 129 | MEMORY[ 3]: CAPTURE PASSED 130 | MEMORY[ 4]: CAPTURE PASSED 131 | MEMORY[ 5]: CAPTURE PASSED 132 | MEMORY[ 6]: CAPTURE PASSED 133 | MEMORY[ 7]: CAPTURE PASSED 134 | MEMORY[ 8]: CAPTURE PASSED 135 | MEMORY[ 9]: CAPTURE PASSED 136 | MEMORY[10]: CAPTURE PASSED 137 | MEMORY[11]: CAPTURE PASSED 138 | MEMORY[12]: CAPTURE PASSED 139 | MEMORY[13]: CAPTURE PASSED 140 | MEMORY[14]: CAPTURE PASSED 141 | MEMORY[15]: CAPTURE PASSED 142 | ``` 143 | 144 | [^1]: https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjcscnm_MKBAxWpV6QEHcLyDzQQFnoECBoQAQ&url=http%3A%2F%2Fwww.sunburst-design.com%2Fpapers%2FCummingsSNUG2002SJ_FIFO1.pdf&usg=AOvVaw3-qzaucL9OsvhhA5RKZqaM&opi=89978449 145 | -------------------------------------------------------------------------------- /BACKEND/README.md: -------------------------------------------------------------------------------- 1 | # ASIC Flow Overview 2 | This document provides an overview of the Application-Specific Integrated Circuit (ASIC) design flow, outlining the key phases from RTL design to DFT insertion. Each phase contributes to the successful creation of a custom digital integrated circuit. 3 | 4 | ## RTL Design 5 | The RTL (Register-Transfer Level) design phase is the starting point for ASIC development. During this phase, the system's functionality is described using hardware description languages (HDLs) like Verilog or VHDL. Designers create high-level representations of digital logic, specifying the interconnections and operations of various components within the ASIC. 6 | 7 | ### [SYS_TOP](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/blob/e372c26c84a87c1082fa384b7910256214bcdd2b/SYS_TOP.v) Simulation Result 8 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/483872b1-8df3-444a-9c0b-e4492cf6961b) 9 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/239aa19b-8427-4012-a0eb-947abbc0a26c) 10 | 11 | ``` 12 | # Write Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=32 13 | # Read Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=32 14 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=32 15 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=32 16 | # Write Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=32 17 | # Read Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=32 18 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=32 19 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=32 20 | # Write Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=32 21 | # Read Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=32 22 | # ALU Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=32 23 | # ALU Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=32 24 | # Write Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=16 25 | # Read Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=16 26 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=16 27 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE=16 28 | # Write Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=16 29 | # Read Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=16 30 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=16 31 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE=16 32 | # Write Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=16 33 | # Read Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=16 34 | # ALU Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=16 35 | # ALU Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE=16 36 | # Write Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE= 8 37 | # Read Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE= 8 38 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE= 8 39 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=0 PRESCALE= 8 40 | # Write Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE= 8 41 | # Read Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE= 8 42 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE= 8 43 | # ALU Operation is succeeded with configurations PARITY_ENABLE=1 PARITY_TYPE=1 PRESCALE= 8 44 | # Write Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE= 8 45 | # Read Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE= 8 46 | # ALU Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE= 8 47 | # ALU Operation is succeeded with configurations PARITY_ENABLE=0 PARITY_TYPE=0 PRESCALE= 8 48 | ``` 49 | 50 | ## [Synthesis](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/tree/523d0aed7bb8a34674a57778fa5e1acd2a9f78f2/System%20Top/Synthesis) 51 | Once the RTL design is complete, synthesis is the next crucial step. In this phase, the RTL code is transformed into a gate-level netlist. The synthesis tool maps the RTL description onto specific target libraries, optimizing for factors like area, power, and speed. The result is a gate-level representation of the design, which can be further optimized. 52 | 53 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/f785937b-2dbe-46fe-916f-efcdfd1c4a6b) 54 | 55 | ## Post-Synthesis Formal Verification 56 | After synthesis, formal verification techniques are employed to ensure that the gate-level netlist accurately reflects the original RTL design. Formal methods, such as model checking and equivalence checking, are used to mathematically verify that the design behaves as intended. This phase helps identify and rectify any discrepancies introduced during synthesis. 57 | 58 |

59 | Post-Synthesis Formal Verification 60 |

61 | 62 | ## [DFT Insertion](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/tree/bbccaeeca005c569c398ab85718bef4f8792171a/System%20Top/DFT) 63 | 64 | Design for Testability (DFT) is a critical phase in ASIC development, aimed at ensuring efficient testing of the final chip. During DFT insertion, various test structures, such as scan chains and boundary scan cells, are added to the design. These structures enable comprehensive testing of the ASIC's functionality and help diagnose and debug any faults. 65 | 66 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/3d1456b6-1ae7-4273-8c3a-dbb44bf4f703) 67 | 68 | ## [Post-DFT Formal Verification](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/tree/bbccaeeca005c569c398ab85718bef4f8792171a/System%20Top/Formal%20Verification%20(POST-DFT)) 69 | 70 | Following DFT insertion, formal verification is once again applied to the modified design. This phase ensures that the test structures and DFT logic are correctly integrated into the ASIC and that they do not introduce any unintended behavior. Formal methods play a crucial role in confirming that the DFT enhancements do not compromise the design's integrity. 71 | 72 |

73 | Your Image Description 74 |

75 | 76 | ## Physical Design and Place-and-Route (PnR) 77 | In the Physical Design phase, the logical design is translated into a physical layout. This involves defining the exact locations and sizes of transistors, interconnections, and metal layers on the silicon wafer. The Place-and-Route (PnR) tool plays a crucial role in determining the optimal placement of components and routing of connections to meet performance, power, and area constraints. 78 | 79 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/52642dbb-2578-4752-8659-6e1cdb923e48) 80 | 81 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/a95fc600-16e8-4180-bece-a7766279dc10) 82 | 83 | 84 | -------------------------------------------------------------------------------- /UART/UART RX/README.md: -------------------------------------------------------------------------------- 1 | # UART RX (Receiver) Block 2 | 3 | ## Overview 4 | The UART RX (Receiver) block is a pivotal component in our multi-clock domain system, responsible for receiving UART frames and ensuring data integrity. It plays a crucial role in receiving and processing data from a master device through the UART interface. 5 | 6 | ## Block Description 7 | The UART RX block serves several essential functions: 8 | 9 | - **Receiving UART Frames:** It receives UART frames on the `RX_IN` input and processes them for data extraction. 10 | 11 | - **Oversampling Support:** UART RX supports oversampling by 8, 16, or 32, ensuring accurate data reception even at different clock speeds. 12 | 13 | - **Data Validation:** The block checks the received frame for correctness and integrity. If the frame is corrupted, it raises error flags (`PAR_ERR` for parity error and `STP_ERR` for stop bit error). 14 | 15 | - **Data Extraction:** Once the received frame is verified as correct and not corrupted, data is extracted and sent through the `P_DATA` bus, accompanied by the `DATA_VLD` signal. 16 | 17 | - **Consecutive Frame Acceptance:** UART_RX can accept consecutive frames without any gap, ensuring smooth data reception. 18 | 19 | ## Block Interface 20 | The UART RX block has the following interface: 21 | 22 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/ebbaaca8-8b95-4411-8e09-5472c0408fc7) 23 | 24 | - **Inputs:** 25 | - `i_clk`: Clock signal for sequential elements. 26 | - `i_rst_n`: Active-low asynchronous reset signal to clear registers. 27 | - `i_prescale`: Configuration signal for oversampling (8, 16, or 32 times). 28 | - `i_serial_data`: Input for the UART frame data. 29 | - `i_parity_enable`: Configuration signal to enable/disable the frame parity bit (0 for disable, 1 for enable). 30 | - `i_parity_type`: Configuration signal for parity type (0 for even, 1 for odd). 31 | 32 | - **Outputs:** 33 | - `o_data_valid`: Signal indicating the validity of the received data. 34 | - `o_parity_error`: Signal indicating a parity error in the received frame. 35 | - `o_stop_error`: Signal indicating a stop bit error in the received frame. 36 | - `o_parallel_data`: Output bus for the extracted data from the received frame. 37 | 38 | > For a better understanding of how the UART RX block is implemented in RTL (Register-Transfer Level) code, please refer to the [`UART_RX.v`](./UART_RX.v) file in this repository. 39 | 40 | ## Specifications 41 | To effectively use the UART RX block, consider the following specifications: 42 | 43 | - UART RX receives UART frames on the `RX_IN` input. 44 | 45 | - It supports oversampling by 8, 16, or 32 times, ensuring accurate data reception at different clock speeds. 46 | 47 | - The `RX_IN` input is high in the IDLE case (No transmission). 48 | 49 | - The `PAR_ERR` signal is high when the calculated parity bit does not match the received frame's parity bit, indicating a corrupted frame. 50 | 51 | - The `STP_ERR` signal is high when the received stop bit is not equal to 1, indicating a corrupted frame. 52 | 53 | - Data is extracted from the received frame and sent through the `P_DATA` bus, accompanied by the `DATA_VLD` signal, only after verifying that the frame is received correctly and not corrupted (`PAR_ERR = 0` and `STP_ERR = 0`). 54 | 55 | - UART_RX can accept consecutive frames without any gap, ensuring smooth data reception. 56 | 57 | - The block is cleared using the asynchronous active low reset signal `i_rst_n`. 58 | 59 | - Configuration: 60 | - `i_parity_enable` (Parity Configuration): 61 | - 0: Disables the frame parity bit. 62 | - 1: Enables the frame parity bit. 63 | - `i_parity_type` (Parity Type Configuration): 64 | - 0: Specifies even parity. 65 | - 1: Specifies odd parity. 66 | 67 | - The prescale value determines the clock speed of UART_RX to the speed of UART_TX. 68 | 69 | ## Elaborated Design 70 | The UART RX block is composed of several essential components, each serving a unique function: 71 | 72 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/770cb745-842c-40b8-8467-7777ac143f86) 73 | 74 | ### 1. Deserializer ([deserializer.v](./deserializer.v)) 75 | The Deserializer converts the incoming serial data into parallel data, making it accessible for further processing within the block. 76 | 77 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/6caa323c-978d-4428-8193-aa0e57ca87fe) 78 | 79 | ### 2. Edge Bit Counter ([edge_bit_counter.v](./edge_bit_counter.v)) 80 | The Edge Bit Counter is used to determine the sampling time at the mid-time of each bit, ensuring accurate data sampling. 81 | 82 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/8146708a-31a1-4bbf-8854-ad1ad2c37863) 83 | 84 | ### 3. Data Sampling ([data_sampling.v](./data_sampling.v)) 85 | Data Sampling is responsible for the actual sampling of the received data, ensuring that the data is captured accurately. 86 | 87 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/bf634e67-29b9-4d28-8834-422bf6c312f0) 88 | 89 | ### 4. Parity Check ([parity_check.v](./parity_check.v)) 90 | The Parity Check component verifies the parity bit in the received frame, ensuring data integrity. If the parity bit does not match, a `PAR_ERR` signal is raised. 91 | 92 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/3851e579-3328-47f5-88ad-cba65af039d7) 93 | 94 | ### 5. Start Bit Check ([start_check.v](./start_check.v)) 95 | Start Bit Check verifies the start bit of the received frame to ensure that data reception begins correctly. 96 | 97 |

98 | Block Interface 99 |

100 | 101 | ### 6. Stop Bit Check ([stop_check.v](./stop_check.v)) 102 | Stop Bit Check ensures that the stop bit of the received frame is set to 1, indicating the end of data transmission. If the stop bit is incorrect, an `STP_ERR` signal is raised. 103 | 104 |

105 | Block Interface 106 |

107 | 108 | ### 7. Finite State Machine (FSM) ([FSM.v](./FSM.v)) 109 | The Finite State Machine (FSM) governs the overall flow of the UART RX block, orchestrating the transitions between different states based on received data and control signals. 110 | 111 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/d34060b6-3834-4e73-895f-5bc902084a36) 112 | 113 | ## [Testbench](./UART_RX_tb.v) 114 | 115 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/96a602f0-0e24-40df-8d85-d0f30d61d1f3) 116 | 117 | ``` 118 | # /*********************** Prescale Testcases *************************/ 119 | # Prescale = 8: RX Period = 5ns & TX Period = 40ns [PASSED] 120 | # Prescale = 16: RX Period = 5ns & TX Period = 80ns [PASSED] 121 | # Prescale = 32: RX Period = 5ns & TX Period = 160ns [PASSED] 122 | # /*********************** Even Parity Testcases **********************/ 123 | # MISMATCH: 00000000 -> EVEN PARITY TESTCASE [PASSED] 124 | # MISMATCH: 00000000 -> EVEN PARITY TESTCASE [PASSED] 125 | # MISMATCH: 00000000 -> EVEN PARITY TESTCASE [PASSED] 126 | # /************************ Odd Parity Testcases **********************/ 127 | # MISMATCH: 00000000 -> ODD PARITY TESTCASE [PASSED] 128 | # MISMATCH: 00000000 -> ODD PARITY TESTCASE [PASSED] 129 | # MISMATCH: 00000000 -> ODD PARITY TESTCASE [PASSED] 130 | # /*********************** NO Parity Testcases ************************/ 131 | # MISMATCH: 00000000 -> NO PARITY TESTCASE [PASSED] 132 | # MISMATCH: 00000000 -> NO PARITY TESTCASE [PASSED] 133 | # MISMATCH: 00000000 -> NO PARITY TESTCASE [PASSED] 134 | # /******************** Gliches & Errors Testcases ********************/ 135 | # MISMATCH: 00000000 -> START GLITCH TESTCASE [PASSED] 136 | # MISMATCH: 00000000 -> INCORRECT STOP TESTCASE [PASSED] 137 | # MISMATCH: 00000000 -> INCORRECT PARITY TESTCASE [PASSED] 138 | # /*********************** Two Successive Bytes ***********************/ 139 | # MISMATCH: 0000000000000000 -> TWO SUCCESSIVE BYTES TESTCASE [PASSED] 140 | # /********************* Multiple Successive Bytes *********************/ 141 | ``` 142 | -------------------------------------------------------------------------------- /UART/UART RX/FSM.v: -------------------------------------------------------------------------------- 1 | module UART_RX_FSM #( 2 | parameter NO_STATES = 5 , 3 | HIGH = 1 , 4 | LOW = 0 , 5 | PAR_MAX = 11 , 6 | STAT_WIDTH = ($clog2(NO_STATES)) , 7 | FRAME_WIDTH = ($clog2(PAR_MAX) + 1) ) 8 | ( 9 | input wire clk , 10 | input wire rst , 11 | input wire RX_IN , 12 | input wire par_en , 13 | input wire par_err , 14 | input wire start_glitch , 15 | input wire stop_err , 16 | input wire [FRAME_WIDTH-2:0] bit_cnt , 17 | input wire done_sampling , 18 | output reg par_check_en , 19 | output reg start_check_en , 20 | output reg stop_check_en , 21 | output reg samp_cnt_en , 22 | output reg deser_en , 23 | output reg data_valid ); 24 | 25 | 26 | // states register declaration 27 | reg [STAT_WIDTH-1:0] current_state, next_state; 28 | 29 | // registering check_error 30 | reg check_error; 31 | 32 | // states encoding using HOT STATE 33 | localparam IDLE = 'b000; 34 | localparam start_bit = 'b001; 35 | localparam serial_data = 'b011; 36 | localparam parity_bit = 'b010; 37 | localparam stop_bit = 'b110; 38 | 39 | // current state sequential logic 40 | always @(posedge clk, negedge rst) 41 | begin 42 | if(!rst) 43 | current_state <= IDLE; 44 | else 45 | current_state <= next_state; 46 | end 47 | 48 | // next state combinational logic 49 | always @(*) 50 | begin 51 | case(current_state) 52 | IDLE: begin 53 | if(!RX_IN) 54 | next_state = start_bit; 55 | else 56 | next_state = IDLE; 57 | end 58 | 59 | start_bit: begin 60 | if((bit_cnt == 'b1) && !check_error) 61 | next_state = serial_data; 62 | else if((bit_cnt == 'b1) && check_error) 63 | next_state = IDLE; 64 | else 65 | next_state = start_bit; 66 | end 67 | 68 | serial_data: begin 69 | if((bit_cnt == 'b1001) && par_en) 70 | next_state = parity_bit; 71 | else if((bit_cnt == 'b1001) && !par_en) 72 | next_state = stop_bit; 73 | else 74 | next_state = serial_data; 75 | end 76 | 77 | parity_bit: begin 78 | if(bit_cnt == 'b1010) 79 | next_state = stop_bit; 80 | else 81 | next_state = parity_bit; 82 | end 83 | 84 | stop_bit: begin 85 | if( ((bit_cnt == 'b0) && RX_IN) || done_sampling && check_error) 86 | next_state = IDLE; 87 | else if((bit_cnt == 'b0) && !RX_IN) 88 | next_state = start_bit; 89 | else 90 | next_state = stop_bit; 91 | end 92 | 93 | default: begin 94 | next_state = IDLE; 95 | end 96 | endcase 97 | end 98 | 99 | // output combinational logic 100 | always @(*) 101 | begin 102 | case(current_state) 103 | IDLE: begin 104 | if(!RX_IN) 105 | begin 106 | samp_cnt_en = HIGH; 107 | start_check_en = LOW; 108 | deser_en = LOW; 109 | par_check_en = LOW; 110 | stop_check_en = LOW; 111 | data_valid = LOW; 112 | end 113 | else 114 | begin 115 | samp_cnt_en = LOW; 116 | start_check_en = LOW; 117 | deser_en = LOW; 118 | par_check_en = LOW; 119 | stop_check_en = LOW; 120 | data_valid = LOW; 121 | end 122 | end 123 | 124 | start_bit: begin 125 | if((bit_cnt == 'b1) && start_glitch) 126 | begin 127 | samp_cnt_en = LOW; 128 | start_check_en = LOW; 129 | deser_en = LOW; 130 | par_check_en = LOW; 131 | stop_check_en = LOW; 132 | data_valid = LOW; 133 | end 134 | else if((bit_cnt == 'b1) && !start_glitch) 135 | begin 136 | samp_cnt_en = HIGH; 137 | start_check_en = LOW; 138 | deser_en = LOW; 139 | par_check_en = LOW; 140 | stop_check_en = LOW; 141 | data_valid = LOW; 142 | end 143 | else 144 | begin 145 | samp_cnt_en = HIGH; 146 | start_check_en = (done_sampling)? HIGH:LOW; 147 | deser_en = LOW; 148 | par_check_en = LOW; 149 | stop_check_en = LOW; 150 | data_valid = LOW; 151 | end 152 | end 153 | 154 | serial_data: begin 155 | if((bit_cnt == 'b1001) && par_en) 156 | begin 157 | samp_cnt_en = HIGH; 158 | start_check_en = LOW; 159 | deser_en = LOW; 160 | par_check_en = LOW; 161 | stop_check_en = LOW; 162 | data_valid = LOW; 163 | end 164 | else if((bit_cnt == 'b1001) && !par_en) 165 | begin 166 | samp_cnt_en = HIGH; 167 | start_check_en = LOW; 168 | deser_en = LOW; 169 | par_check_en = LOW; 170 | stop_check_en = LOW; 171 | data_valid = LOW; 172 | end 173 | else 174 | begin 175 | samp_cnt_en = HIGH; 176 | start_check_en = LOW; 177 | if(done_sampling) 178 | deser_en = HIGH; 179 | else 180 | deser_en = LOW; 181 | par_check_en = LOW; 182 | stop_check_en = LOW; 183 | data_valid = LOW; 184 | end 185 | end 186 | 187 | parity_bit: begin 188 | if(bit_cnt == 'b1010) 189 | begin 190 | samp_cnt_en = HIGH; 191 | start_check_en = LOW; 192 | deser_en = LOW; 193 | par_check_en = LOW; 194 | stop_check_en = LOW; 195 | data_valid = LOW; 196 | end 197 | else 198 | begin 199 | samp_cnt_en = HIGH; 200 | start_check_en = LOW; 201 | deser_en = LOW; 202 | par_check_en = (done_sampling)? HIGH:LOW; 203 | stop_check_en = LOW; 204 | data_valid = LOW; 205 | end 206 | end 207 | 208 | stop_bit: begin 209 | if((bit_cnt == 'b0) && RX_IN) 210 | begin 211 | samp_cnt_en = LOW; 212 | start_check_en = LOW; 213 | deser_en = LOW; 214 | par_check_en = LOW; 215 | stop_check_en = LOW; 216 | data_valid = LOW; 217 | end 218 | else 219 | begin 220 | samp_cnt_en = HIGH; 221 | start_check_en = LOW; 222 | deser_en = LOW; 223 | par_check_en = LOW; 224 | stop_check_en = (done_sampling)? HIGH:LOW; 225 | data_valid = (done_sampling)? ~(check_error):LOW; 226 | end 227 | end 228 | default: begin 229 | samp_cnt_en = LOW; 230 | start_check_en = LOW; 231 | deser_en = LOW; 232 | par_check_en = LOW; 233 | stop_check_en = LOW; 234 | data_valid = LOW; 235 | end 236 | endcase 237 | end 238 | 239 | always @(posedge clk, negedge rst) 240 | begin 241 | if(!rst) 242 | check_error <= 1'b0; 243 | else if(stop_err | par_err | start_glitch) 244 | check_error <= 1'b1; 245 | else if(next_state == IDLE) 246 | check_error <= 1'b0; 247 | end 248 | endmodule -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RTL to GDS Implementation of Low Power Configurable Multi Clock Digital System 2 | 3 | It is responsible of receiving commands through UART receiver to do different system functions as register file reading/writing or doing some processing using ALU block and send result using up to 4 bytes frame through UART transmitter communication protocol 4 | 5 | ## Introduction 6 | 7 | The Low Power Configurable Multi-Clock Digital System is a sophisticated digital design realized in Verilog HDL. It serves as a versatile platform, receiving commands through a UART (Universal Asynchronous Receiver-Transmitter) receiver. It executes a wide range of system functions, including register file operations and complex computations via the ALU (Arithmetic Logic Unit) block. Subsequently, the system transmits results using a 4-byte frame through UART communication. 8 | 9 | ## Overview 10 | ### The system receives a UART Frame from the UART RX block, the first frame determines the needed command, the system offers 4 different operations: 11 | 1. Register File Write command 12 | 2. Register File Read command 13 | 3. ALU Operation command with operand 14 | 4. ALU Operation command with No operand 15 | 16 | **The UART RX parallel data undergoes synchronization before being sent to the System Controller due to the discrepancy in clock domains.** 17 | **The System Controller operates on a 50 MHz REF CLK, while the UART RX functions on a 3.6864 MHz clock.** 18 | **Synchronizing the data is crucial in ensuring its integrity during transfer.** 19 | 20 | After synchronization, the data enters the System Controller, which determines the required operation and configures the necessary control signals. Here's how the System Controller manages different tasks: 21 | 22 | 1. Register File Write Operation (0xAA): 23 | 24 | -It enables the `WrEn` signal of the Register File, indicating a write operation. 25 | 26 | -The desired `Address` for writing is specified. 27 | 28 | 2. Register File Read Operation (0xBB): 29 | 30 | -It enables the `RdEn` signal of the Register File, indicating a read operation. 31 | 32 | -The desired `Address` for reading is specified. 33 | 34 | -The data is retrieved from the Register File and sent to the UART TX. 35 | 36 | > **However, the UART TX operates on a different clock frequency, specifically 115.2 KHz. To prevent data loss due to clock domain crossing (CDC), a `FIFO` (First-In-First-Out) buffer is strategically placed just before the UART TX. This buffer ensures the orderly transmission of data without loss or corruption.** 37 | 38 | 3. ALU (Arithmetic Logic Unit) Operation (0xCC): 39 | 40 | -It activates the `ALU_EN` signal of the ALU, signaling the start of an ALU operation. 41 | 42 | -The `CLK GATE` is enabled to activate the `ALU CLK`, synchronizing it with the ALU operation. 43 | 44 | -The operands required for the operation are obtained from the Register File at the predefined addresses. 45 | 46 | -The desired function for the ALU operation is conveyed using the `ALU_FUN` signal. 47 | 48 | -The result of the ALU operation (`ALU_OUT`) is passed to the System Controller. 49 | 50 | -From there, it is sent to the FIFO for subsequent transmission to the UART TX and, ultimately, to the master. 51 | 52 | 4. ALU Operation without Operand Change (0xDD): 53 | 54 | -This configuration allows the ALU to perform an operation without altering the operands previously defined in the Register File. 55 | 56 | *These well-defined steps ensure efficient data management and processing within the Low Power Configurable Multi-Clock Digital System, even when dealing with disparate clock frequencies and multiple operations.* 57 | 58 | ### To address the presence of multiple clock domains within the system, we have implemented synchronizers. 59 | As mentioned earlier, a [Data Synchronizer](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/tree/405196392bf892d5c6059fc183e1ec9a1a9db0ec/Data%20Synchronizer) is introduced after the UART RX stage. This addition is essential to prevent the occurrence of metastability in the output byte from the UART RX when it interfaces with the SYS CTRL block. 60 | 61 | Furthermore, to mitigate metastability issues during the de-assertion of the reset signal, we have incorporated two [Reset Synchronizers](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/tree/24d94171fbf92b36649f055d8c104d8afbe419e2/Reset%20Synchronizer). Each of these synchronizers is integrated into its respective clock domain group, ensuring that reset signals are effectively synchronized across the system. 62 | 63 | To accommodate various configurations for UART sampling, we connect the highest required frequency to the i_uart_clk port. Subsequently, we utilize a [clock divider](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/tree/54e8705dad16caf8acdef827c448cbae46984f52/Clock%20Divider) to generate both the UART RX Clock and the UART TX Clock 64 | 65 | ## System Architecture 66 | 67 | This system consists of ten distinct blocks, each contributing to its overall functionality. Let's delve into these blocks: 68 | 69 | ![image](https://github.com/AhmedAmrAbdellatif1/Multi-Clock-Domain-System/assets/140100601/f9f76758-d168-41a6-8cc1-5713a302ed29) 70 | 71 | ### Clock Domain 1 (REF_CLK) 72 | 73 | #### 1. RegFile (Register File) 74 | 75 | The RegFile block serves as a data storage unit, facilitating efficient data storage and retrieval operations. 76 | 77 | #### 2. ALU (Arithmetic Logic Unit) 78 | 79 | The ALU is the computational powerhouse of the system, capable of executing a variety of arithmetic and logic operations. 80 | 81 | #### 3. Clock Gating 82 | 83 | The Clock Gating block optimizes power consumption by controlling clock signals during idle periods, reducing dynamic power consumption. 84 | 85 | #### 4. SYS_CTRL (System Controller) 86 | 87 | SYS_CTRL acts as the central hub of the system. It receives external commands, orchestrates operations across different blocks, and communicates results. 88 | 89 | ### Clock Domain 2 (UART_CLK) 90 | 91 | #### 5. UART_TX (UART Transmitter) 92 | 93 | UART_TX is responsible for transmitting data to an external device or master via UART communication. 94 | 95 | #### 6. UART_RX (UART Receiver) 96 | 97 | UART_RX receives incoming data and commands from external sources, facilitating communication with the system. 98 | 99 | #### 7. PULSE_GEN (Pulse Generator) 100 | 101 | PULSE_GEN generates pulse signals as needed within the system, contributing to various internal operations. 102 | 103 | #### 8. Clock Dividers 104 | 105 | Clock Dividers are essential for generating clocks with different frequencies and ratios, enabling precise control over timing. 106 | 107 | ### Data Synchronizers 108 | 109 | #### 9. RST Synchronizer 110 | 111 | The RST Synchronizer ensures synchronous de-assertion of asynchronous reset signals, addressing timing challenges during system operation. 112 | 113 | #### 10. Data Synchronizer 114 | 115 | The Data Synchronizer employs a unique synchronization scheme to address Clock Domain Crossing challenges, ensuring reliable data transfer between different clock domains. 116 | 117 | ## Reserved Registers 118 | 119 | This system includes several reserved registers, each serving specific functions: 120 | 121 | 1. **REG0 (Address: 0x0) - ALU Operand A** 122 | 2. **REG1 (Address: 0x1) - ALU Operand B** 123 | 3. **REG2 (Address: 0x2) - UART Configuration** 124 | - Bit 0: Parity Enable (Default: 1) 125 | - Bit 1: Parity Type (Default: 0) 126 | - Bits 7-2: Prescale (Default: 32) 127 | 4. **REG3 (Address: 0x3) - Divisor Ratio** 128 | - Bits 7-0: Division ratio (Default: 32) 129 | 130 | ## System Operation 131 | 132 | The system's operation is driven by commands received via UART_RX. It supports a wide range of operations, including ALU operations such as addition, subtraction, multiplication, division, logic operations, comparisons, and shifts. Additionally, it handles register file operations, including read and write commands. 133 | 134 | ### Supported Commands 135 | 136 | 1. Register File Write Command (3 frames) 137 | 2. Register File Read Command (2 frames) 138 | 3. ALU Operation Command with Operand (4 frames) 139 | 4. ALU Operation Command with No Operand (2 frames) 140 | 141 | ## System Specifications 142 | 143 | - Reference Clock (REF_CLK): 50 MHz 144 | - UART Clock (UART_CLK): 3.6864 MHz 145 | - Clock Divider: Always enabled (clock divider enable = 1) 146 | 147 | This system represents a remarkable achievement in digital design, combining versatility, efficiency, and precise control over multi-clock domains. Its wide range of supported operations makes it a valuable asset in various applications. 148 | 149 | -------------------------------------------------------------------------------- /UART/UART TX/UART_TX_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/100ps 2 | 3 | module UART_TX_tb(); 4 | 5 | /*******************************************************************/ 6 | ///////////////////// TB Signals Declaration //////////////////////// 7 | /*******************************************************************/ 8 | parameter WIDTH = 8; // width of the input data 9 | parameter par_frame = 11; // frame size with a parity bit 10 | parameter nopar_frame = 10; // frame size without a partiy bit 11 | parameter TESTCASES = 9; // no. of parity testcases 12 | parameter CLK_PERIOD = 5; // 200MHz frequency 13 | parameter HALF_PERIOD = 2.5; 14 | parameter EVEN = 0; // Even Parity => PAR_TYP 15 | parameter ODD = 1; // Odd Parity => PAR_TYP 16 | parameter HIGH = 1; 17 | parameter LOW = 0; 18 | 19 | 20 | // interface ports 21 | reg [WIDTH-1:0] P_DATA; 22 | reg DATA_VALID; 23 | reg PAR_EN; 24 | reg PAR_TYP; 25 | reg CLK; 26 | reg RST; 27 | wire TX_OUT; 28 | wire Busy; 29 | 30 | // register to store output serial data for testing 31 | reg [par_frame-1:0] tx_pdata; 32 | reg [nopar_frame-1:0] tx_npdata; 33 | 34 | // testing memories 35 | reg [WIDTH-1:0] input_data[0:TESTCASES-1]; 36 | reg [par_frame-1:0] expec_out [0:TESTCASES-1]; 37 | 38 | // control loop index 39 | integer i,n; 40 | 41 | /*******************************************************************/ 42 | ////////////////////////// Initial Block //////////////////////////// 43 | /*******************************************************************/ 44 | initial 45 | begin 46 | $dumpfile("UART_TX.vcd"); 47 | $dumpvars; 48 | 49 | // the .txt files has 9 rows, each 3 rows represet different testcase 50 | // first section: even parity 51 | // second section: odd parity 52 | // third section: no parity 53 | $readmemb("input_data.txt",input_data); 54 | $readmemb("expected_output.txt",expec_out); 55 | 56 | initialize(); 57 | reset(); 58 | 59 | #CLK_PERIOD 60 | n = 0; 61 | 62 | $display("/********** Even Parity Testcases **********/"); 63 | repeat(3) 64 | begin 65 | even_parity(input_data[n],expec_out[n]); 66 | n = n + 1; 67 | #CLK_PERIOD; 68 | end 69 | 70 | $display("/********** Odd Parity Testcases **********/"); 71 | repeat(3) 72 | begin 73 | odd_parity(input_data[n],expec_out[n]); 74 | n = n + 1; 75 | #CLK_PERIOD; 76 | end 77 | 78 | $display("/********** NO Parity Testcases **********/"); 79 | repeat(3) 80 | begin 81 | NO_parity(input_data[n],expec_out[n]); 82 | n = n + 1; 83 | #CLK_PERIOD; 84 | end 85 | 86 | $display("/**** Passing New Data While Transmission ****/"); 87 | adding_new_data(input_data[0],expec_out[0]); 88 | 89 | // we disabled this feature in FSM.v line 64, un-comment both to enable it 90 | //$display("/********** Two Successive Bytes **********/"); 91 | //two_success_bytes(input_data[0],expec_out[0],input_data[3],expec_out[3]); 92 | 93 | #(5*CLK_PERIOD) $stop; 94 | end 95 | 96 | /*******************************************************************/ 97 | ////////////////////////////// TASKS //////////////////////////////// 98 | /*******************************************************************/ 99 | task reset; 100 | begin 101 | RST = HIGH; 102 | #HALF_PERIOD; 103 | RST = LOW; 104 | #HALF_PERIOD 105 | RST = HIGH; 106 | tx_pdata = 'bx; // evacute the register for another test 107 | tx_npdata = 'bx; 108 | end 109 | endtask 110 | /********************************/ 111 | task initialize; 112 | begin 113 | RST = HIGH; 114 | CLK = LOW; 115 | P_DATA = 'b0; 116 | PAR_EN = LOW; 117 | PAR_TYP = LOW; 118 | DATA_VALID = LOW; 119 | end 120 | endtask 121 | /********************************/ 122 | task valid; 123 | begin 124 | DATA_VALID = HIGH; 125 | #CLK_PERIOD 126 | DATA_VALID = LOW; 127 | end 128 | endtask 129 | /********************************/ 130 | task even_parity; 131 | input [WIDTH-1:0] data; // input parallel data 132 | input [par_frame-1:0] check_data; // expected output data 133 | reg [par_frame-1:0] mismatch; // mismatch bits 134 | integer cycle; // control loop index 135 | 136 | begin 137 | reset(); 138 | P_DATA = data; 139 | PAR_EN = HIGH; 140 | PAR_TYP = EVEN; 141 | 142 | valid(); 143 | 144 | cycle = par_frame - 1; 145 | 146 | repeat(par_frame) // preserve the output serial data in a register 147 | begin 148 | @(negedge CLK) 149 | tx_pdata[cycle] = TX_OUT; 150 | cycle = cycle - 1; 151 | end 152 | 153 | #CLK_PERIOD 154 | mismatch = tx_pdata - check_data; 155 | if(tx_pdata == check_data) 156 | $display("MISMATCH: %11b -> EVEN PARITY TESTCASE [PASSED]",mismatch); 157 | else 158 | $display("MISMATCH: %11b -> EVEN PARITY TESTCASE [FAILED]",mismatch); 159 | 160 | #CLK_PERIOD; 161 | end 162 | endtask 163 | /********************************/ 164 | task odd_parity; 165 | input [WIDTH-1:0] data; 166 | input [par_frame-1:0] check_data; 167 | 168 | reg [par_frame-1:0] mismatch; 169 | integer cycle; 170 | begin 171 | reset(); 172 | P_DATA = data; 173 | PAR_EN = HIGH; 174 | PAR_TYP = ODD; 175 | 176 | valid(); 177 | 178 | cycle = par_frame - 1; 179 | repeat(par_frame) 180 | begin 181 | @(negedge CLK) 182 | tx_pdata[cycle] = TX_OUT; 183 | cycle = cycle - 1; 184 | end 185 | #CLK_PERIOD 186 | mismatch = tx_pdata - check_data; 187 | if(tx_pdata == check_data) 188 | $display("MISMATCH: %11b -> ODD PARITY TESTCASE [PASSED]",mismatch); 189 | else 190 | $display("MISMATCH: %11b -> ODD PARITY TESTCASE [FAILED]",mismatch); 191 | 192 | #CLK_PERIOD; 193 | end 194 | endtask 195 | /********************************/ 196 | task NO_parity; 197 | input [WIDTH-1:0] data; 198 | input [nopar_frame-1:0] check_data; 199 | 200 | reg [nopar_frame-1:0] mismatch; 201 | integer cycle; 202 | begin 203 | reset(); 204 | P_DATA = data; 205 | PAR_EN = LOW; 206 | 207 | valid(); 208 | 209 | cycle = nopar_frame - 1; 210 | repeat(nopar_frame) 211 | begin 212 | @(negedge CLK) 213 | tx_npdata[cycle] = TX_OUT; 214 | cycle = cycle - 1; 215 | end 216 | #CLK_PERIOD 217 | mismatch = tx_npdata - check_data; 218 | if(tx_npdata == check_data) 219 | $display("MISMATCH: %11b -> NO PARITY TESTCASE [PASSED]",mismatch); 220 | else 221 | $display("MISMATCH: %11b -> NO PARITY TESTCASE [FAILED]",mismatch); 222 | 223 | #CLK_PERIOD; 224 | end 225 | endtask 226 | /********************************/ 227 | task two_success_bytes; 228 | input [WIDTH-1:0] data_1; 229 | input [par_frame-1:0] check_data_1; 230 | input [WIDTH-1:0] data_2; 231 | input [par_frame-1:0] check_data_2; 232 | 233 | reg [2*(par_frame)-1:0] tx_o_data; 234 | reg [2*(par_frame)-1:0] mismatch; 235 | integer cycle; 236 | begin 237 | reset(); 238 | P_DATA = data_1; 239 | 240 | PAR_EN = HIGH; 241 | PAR_TYP = EVEN; 242 | 243 | valid(); 244 | 245 | cycle = 2*(par_frame)-1; 246 | repeat(par_frame) 247 | begin 248 | @(negedge CLK) 249 | tx_o_data[cycle] = TX_OUT; 250 | cycle = cycle - 1; 251 | end 252 | 253 | begin 254 | DATA_VALID = HIGH; 255 | P_DATA = data_2; 256 | PAR_EN = HIGH; 257 | PAR_TYP = ODD; 258 | end 259 | 260 | #CLK_PERIOD; 261 | DATA_VALID = LOW; 262 | repeat(par_frame) 263 | begin 264 | @(negedge CLK) 265 | tx_o_data[cycle] = TX_OUT; 266 | cycle = cycle - 1; 267 | end 268 | 269 | #CLK_PERIOD 270 | mismatch = tx_o_data - {check_data_1,check_data_2}; 271 | if(!mismatch) 272 | $display("MISMATCH: %22b -> TWO SUCCESSIVE BYTES TESTCASE [PASSED]",mismatch); 273 | else 274 | $display("MISMATCH: %22b -> TWO SUCCESSIVE BYTES [FAILED]",mismatch); 275 | 276 | #CLK_PERIOD; 277 | end 278 | endtask 279 | /********************************/ 280 | task adding_new_data; 281 | input [WIDTH-1:0] data; // input parallel data 282 | input [par_frame-1:0] check_data; // expected output data 283 | reg [par_frame-1:0] mismatch; // mismatch bits 284 | 285 | integer RANDOM; 286 | integer cycle; // control loop index 287 | 288 | begin 289 | reset(); 290 | P_DATA = data; 291 | PAR_EN = HIGH; 292 | PAR_TYP = EVEN; 293 | valid(); 294 | 295 | cycle = par_frame - 1; 296 | 297 | repeat(par_frame) // preserve the output serial data in a register 298 | begin 299 | @(negedge CLK) 300 | RANDOM = $urandom %127; // random 7-bit generator 301 | tx_pdata[cycle] = TX_OUT; 302 | cycle = cycle - 1; 303 | P_DATA = {RANDOM,~^(RANDOM)}; // random 8-bit odd parity generator 304 | end 305 | 306 | #CLK_PERIOD 307 | mismatch = tx_pdata - check_data; 308 | if(tx_pdata == check_data) 309 | $display("MISMATCH: %11b -> IGNORING INPUT TESTCASE [PASSED]",mismatch); 310 | else 311 | $display("MISMATCH: %11b -> IGNORING INPUT TESTCASE [FAILED]",mismatch); 312 | 313 | #CLK_PERIOD; 314 | end 315 | endtask 316 | /********************************/ 317 | 318 | /*******************************************************************/ 319 | ///////////////////////// Clock Generator /////////////////////////// 320 | /*******************************************************************/ 321 | always #HALF_PERIOD CLK = ~CLK; 322 | 323 | /*******************************************************************/ 324 | //////////////////////// DUT Instantiation ////////////////////////// 325 | /*******************************************************************/ 326 | UART_TX DUT ( .P_DATA(P_DATA), 327 | .DATA_VALID(DATA_VALID), 328 | .PAR_EN(PAR_EN), 329 | .PAR_TYP(PAR_TYP), 330 | .CLK(CLK), 331 | .RST(RST), 332 | .TX_OUT(TX_OUT), 333 | .Busy(Busy) ); 334 | endmodule 335 | -------------------------------------------------------------------------------- /SYS_TOP.v: -------------------------------------------------------------------------------- 1 | //***************************************************************************************************************// 2 | // Module: SYS_TOP.Valid 3 | // Project: Multi Clock Domain System 4 | // Description: 5 | //***************************************************************************************************************// 6 | 7 | module SYS_TOP #( parameter MEM_DEPTH = 8 , // RegFile and FIFO depth 8 | parameter BUS_WIDTH = 8 , // data bus width 9 | parameter ALU_WIDTH = 16 , // ALU output max width 10 | parameter ADDR_WIDTH = 4 , // address width 11 | parameter ALUFN_WIDTH = 4 , // ALU func width 12 | parameter PAR_EN = 1 , // parity enable 13 | parameter PAR_TYPE = 0 , // parity type 14 | parameter PRESCALE = 32 , // prescale value 15 | parameter DIV_RATIO = 32 , // clock div ratio 16 | parameter PTR_WIDTH = ($clog2(MEM_DEPTH)+1) ) // pointer width 17 | 18 | ( input wire i_ref_clk , // reference clock signal 19 | input wire i_uart_clk , // UART clock signal 20 | input wire i_rst_n , // Asynchronous active-low reset signal 21 | input wire i_rx_in , // input serial data 22 | output wire o_parity_err , // parity bit error 23 | output wire o_stop_err , // stop bit error 24 | output wire o_tx_out ); // output serial data 25 | 26 | /******************************************* Internal Signal Declaration *******************************************/ 27 | /********* UART RX OUTPUT SIGNALS *********/ 28 | wire x_URX_VLD ; // Out Data Valid : connected to DATA_SYNC 29 | wire [BUS_WIDTH-1:0] x_URX_OUT ; // Parallel Out Data Bus : connected to DATA_SYNC 30 | 31 | /******** DATA _SYNC OUTPUT SIGNALS *******/ 32 | wire [BUS_WIDTH-1:0] x_DS_OUT ; // Synchronized Data Bus : connected to SYS_CTRL 33 | wire x_DS_pulse ; // Enable Pulse Signal : connected to SYS_CTRL 34 | 35 | /******** Sys Ctrl OUTPUT SIGNALS *********/ 36 | wire [ALUFN_WIDTH-1:0] x_ALU_fun ; // ALU Function Signal : connected to ALU 37 | wire x_ALU_en ; // ALU Enable Signal : connected to ALU 38 | wire x_CG_en ; // Clock Gate Enable Signal : connected to CLK_GATE 39 | wire [ADDR_WIDTH-1:0] x_Reg_addr ; // Address Bus : connected to RegFile 40 | wire x_Reg_WrEn ; // Write Enable Signal : connected to RegFile 41 | wire x_Reg_RdEn ; // Read Enable Signal : connected to RegFile 42 | wire [BUS_WIDTH-1:0] x_Reg_WrData ; // Write Data Bus : connected to RegFile 43 | wire [BUS_WIDTH-1:0] x_UTX_data ; // Parallel Data Bus : connected to UART_TX 44 | wire x_UTX_VLD ; // Parallel Data Valid : connected to UART_TX 45 | wire x_CD_en ; // Clock Divider Enable : connected to ClkDiv 46 | wire [BUS_WIDTH-3:0] x_CD_RX ; // Clock Divider RX ratio : connected to ClkDiv 47 | 48 | /*********** ALU OUTPUT SIGNALS ***********/ 49 | wire [ALU_WIDTH-1:0] x_ALU_out ; // ALU Result : connected to SYS_CTRL 50 | wire x_ALU_vld ; // Result Valid : connected to SYS_CTRL 51 | 52 | /********* RegFile OUTPUT SIGNALS *********/ 53 | wire [BUS_WIDTH-1:0] x_Reg_RdData ; // Read Data Bus : connected to SYS_CTRL 54 | wire [BUS_WIDTH-1:0] x_Reg_REG0 ; // Register at Address 0x0 : connected to ALU 55 | wire [BUS_WIDTH-1:0] x_Reg_REG1 ; // Register at Address 0x1 : connected to ALU 56 | wire [BUS_WIDTH-1:0] x_Reg_REG2 ; // Register at Address 0x2 : connected to UART 57 | wire [BUS_WIDTH-1:0] x_Reg_REG3 ; // Register at Address 0x3 : connected to ClkDiv 58 | wire x_Reg_RdVld ; // Read Data Valid : connected to SYS_CTRL 59 | 60 | /******** ASYNC_FIFO OUTPUT SIGNALS *******/ 61 | wire [BUS_WIDTH-1:0] x_FIFO_RData ; // Read Data Bus : connected to UART_TX 62 | wire x_FIFO_EMPTY ; // FIFO Buffer empty flag : connected to UART_TX 63 | wire x_FIFO_FULL ; // FIFO Buffer full flag : connected to SYS_CTRL 64 | 65 | /********** UART TX OUTPUT SIGNALS ********/ 66 | wire x_UTX_busy ; // UART TX Status Signal : connected to PULSE_GEN 67 | 68 | /********* Pulse Gen OUTPUT SIGNALS *******/ 69 | wire x_PG_pulse ; // Pulse signal : connected to ASYNC_FIFO 70 | 71 | /********* Clk Gate OUTPUT SIGNALS ********/ 72 | wire x_CG_ALUclk ; // Gated Clock signal : connected to ALU 73 | 74 | /********* Clk Div OUTPUT SIGNALS *********/ 75 | wire x_UTX_CLK ; // Divided Clock Signal : connected to UART_TX 76 | wire x_URX_CLK ; // Divided Clock Signal : connected to UART_RX 77 | 78 | /******** RST_SYNC OUTPUT SIGNALS *********/ 79 | wire x_RST_SYNC1 ; // Active Low synchronized Reset : connected to ASYNC_FIFO 80 | wire x_RST_SYNC2 ; // Active Low synchronized Reset : connected to UART 81 | 82 | 83 | 84 | /********************************************* IP Blocks Instantiation *********************************************/ 85 | /********* UART RX instantiation **********/ 86 | UART_RX #( 87 | .WIDTH ( BUS_WIDTH ) 88 | 89 | ) U0_UART_RX ( 90 | .i_clk ( x_URX_CLK ) , 91 | .i_rst_n ( x_RST_SYNC2 ) , 92 | .i_prescale ( x_Reg_REG2[7:2] ) , 93 | .i_serial_data ( i_rx_in ) , 94 | .i_parity_enable ( x_Reg_REG2[0] ) , 95 | .i_parity_type ( x_Reg_REG2[1] ) , 96 | .o_parity_error ( o_parity_err ) , 97 | .o_stop_error ( o_stop_err ) , 98 | .o_data_valid ( x_URX_VLD ) , 99 | .o_parallel_data ( x_URX_OUT ) ); 100 | 101 | /**** Data Synchronizer instantiation *****/ 102 | DATA_SYNC #( 103 | .BUS_WIDTH ( BUS_WIDTH ) 104 | 105 | ) U0_DATA_SYNC ( 106 | .dest_clk ( i_ref_clk ) , 107 | .dest_rst ( x_RST_SYNC1 ) , 108 | .bus_enable ( x_URX_VLD ) , 109 | .unsync_bus ( x_URX_OUT ) , 110 | .sync_bus ( x_DS_OUT ) , 111 | .enable_pulse ( x_DS_pulse ) ); 112 | 113 | /********* Sys Ctrl instantiation *********/ 114 | SYS_CTRL #( 115 | .ALU_WIDTH ( ALU_WIDTH ), 116 | .ADDR_WIDTH ( ADDR_WIDTH ), 117 | .ALUFN_WIDTH ( ALUFN_WIDTH ), 118 | .DATA_BUS_WIDTH ( BUS_WIDTH ) 119 | 120 | ) U0_SYS_CTRL ( 121 | .CLK ( i_ref_clk ) , 122 | .RST ( x_RST_SYNC1 ) , 123 | .ALU_OUT ( x_ALU_out ) , 124 | .OUT_Valid ( x_ALU_vld ) , 125 | .RX_P_Data ( x_DS_OUT ) , 126 | .RX_D_VLD ( x_DS_pulse ) , 127 | .RdData ( x_Reg_RdData ) , 128 | .RdData_Valid ( x_Reg_RdVld ) , 129 | .Prescale_RX ( x_Reg_REG2[7:2]) , 130 | .ClkDiv_RX ( x_CD_RX ) , 131 | .FIFO_FULL ( x_FIFO_FULL ) , 132 | .ALU_EN ( x_ALU_en ) , 133 | .ALU_FUN ( x_ALU_fun ) , 134 | .CLK_EN ( x_CG_en ) , 135 | .Address ( x_Reg_addr ) , 136 | .WrEn ( x_Reg_WrEn ) , 137 | .RdEn ( x_Reg_RdEn ) , 138 | .WrData ( x_Reg_WrData ) , 139 | .TX_P_Data ( x_UTX_data ) , 140 | .TX_D_VLD ( x_UTX_VLD ) , 141 | .clk_div_en ( x_CD_en ) ); 142 | 143 | /*********** ALU instantiation ************/ 144 | ALU #( 145 | .OUT_WIDTH( ALU_WIDTH ), 146 | .OPRND_WIDTH( BUS_WIDTH ), 147 | .CTRL_WIDTH( ALUFN_WIDTH ) 148 | 149 | ) U0_ALU ( 150 | .CLK ( x_CG_ALUclk ) , 151 | .RST ( x_RST_SYNC1 ) , 152 | .Enable ( x_ALU_en ) , 153 | .A ( x_Reg_REG0 ) , 154 | .B ( x_Reg_REG1 ) , 155 | .ALU_FUN ( x_ALU_fun ) , 156 | .ALU_OUT ( x_ALU_out ) , 157 | .OUT_VALID ( x_ALU_vld ) ); 158 | 159 | /********** RegFile instantiation **********/ 160 | RegFile #( 161 | .DEPTH ( MEM_DEPTH ), 162 | .PAR_EN ( PAR_EN ), 163 | .PAR_TYPE ( PAR_TYPE ), 164 | .PRESCALE ( PRESCALE ), 165 | .DIV_RATIO ( DIV_RATIO), 166 | .BUS_WIDTH ( BUS_WIDTH ), 167 | .ADDR_WIDTH ( ADDR_WIDTH ) 168 | 169 | ) U0_RegFile ( 170 | .CLK ( i_ref_clk ) , 171 | .RST ( x_RST_SYNC1 ) , 172 | .WrEn ( x_Reg_WrEn ) , 173 | .RdEn ( x_Reg_RdEn ) , 174 | .Address ( x_Reg_addr ) , 175 | .WrData ( x_Reg_WrData ) , 176 | .REG0 ( x_Reg_REG0 ) , 177 | .REG1 ( x_Reg_REG1 ) , 178 | .REG2 ( x_Reg_REG2 ) , 179 | .REG3 ( x_Reg_REG3 ) , 180 | .RdData ( x_Reg_RdData ) , 181 | .RdData_Valid ( x_Reg_RdVld ) ); 182 | 183 | /********* ASYNC FIFO instantiation ********/ 184 | ASYNC_FIFO #( 185 | .DATA_WIDTH ( BUS_WIDTH ), 186 | .MEM_DEPTH ( MEM_DEPTH ), 187 | .PTR_WIDTH ( PTR_WIDTH ) 188 | 189 | ) U0_ASYNC_FIFO ( 190 | .i_Wclk ( i_ref_clk ) , 191 | .i_Wrst_n ( x_RST_SYNC1 ) , 192 | .i_Winc ( x_UTX_VLD ) , 193 | .i_Rclk ( x_UTX_CLK ) , 194 | .i_Rrst_n ( x_RST_SYNC2 ) , 195 | .i_Rinc ( x_PG_pulse ) , 196 | .i_Wdata ( x_UTX_data ) , 197 | .o_full ( x_FIFO_FULL ) , 198 | .o_Rdata ( x_FIFO_RData ) , 199 | .o_empty ( x_FIFO_EMPTY ) ); 200 | 201 | /********* RST SYNC instantiation **********/ 202 | RST_SYNC U0_RST_SYNC ( 203 | .CLK ( i_ref_clk ) , 204 | .RST ( i_rst_n ) , 205 | .SYNC_RST ( x_RST_SYNC1 ) ); 206 | 207 | RST_SYNC U1_RST_SYNC ( 208 | .CLK ( i_uart_clk ) , 209 | .RST ( i_rst_n ) , 210 | .SYNC_RST ( x_RST_SYNC2 ) ); 211 | 212 | /********** CLK DIV instantiation **********/ 213 | ClkDiv #(.RATIO_WIDTH ( BUS_WIDTH-2 )) U0_ClkDiv ( 214 | .i_ref_clk ( i_uart_clk ) , 215 | .i_rst_n ( x_RST_SYNC2 ) , 216 | .i_clk_en ( x_CD_en ) , 217 | .i_div_ratio ( x_CD_RX ) , 218 | .o_div_clk ( x_URX_CLK ) ); 219 | 220 | ClkDiv U1_ClkDiv ( 221 | .i_ref_clk ( i_uart_clk ) , 222 | .i_rst_n ( x_RST_SYNC2 ) , 223 | .i_clk_en ( x_CD_en ) , 224 | .i_div_ratio ( x_Reg_REG3 ) , 225 | .o_div_clk ( x_UTX_CLK ) ); 226 | 227 | /********* Pulse Gen instantiation *********/ 228 | PULSE_GEN U0_PULSE_GEN ( 229 | .CLK ( x_UTX_CLK ) , 230 | .RST ( x_RST_SYNC2 ) , 231 | .LVL_SIG ( x_UTX_busy ) , 232 | .PULSE_SIG ( x_PG_pulse ) ; 233 | 234 | /********* UART TX instantiation *********/ 235 | UART_TX U0_UART_TX ( 236 | .CLK ( x_UTX_CLK ) , 237 | .RST ( x_RST_SYNC2 ) , 238 | .P_DATA ( x_FIFO_RData ) , 239 | .DATA_VALID ( !x_FIFO_EMPTY ) , 240 | .PAR_EN ( x_Reg_REG2[0] ) , 241 | .PAR_TYP ( x_Reg_REG2[1] ) , 242 | .TX_OUT ( o_tx_out ) , 243 | .Busy ( x_UTX_busy ) ); 244 | 245 | /********* Clk Gate instantiation ********/ 246 | ClkGate U0_ClkGate ( 247 | .CLK ( i_ref_clk ) , 248 | .CLK_EN ( x_CG_en ) , 249 | .GATED_CLK ( x_CG_ALUclk ) ); 250 | 251 | endmodule 252 | 253 | -------------------------------------------------------------------------------- /System Controller/SYS_CTRL.v: -------------------------------------------------------------------------------- 1 | module SYS_CTRL #( parameter ALU_WIDTH = 16, ADDR_WIDTH = 4, DATA_BUS_WIDTH = 8, ALUFN_WIDTH = 4, NO_STATES = 12, STATE_WIDTH = $clog2(NO_STATES)) 2 | 3 | ( input wire CLK , // Clock Signal 4 | input wire RST , // Active Low Reset 5 | input wire [ALU_WIDTH-1:0] ALU_OUT , // ALU Result 6 | input wire OUT_Valid , // ALU Result Valid 7 | input wire [DATA_BUS_WIDTH-1:0] RX_P_Data , // UART_RX Data 8 | input wire RX_D_VLD , // RX Data Valid 9 | input wire [DATA_BUS_WIDTH-1:0] RdData , // Read Data Bus 10 | input wire RdData_Valid , // Read Data Valid 11 | input wire [DATA_BUS_WIDTH-3:0] Prescale_RX , // config prescale values 12 | input wire FIFO_FULL , // FIFO full flag 13 | output reg [DATA_BUS_WIDTH-3:0] ClkDiv_RX , // Clock Divider Ratio for RX 14 | output reg ALU_EN , // ALU Enable signal 15 | output reg [ALUFN_WIDTH-1:0] ALU_FUN , // ALU Function signal 16 | output reg CLK_EN , // Clock gate enable 17 | output reg [ADDR_WIDTH-1:0] Address , // Address bus 18 | output reg WrEn , // Write Enable 19 | output reg RdEn , // Read Enable 20 | output reg [DATA_BUS_WIDTH-1:0] WrData , // Write Data Bus 21 | output reg [DATA_BUS_WIDTH-1:0] TX_P_Data , // UART _TX Data 22 | output reg TX_D_VLD , // TX Data Valid 23 | output wire clk_div_en ); // Clock divider enable 24 | 25 | // states register declaration 26 | reg [STATE_WIDTH-1:0] current_state, next_state; 27 | 28 | // state encoding 29 | localparam S_IDLE = 'b0000; // Idle state 30 | localparam S_REG_WRT_ADRS = 'b0001; // Register File Write command: Frame 1 [Address] 31 | localparam S_REG_WRT_DATA = 'b0011; // Register File Write command: Frame 2 [Data] 32 | localparam S_REG_RD_ADRS = 'b0010; // Register File Read command: [Address] 33 | localparam S_REG_RD_OUT = 'b0110; // Register File Passing Data to output 34 | localparam S_ALU_IN_A = 'b0111; // ALU Operation with OPERAND command: Frame 1 [Operand A] 35 | localparam S_ALU_IN_B = 'b0101; // ALU Operation with OPERAND command: Frame 2 [Operand B] 36 | localparam S_ALU_FUN = 'b0100; // ALU Operation with OPERAND command: Frame 3 [ALU Func] 37 | localparam S_ALU_OUT_LSB = 'b1100; // ALU Operation with OPERAND command: Pass the output outside LSB 38 | localparam S_ALU_OUT_MSB = 'b1101; // ALU Operation with OPERAND command: Pass the output outside MSB 39 | 40 | // commands encoding 41 | localparam REG_WR_CMD = 'hAA; 42 | localparam REG_RD_CMD = 'hBB; 43 | localparam ALU_OP_CMD = 'hCC; 44 | localparam ALU_NOP_CMD = 'hDD; 45 | 46 | // registers 47 | reg [ADDR_WIDTH-1:0] addr_reg; 48 | reg [ALUFN_WIDTH-1:0] ALUFN_reg; 49 | 50 | // conditions 51 | wire CHANGE_ADDR,CHANGE_FUNC; 52 | 53 | 54 | /****************************************** *******************************************/ 55 | // current state sequential always 56 | always @(posedge CLK or negedge RST) 57 | begin 58 | if(!RST) 59 | current_state <= S_IDLE; 60 | else 61 | current_state <= next_state; 62 | end 63 | 64 | // next state & output logic 65 | always @(*) 66 | begin 67 | case(current_state) 68 | // idle state 69 | S_IDLE: begin 70 | ALU_EN = 1'b0; 71 | ALU_FUN = 'b1000; 72 | CLK_EN = 1'b0; 73 | Address = addr_reg; 74 | WrEn = 1'b0; 75 | RdEn = 1'b0; 76 | WrData = 'b0; 77 | TX_P_Data = 'hFF; 78 | TX_D_VLD = 1'b0; 79 | 80 | if(RX_D_VLD) 81 | case(RX_P_Data) 82 | REG_WR_CMD: begin 83 | ALU_EN = 1'b0; 84 | CLK_EN = 1'b0; 85 | next_state = S_REG_WRT_ADRS; 86 | end 87 | 88 | REG_RD_CMD: begin 89 | ALU_EN = 1'b0; 90 | CLK_EN = 1'b0; 91 | next_state = S_REG_RD_ADRS; 92 | end 93 | ALU_OP_CMD: begin 94 | ALU_EN = 1'b1; 95 | CLK_EN = 1'b1; 96 | next_state = S_ALU_IN_A; 97 | end 98 | ALU_NOP_CMD: begin 99 | ALU_EN = 1'b1; 100 | CLK_EN = 1'b1; 101 | next_state = S_ALU_FUN; 102 | end 103 | default: next_state = S_IDLE; 104 | endcase 105 | else 106 | next_state = S_IDLE; 107 | end 108 | 109 | 110 | // Reg Write frame 1: Address Frame 111 | S_REG_WRT_ADRS: begin 112 | ALU_EN = 1'b0; 113 | ALU_FUN = 'b1000; 114 | CLK_EN = 1'b0; 115 | WrEn = 1'b0; 116 | RdEn = 1'b0; 117 | WrData = 'b0; 118 | TX_P_Data = 'b0; 119 | TX_D_VLD = 1'b0; 120 | if(RX_D_VLD) 121 | begin 122 | Address = addr_reg; 123 | next_state = S_REG_WRT_DATA; 124 | end 125 | else 126 | begin 127 | Address = addr_reg; 128 | next_state = S_REG_WRT_ADRS; 129 | end 130 | end 131 | 132 | // Reg Write frame 2: Data Frame 133 | S_REG_WRT_DATA: begin 134 | ALU_EN = 1'b0; 135 | ALU_FUN = 'b1000; 136 | CLK_EN = 1'b0; 137 | Address = addr_reg; 138 | WrData = 'b0; 139 | TX_P_Data = 'b0; 140 | TX_D_VLD = 1'b0; 141 | 142 | if(RX_D_VLD) 143 | begin 144 | WrEn = 1'b1; 145 | RdEn = 1'b0; 146 | WrData = RX_P_Data; 147 | next_state = S_IDLE; 148 | end 149 | else 150 | begin 151 | WrEn = 1'b0; 152 | RdEn = 1'b0; 153 | WrData = 'b0; 154 | next_state = S_REG_WRT_DATA; 155 | end 156 | end 157 | 158 | // Reg Read address 159 | S_REG_RD_ADRS: begin 160 | ALU_EN = 1'b0; 161 | ALU_FUN = 'b1000; 162 | CLK_EN = 1'b0; 163 | WrEn = 1'b0; 164 | RdEn = 1'b0; 165 | WrData = 'b0; 166 | TX_P_Data = 'b0; 167 | TX_D_VLD = 1'b0; 168 | 169 | if(RX_D_VLD) 170 | begin 171 | Address = addr_reg; 172 | next_state = S_REG_RD_OUT; 173 | end 174 | else 175 | begin 176 | Address = addr_reg; 177 | next_state = S_REG_RD_ADRS; 178 | end 179 | end 180 | 181 | // Passing read data 182 | S_REG_RD_OUT: begin 183 | ALU_EN = 1'b0; 184 | ALU_FUN = 'b1000; 185 | CLK_EN = 1'b0; 186 | Address = addr_reg; 187 | WrData = 'b0; 188 | WrEn = 1'b0; 189 | RdEn = 1'b1; 190 | 191 | if(RdData_Valid && !FIFO_FULL) 192 | begin 193 | TX_P_Data = RdData; 194 | TX_D_VLD = 1'b1; 195 | next_state = S_IDLE; 196 | end 197 | else 198 | begin 199 | TX_P_Data = 'b0; 200 | TX_D_VLD = 1'b0; 201 | next_state = S_REG_RD_OUT; 202 | end 203 | end 204 | 205 | // ALU Operantion with Operand command: Operand A 206 | S_ALU_IN_A: begin 207 | Address = 'h0; 208 | ALU_EN = 1'b0; 209 | ALU_FUN = 'b1000; 210 | CLK_EN = 1'b0; 211 | TX_P_Data = 'b0; 212 | TX_D_VLD = 1'b0; 213 | 214 | if(RX_D_VLD) 215 | begin 216 | WrEn = 1'b1; 217 | RdEn = 1'b0; 218 | WrData = RX_P_Data; 219 | next_state = S_ALU_IN_B; 220 | end 221 | else 222 | begin 223 | WrEn = 1'b0; 224 | RdEn = 1'b0; 225 | WrData = 'b0; 226 | next_state = S_ALU_IN_A; 227 | end 228 | end 229 | 230 | // ALU Operantion with Operand command: Operand B 231 | S_ALU_IN_B: begin 232 | Address = 'h1; 233 | ALU_EN = 1'b0; 234 | ALU_FUN = 'b1000; 235 | CLK_EN = 1'b0; 236 | TX_P_Data = 'b0; 237 | TX_D_VLD = 1'b0; 238 | 239 | if(RX_D_VLD) 240 | begin 241 | WrEn = 1'b1; 242 | RdEn = 1'b0; 243 | WrData = RX_P_Data; 244 | next_state = S_ALU_FUN; 245 | end 246 | else 247 | begin 248 | WrEn = 1'b0; 249 | RdEn = 1'b0; 250 | WrData = 'b0; 251 | next_state = S_ALU_IN_B; 252 | end 253 | end 254 | 255 | // ALU Operantion with Operand command: ALU FUNC 256 | S_ALU_FUN: begin 257 | ALU_EN = 1'b1; 258 | CLK_EN = 1'b1; 259 | Address = addr_reg; 260 | WrEn = 1'b0; 261 | RdEn = 1'b0; 262 | WrData = 'b0; 263 | TX_P_Data = 'b0; 264 | TX_D_VLD = 1'b0; 265 | WrEn = 1'b0; 266 | RdEn = 1'b0; 267 | 268 | if(RX_D_VLD) 269 | begin 270 | ALU_FUN = RX_P_Data; 271 | next_state = S_ALU_OUT_LSB; 272 | end 273 | else 274 | begin 275 | ALU_FUN = 'b1000; 276 | next_state = S_ALU_FUN; 277 | end 278 | end 279 | 280 | // Passing the ALU result 281 | S_ALU_OUT_LSB: begin 282 | ALU_EN = 1'b1; 283 | CLK_EN = 1'b1; 284 | ALU_FUN = ALUFN_reg; 285 | Address = addr_reg; 286 | WrEn = 1'b0; 287 | RdEn = 1'b0; 288 | WrData = 'b0; 289 | WrEn = 1'b0; 290 | RdEn = 1'b0; 291 | 292 | if(OUT_Valid && !FIFO_FULL) 293 | begin 294 | 295 | TX_P_Data = ALU_OUT[DATA_BUS_WIDTH-1:0]; 296 | TX_D_VLD = 1'b1; 297 | next_state = S_ALU_OUT_MSB; 298 | end 299 | else 300 | begin 301 | TX_P_Data = 'b0; 302 | TX_D_VLD = 1'b0; 303 | next_state = S_ALU_OUT_LSB; 304 | end 305 | end 306 | 307 | // Passing the ALU result 308 | S_ALU_OUT_MSB: begin 309 | ALU_EN = 1'b1; 310 | CLK_EN = 1'b1; 311 | Address = addr_reg; 312 | WrEn = 1'b0; 313 | RdEn = 1'b0; 314 | WrData = 'b0; 315 | WrEn = 1'b0; 316 | RdEn = 1'b0; 317 | 318 | if(OUT_Valid && !FIFO_FULL) 319 | begin 320 | TX_P_Data = ALU_OUT[2*DATA_BUS_WIDTH-1:DATA_BUS_WIDTH]; 321 | TX_D_VLD = 1'b1; 322 | ALU_FUN = 'b1000; 323 | next_state = S_IDLE; 324 | end 325 | else 326 | begin 327 | TX_P_Data = 'b0; 328 | TX_D_VLD = 1'b0; 329 | ALU_FUN = ALUFN_reg; 330 | next_state = S_ALU_OUT_MSB; 331 | end 332 | end 333 | 334 | default: begin 335 | ALU_EN = 1'b0; 336 | ALU_FUN = 'b1000; 337 | CLK_EN = 1'b0; 338 | Address = addr_reg; 339 | WrEn = 1'b0; 340 | RdEn = 1'b0; 341 | WrData = 'b0; 342 | TX_P_Data = 'b0; 343 | TX_D_VLD = 1'b0; 344 | next_state = S_IDLE; 345 | end 346 | endcase 347 | end 348 | 349 | 350 | 351 | // registering the addr_reg 352 | always @(posedge CLK or negedge RST) 353 | begin 354 | if(!RST) 355 | addr_reg <= 'b0; 356 | else if(CHANGE_ADDR) 357 | addr_reg <= RX_P_Data; 358 | end 359 | 360 | // registering the ALU func 361 | always @(posedge CLK or negedge RST) 362 | begin 363 | if(!RST) 364 | ALUFN_reg <= 'b1000; 365 | else if(CHANGE_FUNC) 366 | ALUFN_reg <= RX_P_Data; 367 | end 368 | 369 | // Configuring ClkDiv RX Ratio 370 | always @(*) 371 | begin 372 | case(Prescale_RX) 373 | 'd8: ClkDiv_RX = 'd4; 374 | 'd16: ClkDiv_RX = 'd2; 375 | 'd32: ClkDiv_RX = 'd1; 376 | default: ClkDiv_RX = 'd1; 377 | endcase 378 | end 379 | 380 | // change address conditions 381 | assign CHANGE_ADDR = ( (current_state == S_REG_WRT_ADRS) || 382 | (current_state == S_REG_RD_ADRS) ); 383 | 384 | // change address conditions 385 | assign CHANGE_FUNC = ( (current_state == S_ALU_FUN) ); 386 | 387 | // clock divider is always active 388 | assign clk_div_en = 1'b1; 389 | endmodule --------------------------------------------------------------------------------