diff --git a/fpga/common.mk b/fpga/common.mk index aa9308f..9e012cb 100644 --- a/fpga/common.mk +++ b/fpga/common.mk @@ -22,7 +22,7 @@ install: EXTRA_FPGA_VSRCS := verilog := $(wildcard ${INSTALL_RTL}/*/*.v) -verilog += $(wildcard ${INSTALL_RTL}/*/*/*.sv) +verilog += $(wildcard ${INSTALL_RTL}/*/*/*.v) verilog += $(wildcard ${INSTALL_RTL}/*.v) diff --git a/rtl/e203/perips/apb_adv_timer/adv_timer_apb_if.sv b/rtl/e203/perips/apb_adv_timer/adv_timer_apb_if.sv deleted file mode 100644 index d9b1d97..0000000 --- a/rtl/e203/perips/apb_adv_timer/adv_timer_apb_if.sv +++ /dev/null @@ -1,1024 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -////////////////////////////////////////////////////////// -//// -//// TIMER 0 CONFIG -//// -////////////////////////////////////////////////////////// -`define REG_TIM0_CMD 8'b00000000 //BASEADDR+0x000 -`define REG_TIM0_CFG 8'b00000001 //BASEADDR+0x004 - -`define REG_TIM0_TH 8'b00000010 //BASEADDR+0x008 - -`define REG_TIM0_CH0_TH 8'b00000011 //BASEADDR+0x00C -`define REG_TIM0_CH1_TH 8'b00000100 //BASEADDR+0x010 -`define REG_TIM0_CH2_TH 8'b00000101 //BASEADDR+0x014 -`define REG_TIM0_CH3_TH 8'b00000110 //BASEADDR+0x018 - -`define REG_TIM0_CH0_LUT 8'b00000111 //BASEADDR+0x01C -`define REG_TIM0_CH1_LUT 8'b00001000 //BASEADDR+0x020 -`define REG_TIM0_CH2_LUT 8'b00001001 //BASEADDR+0x024 -`define REG_TIM0_CH3_LUT 8'b00001010 //BASEADDR+0x028 - -`define REG_TIM0_COUNTER 8'b00001011 //BASEADDR+0x02C - -////////////////////////////////////////////////////////// -//// -//// TIMER 1 CONFIG -//// -////////////////////////////////////////////////////////// -`define REG_TIM1_CMD 8'b00010000 //BASEADDR+0x040 -`define REG_TIM1_CFG 8'b00010001 //BASEADDR+0x044 - -`define REG_TIM1_TH 8'b00010010 //BASEADDR+0x048 - -`define REG_TIM1_CH0_TH 8'b00010011 //BASEADDR+0x04C -`define REG_TIM1_CH1_TH 8'b00010100 //BASEADDR+0x050 -`define REG_TIM1_CH2_TH 8'b00010101 //BASEADDR+0x054 -`define REG_TIM1_CH3_TH 8'b00010110 //BASEADDR+0x058 - -`define REG_TIM1_CH0_LUT 8'b00010111 //BASEADDR+0x05C -`define REG_TIM1_CH1_LUT 8'b00011000 //BASEADDR+0x060 -`define REG_TIM1_CH2_LUT 8'b00011001 //BASEADDR+0x064 -`define REG_TIM1_CH3_LUT 8'b00011010 //BASEADDR+0x068 - -`define REG_TIM1_COUNTER 8'b00011011 //BASEADDR+0x06C - -////////////////////////////////////////////////////////// -//// -//// TIMER 2 CONFIG -//// -////////////////////////////////////////////////////////// -`define REG_TIM2_CMD 8'b00100000 //BASEADDR+0x080 -`define REG_TIM2_CFG 8'b00100001 //BASEADDR+0x084 - -`define REG_TIM2_TH 8'b00100010 //BASEADDR+0x088 - -`define REG_TIM2_CH0_TH 8'b00100011 //BASEADDR+0x08C -`define REG_TIM2_CH1_TH 8'b00100100 //BASEADDR+0x090 -`define REG_TIM2_CH2_TH 8'b00100101 //BASEADDR+0x094 -`define REG_TIM2_CH3_TH 8'b00100110 //BASEADDR+0x098 - -`define REG_TIM2_CH0_LUT 8'b00100111 //BASEADDR+0x09C -`define REG_TIM2_CH1_LUT 8'b00101000 //BASEADDR+0x0A0 -`define REG_TIM2_CH2_LUT 8'b00101001 //BASEADDR+0x0A4 -`define REG_TIM2_CH3_LUT 8'b00101010 //BASEADDR+0x0A8 - -`define REG_TIM2_COUNTER 8'b00101011 //BASEADDR+0x0AC - -////////////////////////////////////////////////////////// -//// -//// TIMER 3 CONFIG -//// -////////////////////////////////////////////////////////// -`define REG_TIM3_CMD 8'b00110000 //BASEADDR+0x0C0 -`define REG_TIM3_CFG 8'b00110001 //BASEADDR+0x0C4 - -`define REG_TIM3_TH 8'b00110010 //BASEADDR+0x0C8 - -`define REG_TIM3_CH0_TH 8'b00110011 //BASEADDR+0x0CC -`define REG_TIM3_CH1_TH 8'b00110100 //BASEADDR+0x0D0 -`define REG_TIM3_CH2_TH 8'b00110101 //BASEADDR+0x0D4 -`define REG_TIM3_CH3_TH 8'b00110110 //BASEADDR+0x0D8 - -`define REG_TIM3_CH0_LUT 8'b00110111 //BASEADDR+0x0DC -`define REG_TIM3_CH1_LUT 8'b00111000 //BASEADDR+0x0E0 -`define REG_TIM3_CH2_LUT 8'b00111001 //BASEADDR+0x0E4 -`define REG_TIM3_CH3_LUT 8'b00111010 //BASEADDR+0x0E8 - -`define REG_TIM3_COUNTER 8'b00111011 //BASEADDR+0x0EC - -`define REG_EVENT_CFG 8'b01000000 //BASEADDR+0x100 -`define REG_CH_EN 8'b01000001 //BASEADDR+0x104 - -module adv_timer_apb_if #( - parameter APB_ADDR_WIDTH = 12 -) ( - input logic HCLK, - input logic HRESETn, - input logic [APB_ADDR_WIDTH-1:0] PADDR, - input logic [31:0] PWDATA, - input logic PWRITE, - input logic PSEL, - input logic PENABLE, - output logic [31:0] PRDATA, - output logic PREADY, - output logic PSLVERR, - - output logic [3:0] events_en_o, - output logic [3:0] events_sel_0_o, - output logic [3:0] events_sel_1_o, - output logic [3:0] events_sel_2_o, - output logic [3:0] events_sel_3_o, - - input logic [15:0] timer0_counter_i, - input logic [15:0] timer1_counter_i, - input logic [15:0] timer2_counter_i, - input logic [15:0] timer3_counter_i, - - output logic timer0_start_o, - output logic timer0_stop_o, - output logic timer0_update_o, - output logic timer0_arm_o, - output logic timer0_rst_o, - output logic timer0_saw_o, - output logic [2:0] timer0_in_mode_o, - output logic [7:0] timer0_in_sel_o, - output logic timer0_in_clk_o, - output logic [7:0] timer0_presc_o, - output logic [15:0] timer0_th_hi_o, - output logic [15:0] timer0_th_low_o, - output logic [2:0] timer0_ch0_mode_o, - output logic [1:0] timer0_ch0_flt_o, - output logic [15:0] timer0_ch0_th_o, - output logic [15:0] timer0_ch0_lut_o, - output logic [2:0] timer0_ch1_mode_o, - output logic [1:0] timer0_ch1_flt_o, - output logic [15:0] timer0_ch1_th_o, - output logic [15:0] timer0_ch1_lut_o, - output logic [2:0] timer0_ch2_mode_o, - output logic [1:0] timer0_ch2_flt_o, - output logic [15:0] timer0_ch2_th_o, - output logic [15:0] timer0_ch2_lut_o, - output logic [2:0] timer0_ch3_mode_o, - output logic [1:0] timer0_ch3_flt_o, - output logic [15:0] timer0_ch3_th_o, - output logic [15:0] timer0_ch3_lut_o, - - output logic timer1_start_o, - output logic timer1_stop_o, - output logic timer1_update_o, - output logic timer1_arm_o, - output logic timer1_rst_o, - output logic timer1_saw_o, - output logic [2:0] timer1_in_mode_o, - output logic [7:0] timer1_in_sel_o, - output logic timer1_in_clk_o, - output logic [7:0] timer1_presc_o, - output logic [15:0] timer1_th_hi_o, - output logic [15:0] timer1_th_low_o, - output logic [2:0] timer1_ch0_mode_o, - output logic [1:0] timer1_ch0_flt_o, - output logic [15:0] timer1_ch0_th_o, - output logic [15:0] timer1_ch0_lut_o, - output logic [2:0] timer1_ch1_mode_o, - output logic [1:0] timer1_ch1_flt_o, - output logic [15:0] timer1_ch1_th_o, - output logic [15:0] timer1_ch1_lut_o, - output logic [2:0] timer1_ch2_mode_o, - output logic [1:0] timer1_ch2_flt_o, - output logic [15:0] timer1_ch2_th_o, - output logic [15:0] timer1_ch2_lut_o, - output logic [2:0] timer1_ch3_mode_o, - output logic [1:0] timer1_ch3_flt_o, - output logic [15:0] timer1_ch3_th_o, - output logic [15:0] timer1_ch3_lut_o, - - output logic timer2_start_o, - output logic timer2_stop_o, - output logic timer2_update_o, - output logic timer2_arm_o, - output logic timer2_rst_o, - output logic timer2_saw_o, - output logic [2:0] timer2_in_mode_o, - output logic [7:0] timer2_in_sel_o, - output logic timer2_in_clk_o, - output logic [7:0] timer2_presc_o, - output logic [15:0] timer2_th_hi_o, - output logic [15:0] timer2_th_low_o, - output logic [2:0] timer2_ch0_mode_o, - output logic [1:0] timer2_ch0_flt_o, - output logic [15:0] timer2_ch0_th_o, - output logic [15:0] timer2_ch0_lut_o, - output logic [2:0] timer2_ch1_mode_o, - output logic [1:0] timer2_ch1_flt_o, - output logic [15:0] timer2_ch1_th_o, - output logic [15:0] timer2_ch1_lut_o, - output logic [2:0] timer2_ch2_mode_o, - output logic [1:0] timer2_ch2_flt_o, - output logic [15:0] timer2_ch2_th_o, - output logic [15:0] timer2_ch2_lut_o, - output logic [2:0] timer2_ch3_mode_o, - output logic [1:0] timer2_ch3_flt_o, - output logic [15:0] timer2_ch3_th_o, - output logic [15:0] timer2_ch3_lut_o, - - output logic timer3_start_o, - output logic timer3_stop_o, - output logic timer3_update_o, - output logic timer3_arm_o, - output logic timer3_rst_o, - output logic timer3_saw_o, - output logic [2:0] timer3_in_mode_o, - output logic [7:0] timer3_in_sel_o, - output logic timer3_in_clk_o, - output logic [7:0] timer3_presc_o, - output logic [15:0] timer3_th_hi_o, - output logic [15:0] timer3_th_low_o, - output logic [2:0] timer3_ch0_mode_o, - output logic [1:0] timer3_ch0_flt_o, - output logic [15:0] timer3_ch0_th_o, - output logic [15:0] timer3_ch0_lut_o, - output logic [2:0] timer3_ch1_mode_o, - output logic [1:0] timer3_ch1_flt_o, - output logic [15:0] timer3_ch1_th_o, - output logic [15:0] timer3_ch1_lut_o, - output logic [2:0] timer3_ch2_mode_o, - output logic [1:0] timer3_ch2_flt_o, - output logic [15:0] timer3_ch2_th_o, - output logic [15:0] timer3_ch2_lut_o, - output logic [2:0] timer3_ch3_mode_o, - output logic [1:0] timer3_ch3_flt_o, - output logic [15:0] timer3_ch3_th_o, - output logic [15:0] timer3_ch3_lut_o, - - output logic timer0_clk_en_o, - output logic timer1_clk_en_o, - output logic timer2_clk_en_o, - output logic timer3_clk_en_o -); - - logic s_timer1_apb_in_clk; - logic s_timer2_apb_in_clk; - logic s_timer3_apb_in_clk; - logic s_timer1_apb_start; - logic s_timer1_apb_stop; - logic s_timer2_apb_start; - logic s_timer2_apb_stop; - logic s_timer3_apb_start; - logic s_timer3_apb_stop; - - logic [31:0] r_timer0_th; - logic [7:0] r_timer0_presc; - logic [7:0] r_timer0_in_sel; - logic r_timer0_in_clk; - logic [2:0] r_timer0_in_mode; - logic r_timer0_start; - logic r_timer0_stop; - logic r_timer0_update; - logic r_timer0_arm; - logic r_timer0_rst; - logic r_timer0_saw; - logic [15:0] r_timer0_ch0_th; - logic [2:0] r_timer0_ch0_mode; - logic [15:0] r_timer0_ch0_lut; - logic [1:0] r_timer0_ch0_flt; - logic [15:0] r_timer0_ch1_th; - logic [2:0] r_timer0_ch1_mode; - logic [15:0] r_timer0_ch1_lut; - logic [1:0] r_timer0_ch1_flt; - logic [15:0] r_timer0_ch2_th; - logic [2:0] r_timer0_ch2_mode; - logic [15:0] r_timer0_ch2_lut; - logic [1:0] r_timer0_ch2_flt; - logic [15:0] r_timer0_ch3_th; - logic [2:0] r_timer0_ch3_mode; - logic [15:0] r_timer0_ch3_lut; - logic [1:0] r_timer0_ch3_flt; - - logic [31:0] r_timer1_th; - logic [7:0] r_timer1_presc; - logic [7:0] r_timer1_in_sel; - logic r_timer1_in_clk; - logic [2:0] r_timer1_in_mode; - logic r_timer1_start; - logic r_timer1_stop; - logic r_timer1_update; - logic r_timer1_arm; - logic r_timer1_rst; - logic r_timer1_saw; - logic [15:0] r_timer1_ch0_th; - logic [2:0] r_timer1_ch0_mode; - logic [15:0] r_timer1_ch0_lut; - logic [1:0] r_timer1_ch0_flt; - logic [15:0] r_timer1_ch1_th; - logic [2:0] r_timer1_ch1_mode; - logic [15:0] r_timer1_ch1_lut; - logic [1:0] r_timer1_ch1_flt; - logic [15:0] r_timer1_ch2_th; - logic [2:0] r_timer1_ch2_mode; - logic [15:0] r_timer1_ch2_lut; - logic [1:0] r_timer1_ch2_flt; - logic [15:0] r_timer1_ch3_th; - logic [2:0] r_timer1_ch3_mode; - logic [15:0] r_timer1_ch3_lut; - logic [1:0] r_timer1_ch3_flt; - - logic [31:0] r_timer2_th; - logic [7:0] r_timer2_presc; - logic [7:0] r_timer2_in_sel; - logic r_timer2_in_clk; - logic [2:0] r_timer2_in_mode; - logic r_timer2_start; - logic r_timer2_stop; - logic r_timer2_update; - logic r_timer2_arm; - logic r_timer2_rst; - logic r_timer2_saw; - logic [15:0] r_timer2_ch0_th; - logic [2:0] r_timer2_ch0_mode; - logic [15:0] r_timer2_ch0_lut; - logic [1:0] r_timer2_ch0_flt; - logic [15:0] r_timer2_ch1_th; - logic [2:0] r_timer2_ch1_mode; - logic [15:0] r_timer2_ch1_lut; - logic [1:0] r_timer2_ch1_flt; - logic [15:0] r_timer2_ch2_th; - logic [2:0] r_timer2_ch2_mode; - logic [15:0] r_timer2_ch2_lut; - logic [1:0] r_timer2_ch2_flt; - logic [15:0] r_timer2_ch3_th; - logic [2:0] r_timer2_ch3_mode; - logic [15:0] r_timer2_ch3_lut; - logic [1:0] r_timer2_ch3_flt; - - logic [31:0] r_timer3_th; - logic [7:0] r_timer3_presc; - logic [7:0] r_timer3_in_sel; - logic r_timer3_in_clk; - logic [2:0] r_timer3_in_mode; - logic r_timer3_start; - logic r_timer3_stop; - logic r_timer3_update; - logic r_timer3_arm; - logic r_timer3_rst; - logic r_timer3_saw; - logic [15:0] r_timer3_ch0_th; - logic [2:0] r_timer3_ch0_mode; - logic [15:0] r_timer3_ch0_lut; - logic [1:0] r_timer3_ch0_flt; - logic [15:0] r_timer3_ch1_th; - logic [2:0] r_timer3_ch1_mode; - logic [15:0] r_timer3_ch1_lut; - logic [1:0] r_timer3_ch1_flt; - logic [15:0] r_timer3_ch2_th; - logic [2:0] r_timer3_ch2_mode; - logic [15:0] r_timer3_ch2_lut; - logic [1:0] r_timer3_ch2_flt; - logic [15:0] r_timer3_ch3_th; - logic [2:0] r_timer3_ch3_mode; - logic [15:0] r_timer3_ch3_lut; - logic [1:0] r_timer3_ch3_flt; - - logic [3:0] r_event_sel_0; - logic [3:0] r_event_sel_1; - logic [3:0] r_event_sel_2; - logic [3:0] r_event_sel_3; - logic [3:0] r_event_en ; - - logic [3:0] r_clk_en; - - logic [7:0] s_apb_addr; - - assign events_en_o = r_event_en; - assign events_sel_0_o = r_event_sel_0; - assign events_sel_1_o = r_event_sel_1; - assign events_sel_2_o = r_event_sel_2; - assign events_sel_3_o = r_event_sel_3; - - assign timer0_start_o = r_timer0_start; - assign timer0_stop_o = r_timer0_stop; - assign timer0_update_o = r_timer0_update; - assign timer0_rst_o = r_timer0_rst; - assign timer0_arm_o = r_timer0_arm; - assign timer0_saw_o = r_timer0_saw; - assign timer0_in_mode_o = r_timer0_in_mode; - assign timer0_in_sel_o = r_timer0_in_sel; - assign timer0_in_clk_o = r_timer0_in_clk; - assign timer0_presc_o = r_timer0_presc; - assign timer0_th_hi_o = r_timer0_th[31:16]; - assign timer0_th_low_o = r_timer0_th[15:0]; - assign timer0_ch0_mode_o = r_timer0_ch0_mode; - assign timer0_ch0_flt_o = r_timer0_ch0_flt; - assign timer0_ch0_th_o = r_timer0_ch0_th; - assign timer0_ch0_lut_o = r_timer0_ch0_lut; - assign timer0_ch1_mode_o = r_timer0_ch1_mode; - assign timer0_ch1_flt_o = r_timer0_ch1_flt; - assign timer0_ch1_th_o = r_timer0_ch1_th; - assign timer0_ch1_lut_o = r_timer0_ch1_lut; - assign timer0_ch2_mode_o = r_timer0_ch2_mode; - assign timer0_ch2_flt_o = r_timer0_ch2_flt; - assign timer0_ch2_th_o = r_timer0_ch2_th; - assign timer0_ch2_lut_o = r_timer0_ch2_lut; - assign timer0_ch3_mode_o = r_timer0_ch3_mode; - assign timer0_ch3_flt_o = r_timer0_ch3_flt; - assign timer0_ch3_th_o = r_timer0_ch3_th; - assign timer0_ch3_lut_o = r_timer0_ch3_lut; - - assign timer1_start_o = r_timer1_start; - assign timer1_stop_o = r_timer1_stop; - assign timer1_update_o = r_timer1_update; - assign timer1_rst_o = r_timer1_rst; - assign timer1_arm_o = r_timer1_arm; - assign timer1_saw_o = r_timer1_saw; - assign timer1_in_mode_o = r_timer1_in_mode; - assign timer1_in_sel_o = r_timer1_in_sel; - assign timer1_in_clk_o = r_timer1_in_clk; - assign timer1_presc_o = r_timer1_presc; - assign timer1_th_hi_o = r_timer1_th[31:16]; - assign timer1_th_low_o = r_timer1_th[15:0]; - assign timer1_ch0_mode_o = r_timer1_ch0_mode; - assign timer1_ch0_flt_o = r_timer1_ch0_flt; - assign timer1_ch0_th_o = r_timer1_ch0_th; - assign timer1_ch0_lut_o = r_timer1_ch0_lut; - assign timer1_ch1_mode_o = r_timer1_ch1_mode; - assign timer1_ch1_flt_o = r_timer1_ch1_flt; - assign timer1_ch1_th_o = r_timer1_ch1_th; - assign timer1_ch1_lut_o = r_timer1_ch1_lut; - assign timer1_ch2_mode_o = r_timer1_ch2_mode; - assign timer1_ch2_flt_o = r_timer1_ch2_flt; - assign timer1_ch2_th_o = r_timer1_ch2_th; - assign timer1_ch2_lut_o = r_timer1_ch2_lut; - assign timer1_ch3_mode_o = r_timer1_ch3_mode; - assign timer1_ch3_flt_o = r_timer1_ch3_flt; - assign timer1_ch3_th_o = r_timer1_ch3_th; - assign timer1_ch3_lut_o = r_timer1_ch3_lut; - - assign timer2_start_o = r_timer2_start; - assign timer2_stop_o = r_timer2_stop; - assign timer2_update_o = r_timer2_update; - assign timer2_rst_o = r_timer2_rst; - assign timer2_arm_o = r_timer2_arm; - assign timer2_saw_o = r_timer2_saw; - assign timer2_in_mode_o = r_timer2_in_mode; - assign timer2_in_sel_o = r_timer2_in_sel; - assign timer2_in_clk_o = r_timer2_in_clk; - assign timer2_presc_o = r_timer2_presc; - assign timer2_th_hi_o = r_timer2_th[31:16]; - assign timer2_th_low_o = r_timer2_th[15:0]; - assign timer2_ch0_mode_o = r_timer2_ch0_mode; - assign timer2_ch0_flt_o = r_timer2_ch0_flt; - assign timer2_ch0_th_o = r_timer2_ch0_th; - assign timer2_ch0_lut_o = r_timer2_ch0_lut; - assign timer2_ch1_mode_o = r_timer2_ch1_mode; - assign timer2_ch1_flt_o = r_timer2_ch1_flt; - assign timer2_ch1_th_o = r_timer2_ch1_th; - assign timer2_ch1_lut_o = r_timer2_ch1_lut; - assign timer2_ch2_mode_o = r_timer2_ch2_mode; - assign timer2_ch2_flt_o = r_timer2_ch2_flt; - assign timer2_ch2_th_o = r_timer2_ch2_th; - assign timer2_ch2_lut_o = r_timer2_ch2_lut; - assign timer2_ch3_mode_o = r_timer2_ch3_mode; - assign timer2_ch3_flt_o = r_timer2_ch3_flt; - assign timer2_ch3_th_o = r_timer2_ch3_th; - assign timer2_ch3_lut_o = r_timer2_ch3_lut; - - assign timer3_start_o = r_timer3_start; - assign timer3_stop_o = r_timer3_stop; - assign timer3_update_o = r_timer3_update; - assign timer3_rst_o = r_timer3_rst; - assign timer3_arm_o = r_timer3_arm; - assign timer3_saw_o = r_timer3_saw; - assign timer3_in_mode_o = r_timer3_in_mode; - assign timer3_in_sel_o = r_timer3_in_sel; - assign timer3_in_clk_o = r_timer3_in_clk; - assign timer3_presc_o = r_timer3_presc; - assign timer3_th_hi_o = r_timer3_th[31:16]; - assign timer3_th_low_o = r_timer3_th[15:0]; - assign timer3_ch0_mode_o = r_timer3_ch0_mode; - assign timer3_ch0_flt_o = r_timer3_ch0_flt; - assign timer3_ch0_th_o = r_timer3_ch0_th; - assign timer3_ch0_lut_o = r_timer3_ch0_lut; - assign timer3_ch1_mode_o = r_timer3_ch1_mode; - assign timer3_ch1_flt_o = r_timer3_ch1_flt; - assign timer3_ch1_th_o = r_timer3_ch1_th; - assign timer3_ch1_lut_o = r_timer3_ch1_lut; - assign timer3_ch2_mode_o = r_timer3_ch2_mode; - assign timer3_ch2_flt_o = r_timer3_ch2_flt; - assign timer3_ch2_th_o = r_timer3_ch2_th; - assign timer3_ch2_lut_o = r_timer3_ch2_lut; - assign timer3_ch3_mode_o = r_timer3_ch3_mode; - assign timer3_ch3_flt_o = r_timer3_ch3_flt; - assign timer3_ch3_th_o = r_timer3_ch3_th; - assign timer3_ch3_lut_o = r_timer3_ch3_lut; - - assign timer0_clk_en_o = r_clk_en[0]; - assign timer1_clk_en_o = r_clk_en[1]; - assign timer2_clk_en_o = r_clk_en[2]; - assign timer3_clk_en_o = r_clk_en[3]; - - assign s_apb_addr = PADDR[9:2]; - - always_ff @(posedge HCLK, negedge HRESETn) - begin - if(~HRESETn) - begin - r_timer0_th <= 'h0; - r_timer0_in_sel <= 'h0; - r_timer0_in_clk <= 'h0; - r_timer0_in_mode <= 'h0; - r_timer0_presc <= 'h0; - r_timer0_start <= 1'b0; - r_timer0_stop <= 1'b0; - r_timer0_update <= 1'b0; - r_timer0_arm <= 1'b0; - r_timer0_rst <= 1'b0; - r_timer0_saw <= 1'b1; - r_timer0_ch0_th <= 'h0; - r_timer0_ch0_mode <= 'h0; - r_timer0_ch0_lut <= 'h0; - r_timer0_ch0_flt <= 'h0; - r_timer0_ch1_th <= 'h0; - r_timer0_ch1_mode <= 'h0; - r_timer0_ch1_lut <= 'h0; - r_timer0_ch1_flt <= 'h0; - r_timer0_ch2_th <= 'h0; - r_timer0_ch2_mode <= 'h0; - r_timer0_ch2_lut <= 'h0; - r_timer0_ch2_flt <= 'h0; - r_timer0_ch3_th <= 'h0; - r_timer0_ch3_mode <= 'h0; - r_timer0_ch3_lut <= 'h0; - r_timer0_ch3_flt <= 'h0; - - r_timer1_th <= 'h0; - r_timer1_in_sel <= 'h0; - r_timer1_in_clk <= 'h0; - r_timer1_in_mode <= 'h0; - r_timer1_presc <= 'h0; - r_timer1_start <= 1'b0; - r_timer1_stop <= 1'b0; - r_timer1_update <= 1'b0; - r_timer1_rst <= 1'b0; - r_timer1_arm <= 1'b0; - r_timer1_saw <= 1'b1; - r_timer1_ch0_th <= 'h0; - r_timer1_ch0_mode <= 'h0; - r_timer1_ch0_lut <= 'h0; - r_timer1_ch0_flt <= 'h0; - r_timer1_ch1_th <= 'h0; - r_timer1_ch1_mode <= 'h0; - r_timer1_ch1_lut <= 'h0; - r_timer1_ch1_flt <= 'h0; - r_timer1_ch2_th <= 'h0; - r_timer1_ch2_mode <= 'h0; - r_timer1_ch2_lut <= 'h0; - r_timer1_ch2_flt <= 'h0; - r_timer1_ch3_th <= 'h0; - r_timer1_ch3_mode <= 'h0; - r_timer1_ch3_lut <= 'h0; - r_timer1_ch3_flt <= 'h0; - - r_timer2_th <= 'h0; - r_timer2_in_sel <= 'h0; - r_timer2_in_clk <= 'h0; - r_timer2_in_mode <= 'h0; - r_timer2_presc <= 'h0; - r_timer2_start <= 1'b0; - r_timer2_stop <= 1'b0; - r_timer2_update <= 1'b0; - r_timer2_rst <= 1'b0; - r_timer2_arm <= 1'b0; - r_timer2_saw <= 1'b1; - r_timer2_ch0_th <= 'h0; - r_timer2_ch0_mode <= 'h0; - r_timer2_ch0_lut <= 'h0; - r_timer2_ch0_flt <= 'h0; - r_timer2_ch1_th <= 'h0; - r_timer2_ch1_mode <= 'h0; - r_timer2_ch1_lut <= 'h0; - r_timer2_ch1_flt <= 'h0; - r_timer2_ch2_th <= 'h0; - r_timer2_ch2_mode <= 'h0; - r_timer2_ch2_lut <= 'h0; - r_timer2_ch2_flt <= 'h0; - r_timer2_ch3_th <= 'h0; - r_timer2_ch3_mode <= 'h0; - r_timer2_ch3_lut <= 'h0; - r_timer2_ch3_flt <= 'h0; - - r_timer3_th <= 'h0; - r_timer3_in_sel <= 'h0; - r_timer3_in_clk <= 'h0; - r_timer3_in_mode <= 'h0; - r_timer3_presc <= 'h0; - r_timer3_start <= 1'b0; - r_timer3_stop <= 1'b0; - r_timer3_update <= 1'b0; - r_timer3_rst <= 1'b0; - r_timer3_arm <= 1'b0; - r_timer3_saw <= 1'b1; - r_timer3_ch0_th <= 'h0; - r_timer3_ch0_mode <= 'h0; - r_timer3_ch0_lut <= 'h0; - r_timer3_ch0_flt <= 'h0; - r_timer3_ch1_th <= 'h0; - r_timer3_ch1_mode <= 'h0; - r_timer3_ch1_lut <= 'h0; - r_timer3_ch1_flt <= 'h0; - r_timer3_ch2_th <= 'h0; - r_timer3_ch2_mode <= 'h0; - r_timer3_ch2_lut <= 'h0; - r_timer3_ch2_flt <= 'h0; - r_timer3_ch3_th <= 'h0; - r_timer3_ch3_mode <= 'h0; - r_timer3_ch3_lut <= 'h0; - r_timer3_ch3_flt <= 'h0; - - r_event_sel_0 <= 'h0; - r_event_sel_1 <= 'h0; - r_event_sel_2 <= 'h0; - r_event_sel_3 <= 'h0; - r_event_en <= 'h0; - - r_clk_en <= 'h0; - - - end - else - begin - if (PSEL && PENABLE && PWRITE) - begin - case (s_apb_addr) - `REG_TIM0_TH: - r_timer0_th <= PWDATA; - `REG_TIM0_CMD: - begin - r_timer0_start <= PWDATA[0]; - r_timer0_stop <= PWDATA[1]; - r_timer0_update <= PWDATA[2]; - r_timer0_rst <= PWDATA[3]; - r_timer0_arm <= PWDATA[4]; - end - `REG_TIM0_CFG: - begin - r_timer0_in_sel <= PWDATA[7:0]; - r_timer0_in_mode<= PWDATA[10:8]; - r_timer0_in_clk <= PWDATA[11]; - r_timer0_saw <= PWDATA[12]; - r_timer0_presc <= PWDATA[23:16]; - end - `REG_TIM0_CH0_TH: - begin - r_timer0_ch0_th <= PWDATA[15:0]; - r_timer0_ch0_mode <= PWDATA[18:16]; - end - `REG_TIM0_CH0_LUT: - begin - r_timer0_ch0_lut <= PWDATA[15:0]; - r_timer0_ch0_flt <= PWDATA[17:16]; - end - `REG_TIM0_CH1_TH: - begin - r_timer0_ch1_th <= PWDATA[15:0]; - r_timer0_ch1_mode <= PWDATA[18:16]; - end - `REG_TIM0_CH1_LUT: - begin - r_timer0_ch1_lut <= PWDATA[15:0]; - r_timer0_ch1_flt <= PWDATA[17:16]; - end - `REG_TIM0_CH2_TH: - begin - r_timer0_ch2_th <= PWDATA[15:0]; - r_timer0_ch2_mode <= PWDATA[18:16]; - end - `REG_TIM0_CH2_LUT: - begin - r_timer0_ch2_lut <= PWDATA[15:0]; - r_timer0_ch2_flt <= PWDATA[17:16]; - end - `REG_TIM0_CH3_TH: - begin - r_timer0_ch3_th <= PWDATA[15:0]; - r_timer0_ch3_mode <= PWDATA[18:16]; - end - `REG_TIM0_CH3_LUT: - begin - r_timer0_ch3_lut <= PWDATA[15:0]; - r_timer0_ch3_flt <= PWDATA[17:16]; - end - - - `REG_TIM1_TH: - r_timer1_th <= PWDATA; - `REG_TIM1_CMD: - begin - r_timer1_start <= PWDATA[0]; - r_timer1_stop <= PWDATA[1]; - r_timer1_update <= PWDATA[2]; - r_timer1_rst <= PWDATA[3]; - r_timer1_arm <= PWDATA[4]; - end - `REG_TIM1_CFG: - begin - r_timer1_in_sel <= PWDATA[7:0]; - r_timer1_in_mode<= PWDATA[10:8]; - r_timer1_in_clk <= PWDATA[11]; - r_timer1_saw <= PWDATA[12]; - r_timer1_presc <= PWDATA[23:16]; - end - `REG_TIM1_CH0_TH: - begin - r_timer1_ch0_th <= PWDATA[15:0]; - r_timer1_ch0_mode <= PWDATA[18:16]; - end - `REG_TIM1_CH0_LUT: - begin - r_timer1_ch0_lut <= PWDATA[15:0]; - r_timer1_ch0_flt <= PWDATA[17:16]; - end - `REG_TIM1_CH1_TH: - begin - r_timer1_ch1_th <= PWDATA[15:0]; - r_timer1_ch1_mode <= PWDATA[18:16]; - end - `REG_TIM1_CH1_LUT: - begin - r_timer1_ch1_lut <= PWDATA[15:0]; - r_timer1_ch1_flt <= PWDATA[17:16]; - end - `REG_TIM1_CH2_TH: - begin - r_timer1_ch2_th <= PWDATA[15:0]; - r_timer1_ch2_mode <= PWDATA[18:16]; - end - `REG_TIM1_CH2_LUT: - begin - r_timer1_ch2_lut <= PWDATA[15:0]; - r_timer1_ch2_flt <= PWDATA[17:16]; - end - `REG_TIM1_CH3_TH: - begin - r_timer1_ch3_th <= PWDATA[15:0]; - r_timer1_ch3_mode <= PWDATA[18:16]; - end - `REG_TIM1_CH3_LUT: - begin - r_timer1_ch3_lut <= PWDATA[15:0]; - r_timer1_ch3_flt <= PWDATA[17:16]; - end - - `REG_TIM2_TH: - r_timer2_th <= PWDATA; - `REG_TIM2_CMD: - begin - r_timer2_start <= PWDATA[0]; - r_timer2_stop <= PWDATA[1]; - r_timer2_update <= PWDATA[2]; - r_timer2_rst <= PWDATA[3]; - r_timer2_arm <= PWDATA[4]; - end - `REG_TIM2_CFG: - begin - r_timer2_in_sel <= PWDATA[7:0]; - r_timer2_in_mode<= PWDATA[10:8]; - r_timer2_in_clk <= PWDATA[11]; - r_timer2_saw <= PWDATA[12]; - r_timer2_presc <= PWDATA[23:16]; - end - `REG_TIM2_CH0_TH: - begin - r_timer2_ch0_th <= PWDATA[15:0]; - r_timer2_ch0_mode <= PWDATA[18:16]; - end - `REG_TIM2_CH0_LUT: - begin - r_timer2_ch0_lut <= PWDATA[15:0]; - r_timer2_ch0_flt <= PWDATA[17:16]; - end - `REG_TIM2_CH1_TH: - begin - r_timer2_ch1_th <= PWDATA[15:0]; - r_timer2_ch1_mode <= PWDATA[18:16]; - end - `REG_TIM2_CH1_LUT: - begin - r_timer2_ch1_lut <= PWDATA[15:0]; - r_timer2_ch1_flt <= PWDATA[17:16]; - end - `REG_TIM2_CH2_TH: - begin - r_timer2_ch2_th <= PWDATA[15:0]; - r_timer2_ch2_mode <= PWDATA[18:16]; - end - `REG_TIM2_CH2_LUT: - begin - r_timer2_ch2_lut <= PWDATA[15:0]; - r_timer2_ch2_flt <= PWDATA[17:16]; - end - `REG_TIM2_CH3_TH: - begin - r_timer2_ch3_th <= PWDATA[15:0]; - r_timer2_ch3_mode <= PWDATA[18:16]; - end - `REG_TIM2_CH3_LUT: - begin - r_timer2_ch3_lut <= PWDATA[15:0]; - r_timer2_ch3_flt <= PWDATA[17:16]; - end - - `REG_TIM3_TH: - r_timer3_th <= PWDATA; - `REG_TIM3_CMD: - begin - r_timer3_start <= PWDATA[0]; - r_timer3_stop <= PWDATA[1]; - r_timer3_update <= PWDATA[2]; - r_timer3_rst <= PWDATA[3]; - r_timer3_arm <= PWDATA[4]; - end - `REG_TIM3_CFG: - begin - r_timer3_in_sel <= PWDATA[7:0]; - r_timer3_in_mode<= PWDATA[10:8]; - r_timer3_in_clk <= PWDATA[11]; - r_timer3_saw <= PWDATA[12]; - r_timer3_presc <= PWDATA[23:16]; - end - `REG_TIM3_CH0_TH: - begin - r_timer3_ch0_th <= PWDATA[15:0]; - r_timer3_ch0_mode <= PWDATA[18:16]; - end - `REG_TIM3_CH0_LUT: - begin - r_timer3_ch0_lut <= PWDATA[15:0]; - r_timer3_ch0_flt <= PWDATA[17:16]; - end - `REG_TIM3_CH1_TH: - begin - r_timer3_ch1_th <= PWDATA[15:0]; - r_timer3_ch1_mode <= PWDATA[18:16]; - end - `REG_TIM3_CH1_LUT: - begin - r_timer3_ch1_lut <= PWDATA[15:0]; - r_timer3_ch1_flt <= PWDATA[17:16]; - end - `REG_TIM3_CH2_TH: - begin - r_timer3_ch2_th <= PWDATA[15:0]; - r_timer3_ch2_mode <= PWDATA[18:16]; - end - `REG_TIM3_CH2_LUT: - begin - r_timer3_ch2_lut <= PWDATA[15:0]; - r_timer3_ch2_flt <= PWDATA[17:16]; - end - `REG_TIM3_CH3_TH: - begin - r_timer3_ch3_th <= PWDATA[15:0]; - r_timer3_ch3_mode <= PWDATA[18:16]; - end - `REG_TIM3_CH3_LUT: - begin - r_timer3_ch3_lut <= PWDATA[15:0]; - r_timer3_ch3_flt <= PWDATA[17:16]; - end - `REG_EVENT_CFG: - begin - r_event_sel_0 <= PWDATA[3:0]; - r_event_sel_1 <= PWDATA[7:4]; - r_event_sel_2 <= PWDATA[11:8]; - r_event_sel_3 <= PWDATA[15:12]; - r_event_en <= PWDATA[19:16]; - end - `REG_CH_EN: - begin - r_clk_en <= PWDATA[3:0]; - end - endcase // s_apb_addr - end - else - begin - r_timer0_start <= 1'b0; - r_timer0_stop <= 1'b0; - r_timer0_rst <= 1'b0; - r_timer0_update <= 1'b0; - r_timer0_arm <= 1'b0; - r_timer1_start <= 1'b0; - r_timer1_stop <= 1'b0; - r_timer1_rst <= 1'b0; - r_timer1_update <= 1'b0; - r_timer1_arm <= 1'b0; - r_timer2_start <= 1'b0; - r_timer2_stop <= 1'b0; - r_timer2_rst <= 1'b0; - r_timer2_update <= 1'b0; - r_timer2_arm <= 1'b0; - r_timer3_start <= 1'b0; - r_timer3_stop <= 1'b0; - r_timer3_rst <= 1'b0; - r_timer3_update <= 1'b0; - r_timer3_arm <= 1'b0; - end - end - end - - - - - always_comb - begin - case (s_apb_addr) - `REG_TIM0_TH: - PRDATA = r_timer0_th; - `REG_TIM1_TH: - PRDATA = r_timer1_th; - `REG_TIM2_TH: - PRDATA = r_timer2_th; - `REG_TIM3_TH: - PRDATA = r_timer3_th; - `REG_TIM0_CFG: - PRDATA = {8'h0,r_timer0_presc,3'h0,r_timer0_saw,r_timer0_in_clk,r_timer0_in_mode,r_timer0_in_sel}; - `REG_TIM0_CH0_TH: - PRDATA = {13'h0,r_timer0_ch0_mode,r_timer0_ch0_th}; - `REG_TIM0_CH0_LUT: - PRDATA = {14'h0,r_timer0_ch0_flt,r_timer0_ch0_lut}; - `REG_TIM0_CH1_TH: - PRDATA = {13'h0,r_timer0_ch1_mode,r_timer0_ch1_th}; - `REG_TIM0_CH1_LUT: - PRDATA = {14'h0,r_timer0_ch1_flt,r_timer0_ch1_lut}; - `REG_TIM0_CH2_TH: - PRDATA = {13'h0,r_timer0_ch2_mode,r_timer0_ch2_th}; - `REG_TIM0_CH2_LUT: - PRDATA = {14'h0,r_timer0_ch2_flt,r_timer0_ch2_lut}; - `REG_TIM0_CH3_TH: - PRDATA = {13'h0,r_timer0_ch3_mode,r_timer0_ch3_th}; - `REG_TIM0_CH3_LUT: - PRDATA = {14'h0,r_timer0_ch3_flt,r_timer0_ch3_lut}; - `REG_TIM1_CFG: - PRDATA = {8'h0,r_timer1_presc,3'h0,r_timer1_saw,r_timer1_in_clk,r_timer1_in_mode,r_timer1_in_sel}; - `REG_TIM1_CH0_TH: - PRDATA = {13'h0,r_timer1_ch0_mode,r_timer1_ch0_th}; - `REG_TIM1_CH0_LUT: - PRDATA = {14'h0,r_timer1_ch0_flt,r_timer1_ch0_lut}; - `REG_TIM1_CH1_TH: - PRDATA = {13'h0,r_timer1_ch1_mode,r_timer1_ch1_th}; - `REG_TIM1_CH1_LUT: - PRDATA = {14'h0,r_timer1_ch1_flt,r_timer1_ch1_lut}; - `REG_TIM1_CH2_TH: - PRDATA = {13'h0,r_timer1_ch2_mode,r_timer1_ch2_th}; - `REG_TIM1_CH2_LUT: - PRDATA = {14'h0,r_timer1_ch2_flt,r_timer1_ch2_lut}; - `REG_TIM1_CH3_TH: - PRDATA = {13'h0,r_timer1_ch3_mode,r_timer1_ch3_th}; - `REG_TIM1_CH3_LUT: - PRDATA = {14'h0,r_timer1_ch3_flt,r_timer1_ch3_lut}; - `REG_TIM2_CFG: - PRDATA = {8'h0,r_timer2_presc,3'h0,r_timer2_saw,r_timer2_in_clk,r_timer2_in_mode,r_timer2_in_sel}; - `REG_TIM2_CH0_TH: - PRDATA = {13'h0,r_timer2_ch0_mode,r_timer2_ch0_th}; - `REG_TIM2_CH0_LUT: - PRDATA = {14'h0,r_timer2_ch0_flt,r_timer2_ch0_lut}; - `REG_TIM2_CH1_TH: - PRDATA = {13'h0,r_timer2_ch1_mode,r_timer2_ch1_th}; - `REG_TIM2_CH1_LUT: - PRDATA = {14'h0,r_timer2_ch1_flt,r_timer2_ch1_lut}; - `REG_TIM2_CH2_TH: - PRDATA = {13'h0,r_timer2_ch2_mode,r_timer2_ch2_th}; - `REG_TIM2_CH2_LUT: - PRDATA = {14'h0,r_timer2_ch2_flt,r_timer2_ch2_lut}; - `REG_TIM2_CH3_TH: - PRDATA = {13'h0,r_timer2_ch3_mode,r_timer2_ch3_th}; - `REG_TIM2_CH3_LUT: - PRDATA = {14'h0,r_timer2_ch3_flt,r_timer2_ch3_lut}; - `REG_TIM3_CFG: - PRDATA = {8'h0,r_timer3_presc,3'h0,r_timer3_saw,r_timer3_in_clk,r_timer3_in_mode,r_timer3_in_sel}; - `REG_TIM3_CH0_TH: - PRDATA = {13'h0,r_timer3_ch0_mode,r_timer3_ch0_th}; - `REG_TIM3_CH0_LUT: - PRDATA = {14'h0,r_timer3_ch0_flt,r_timer3_ch0_lut}; - `REG_TIM3_CH1_TH: - PRDATA = {13'h0,r_timer3_ch1_mode,r_timer3_ch1_th}; - `REG_TIM3_CH1_LUT: - PRDATA = {14'h0,r_timer3_ch1_flt,r_timer3_ch1_lut}; - `REG_TIM3_CH2_TH: - PRDATA = {13'h0,r_timer3_ch2_mode,r_timer3_ch2_th}; - `REG_TIM3_CH2_LUT: - PRDATA = {14'h0,r_timer3_ch2_flt,r_timer3_ch2_lut}; - `REG_TIM3_CH3_TH: - PRDATA = {13'h0,r_timer3_ch3_mode,r_timer3_ch3_th}; - `REG_TIM3_CH3_LUT: - PRDATA = {14'h0,r_timer3_ch3_flt,r_timer3_ch3_lut}; - `REG_TIM0_COUNTER: - PRDATA = {16'h0,timer0_counter_i}; - `REG_TIM1_COUNTER: - PRDATA = {16'h0,timer1_counter_i}; - `REG_TIM2_COUNTER: - PRDATA = {16'h0,timer2_counter_i}; - `REG_TIM3_COUNTER: - PRDATA = {16'h0,timer3_counter_i}; - `REG_EVENT_CFG: - PRDATA = {12'h0,r_event_en,r_event_sel_3,r_event_sel_2,r_event_sel_1,r_event_sel_0}; - `REG_CH_EN: - PRDATA = {28'h0,r_clk_en}; - default: - PRDATA = 'h0; - endcase - end - - assign PREADY = 1'b1; - assign PSLVERR = 1'b0; - - endmodule // adv_timer_apb_if - diff --git a/rtl/e203/perips/apb_adv_timer/adv_timer_apb_if.v b/rtl/e203/perips/apb_adv_timer/adv_timer_apb_if.v new file mode 100644 index 0000000..c7b438f --- /dev/null +++ b/rtl/e203/perips/apb_adv_timer/adv_timer_apb_if.v @@ -0,0 +1,999 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +////////////////////////////////////////////////////////// +//// +//// TIMER 0 CONFIG +//// +////////////////////////////////////////////////////////// +`define REG_TIM0_CMD 8'b00000000 //BASEADDR+0x000 +`define REG_TIM0_CFG 8'b00000001 //BASEADDR+0x004 + +`define REG_TIM0_TH 8'b00000010 //BASEADDR+0x008 + +`define REG_TIM0_CH0_TH 8'b00000011 //BASEADDR+0x00C +`define REG_TIM0_CH1_TH 8'b00000100 //BASEADDR+0x010 +`define REG_TIM0_CH2_TH 8'b00000101 //BASEADDR+0x014 +`define REG_TIM0_CH3_TH 8'b00000110 //BASEADDR+0x018 + +`define REG_TIM0_CH0_LUT 8'b00000111 //BASEADDR+0x01C +`define REG_TIM0_CH1_LUT 8'b00001000 //BASEADDR+0x020 +`define REG_TIM0_CH2_LUT 8'b00001001 //BASEADDR+0x024 +`define REG_TIM0_CH3_LUT 8'b00001010 //BASEADDR+0x028 + +`define REG_TIM0_COUNTER 8'b00001011 //BASEADDR+0x02C + +////////////////////////////////////////////////////////// +//// +//// TIMER 1 CONFIG +//// +////////////////////////////////////////////////////////// +`define REG_TIM1_CMD 8'b00010000 //BASEADDR+0x040 +`define REG_TIM1_CFG 8'b00010001 //BASEADDR+0x044 + +`define REG_TIM1_TH 8'b00010010 //BASEADDR+0x048 + +`define REG_TIM1_CH0_TH 8'b00010011 //BASEADDR+0x04C +`define REG_TIM1_CH1_TH 8'b00010100 //BASEADDR+0x050 +`define REG_TIM1_CH2_TH 8'b00010101 //BASEADDR+0x054 +`define REG_TIM1_CH3_TH 8'b00010110 //BASEADDR+0x058 + +`define REG_TIM1_CH0_LUT 8'b00010111 //BASEADDR+0x05C +`define REG_TIM1_CH1_LUT 8'b00011000 //BASEADDR+0x060 +`define REG_TIM1_CH2_LUT 8'b00011001 //BASEADDR+0x064 +`define REG_TIM1_CH3_LUT 8'b00011010 //BASEADDR+0x068 + +`define REG_TIM1_COUNTER 8'b00011011 //BASEADDR+0x06C + +////////////////////////////////////////////////////////// +//// +//// TIMER 2 CONFIG +//// +////////////////////////////////////////////////////////// +`define REG_TIM2_CMD 8'b00100000 //BASEADDR+0x080 +`define REG_TIM2_CFG 8'b00100001 //BASEADDR+0x084 + +`define REG_TIM2_TH 8'b00100010 //BASEADDR+0x088 + +`define REG_TIM2_CH0_TH 8'b00100011 //BASEADDR+0x08C +`define REG_TIM2_CH1_TH 8'b00100100 //BASEADDR+0x090 +`define REG_TIM2_CH2_TH 8'b00100101 //BASEADDR+0x094 +`define REG_TIM2_CH3_TH 8'b00100110 //BASEADDR+0x098 + +`define REG_TIM2_CH0_LUT 8'b00100111 //BASEADDR+0x09C +`define REG_TIM2_CH1_LUT 8'b00101000 //BASEADDR+0x0A0 +`define REG_TIM2_CH2_LUT 8'b00101001 //BASEADDR+0x0A4 +`define REG_TIM2_CH3_LUT 8'b00101010 //BASEADDR+0x0A8 + +`define REG_TIM2_COUNTER 8'b00101011 //BASEADDR+0x0AC + +////////////////////////////////////////////////////////// +//// +//// TIMER 3 CONFIG +//// +////////////////////////////////////////////////////////// +`define REG_TIM3_CMD 8'b00110000 //BASEADDR+0x0C0 +`define REG_TIM3_CFG 8'b00110001 //BASEADDR+0x0C4 + +`define REG_TIM3_TH 8'b00110010 //BASEADDR+0x0C8 + +`define REG_TIM3_CH0_TH 8'b00110011 //BASEADDR+0x0CC +`define REG_TIM3_CH1_TH 8'b00110100 //BASEADDR+0x0D0 +`define REG_TIM3_CH2_TH 8'b00110101 //BASEADDR+0x0D4 +`define REG_TIM3_CH3_TH 8'b00110110 //BASEADDR+0x0D8 + +`define REG_TIM3_CH0_LUT 8'b00110111 //BASEADDR+0x0DC +`define REG_TIM3_CH1_LUT 8'b00111000 //BASEADDR+0x0E0 +`define REG_TIM3_CH2_LUT 8'b00111001 //BASEADDR+0x0E4 +`define REG_TIM3_CH3_LUT 8'b00111010 //BASEADDR+0x0E8 + +`define REG_TIM3_COUNTER 8'b00111011 //BASEADDR+0x0EC + +`define REG_EVENT_CFG 8'b01000000 //BASEADDR+0x100 +`define REG_CH_EN 8'b01000001 //BASEADDR+0x104 + +module adv_timer_apb_if #( + parameter APB_ADDR_WIDTH = 12 +) ( + input wire HCLK, + input wire HRESETn, + input wire [APB_ADDR_WIDTH - 1:0] PADDR, + input wire [31:0] PWDATA, + input wire PWRITE, + input wire PSEL, + input wire PENABLE, + output reg [31:0] PRDATA, + output wire PREADY, + output wire PSLVERR, + output wire [3:0] events_en_o, + output wire [3:0] events_sel_0_o, + output wire [3:0] events_sel_1_o, + output wire [3:0] events_sel_2_o, + output wire [3:0] events_sel_3_o, + input wire [15:0] timer0_counter_i, + input wire [15:0] timer1_counter_i, + input wire [15:0] timer2_counter_i, + input wire [15:0] timer3_counter_i, + output wire timer0_start_o, + output wire timer0_stop_o, + output wire timer0_update_o, + output wire timer0_arm_o, + output wire timer0_rst_o, + output wire timer0_saw_o, + output wire [2:0] timer0_in_mode_o, + output wire [7:0] timer0_in_sel_o, + output wire timer0_in_clk_o, + output wire [7:0] timer0_presc_o, + output wire [15:0] timer0_th_hi_o, + output wire [15:0] timer0_th_low_o, + output wire [2:0] timer0_ch0_mode_o, + output wire [1:0] timer0_ch0_flt_o, + output wire [15:0] timer0_ch0_th_o, + output wire [15:0] timer0_ch0_lut_o, + output wire [2:0] timer0_ch1_mode_o, + output wire [1:0] timer0_ch1_flt_o, + output wire [15:0] timer0_ch1_th_o, + output wire [15:0] timer0_ch1_lut_o, + output wire [2:0] timer0_ch2_mode_o, + output wire [1:0] timer0_ch2_flt_o, + output wire [15:0] timer0_ch2_th_o, + output wire [15:0] timer0_ch2_lut_o, + output wire [2:0] timer0_ch3_mode_o, + output wire [1:0] timer0_ch3_flt_o, + output wire [15:0] timer0_ch3_th_o, + output wire [15:0] timer0_ch3_lut_o, + output wire timer1_start_o, + output wire timer1_stop_o, + output wire timer1_update_o, + output wire timer1_arm_o, + output wire timer1_rst_o, + output wire timer1_saw_o, + output wire [2:0] timer1_in_mode_o, + output wire [7:0] timer1_in_sel_o, + output wire timer1_in_clk_o, + output wire [7:0] timer1_presc_o, + output wire [15:0] timer1_th_hi_o, + output wire [15:0] timer1_th_low_o, + output wire [2:0] timer1_ch0_mode_o, + output wire [1:0] timer1_ch0_flt_o, + output wire [15:0] timer1_ch0_th_o, + output wire [15:0] timer1_ch0_lut_o, + output wire [2:0] timer1_ch1_mode_o, + output wire [1:0] timer1_ch1_flt_o, + output wire [15:0] timer1_ch1_th_o, + output wire [15:0] timer1_ch1_lut_o, + output wire [2:0] timer1_ch2_mode_o, + output wire [1:0] timer1_ch2_flt_o, + output wire [15:0] timer1_ch2_th_o, + output wire [15:0] timer1_ch2_lut_o, + output wire [2:0] timer1_ch3_mode_o, + output wire [1:0] timer1_ch3_flt_o, + output wire [15:0] timer1_ch3_th_o, + output wire [15:0] timer1_ch3_lut_o, + output wire timer2_start_o, + output wire timer2_stop_o, + output wire timer2_update_o, + output wire timer2_arm_o, + output wire timer2_rst_o, + output wire timer2_saw_o, + output wire [2:0] timer2_in_mode_o, + output wire [7:0] timer2_in_sel_o, + output wire timer2_in_clk_o, + output wire [7:0] timer2_presc_o, + output wire [15:0] timer2_th_hi_o, + output wire [15:0] timer2_th_low_o, + output wire [2:0] timer2_ch0_mode_o, + output wire [1:0] timer2_ch0_flt_o, + output wire [15:0] timer2_ch0_th_o, + output wire [15:0] timer2_ch0_lut_o, + output wire [2:0] timer2_ch1_mode_o, + output wire [1:0] timer2_ch1_flt_o, + output wire [15:0] timer2_ch1_th_o, + output wire [15:0] timer2_ch1_lut_o, + output wire [2:0] timer2_ch2_mode_o, + output wire [1:0] timer2_ch2_flt_o, + output wire [15:0] timer2_ch2_th_o, + output wire [15:0] timer2_ch2_lut_o, + output wire [2:0] timer2_ch3_mode_o, + output wire [1:0] timer2_ch3_flt_o, + output wire [15:0] timer2_ch3_th_o, + output wire [15:0] timer2_ch3_lut_o, + output wire timer3_start_o, + output wire timer3_stop_o, + output wire timer3_update_o, + output wire timer3_arm_o, + output wire timer3_rst_o, + output wire timer3_saw_o, + output wire [2:0] timer3_in_mode_o, + output wire [7:0] timer3_in_sel_o, + output wire timer3_in_clk_o, + output wire [7:0] timer3_presc_o, + output wire [15:0] timer3_th_hi_o, + output wire [15:0] timer3_th_low_o, + output wire [2:0] timer3_ch0_mode_o, + output wire [1:0] timer3_ch0_flt_o, + output wire [15:0] timer3_ch0_th_o, + output wire [15:0] timer3_ch0_lut_o, + output wire [2:0] timer3_ch1_mode_o, + output wire [1:0] timer3_ch1_flt_o, + output wire [15:0] timer3_ch1_th_o, + output wire [15:0] timer3_ch1_lut_o, + output wire [2:0] timer3_ch2_mode_o, + output wire [1:0] timer3_ch2_flt_o, + output wire [15:0] timer3_ch2_th_o, + output wire [15:0] timer3_ch2_lut_o, + output wire [2:0] timer3_ch3_mode_o, + output wire [1:0] timer3_ch3_flt_o, + output wire [15:0] timer3_ch3_th_o, + output wire [15:0] timer3_ch3_lut_o, + output wire timer0_clk_en_o, + output wire timer1_clk_en_o, + output wire timer2_clk_en_o, + output wire timer3_clk_en_o +); + + wire s_timer1_apb_in_clk; + wire s_timer2_apb_in_clk; + wire s_timer3_apb_in_clk; + wire s_timer1_apb_start; + wire s_timer1_apb_stop; + wire s_timer2_apb_start; + wire s_timer2_apb_stop; + wire s_timer3_apb_start; + wire s_timer3_apb_stop; + + reg [31:0] r_timer0_th; + reg [7:0] r_timer0_presc; + reg [7:0] r_timer0_in_sel; + reg r_timer0_in_clk; + reg [2:0] r_timer0_in_mode; + reg r_timer0_start; + reg r_timer0_stop; + reg r_timer0_update; + reg r_timer0_arm; + reg r_timer0_rst; + reg r_timer0_saw; + reg [15:0] r_timer0_ch0_th; + reg [2:0] r_timer0_ch0_mode; + reg [15:0] r_timer0_ch0_lut; + reg [1:0] r_timer0_ch0_flt; + reg [15:0] r_timer0_ch1_th; + reg [2:0] r_timer0_ch1_mode; + reg [15:0] r_timer0_ch1_lut; + reg [1:0] r_timer0_ch1_flt; + reg [15:0] r_timer0_ch2_th; + reg [2:0] r_timer0_ch2_mode; + reg [15:0] r_timer0_ch2_lut; + reg [1:0] r_timer0_ch2_flt; + reg [15:0] r_timer0_ch3_th; + reg [2:0] r_timer0_ch3_mode; + reg [15:0] r_timer0_ch3_lut; + reg [1:0] r_timer0_ch3_flt; + + reg [31:0] r_timer1_th; + reg [7:0] r_timer1_presc; + reg [7:0] r_timer1_in_sel; + reg r_timer1_in_clk; + reg [2:0] r_timer1_in_mode; + reg r_timer1_start; + reg r_timer1_stop; + reg r_timer1_update; + reg r_timer1_arm; + reg r_timer1_rst; + reg r_timer1_saw; + reg [15:0] r_timer1_ch0_th; + reg [2:0] r_timer1_ch0_mode; + reg [15:0] r_timer1_ch0_lut; + reg [1:0] r_timer1_ch0_flt; + reg [15:0] r_timer1_ch1_th; + reg [2:0] r_timer1_ch1_mode; + reg [15:0] r_timer1_ch1_lut; + reg [1:0] r_timer1_ch1_flt; + reg [15:0] r_timer1_ch2_th; + reg [2:0] r_timer1_ch2_mode; + reg [15:0] r_timer1_ch2_lut; + reg [1:0] r_timer1_ch2_flt; + reg [15:0] r_timer1_ch3_th; + reg [2:0] r_timer1_ch3_mode; + reg [15:0] r_timer1_ch3_lut; + reg [1:0] r_timer1_ch3_flt; + + reg [31:0] r_timer2_th; + reg [7:0] r_timer2_presc; + reg [7:0] r_timer2_in_sel; + reg r_timer2_in_clk; + reg [2:0] r_timer2_in_mode; + reg r_timer2_start; + reg r_timer2_stop; + reg r_timer2_update; + reg r_timer2_arm; + reg r_timer2_rst; + reg r_timer2_saw; + reg [15:0] r_timer2_ch0_th; + reg [2:0] r_timer2_ch0_mode; + reg [15:0] r_timer2_ch0_lut; + reg [1:0] r_timer2_ch0_flt; + reg [15:0] r_timer2_ch1_th; + reg [2:0] r_timer2_ch1_mode; + reg [15:0] r_timer2_ch1_lut; + reg [1:0] r_timer2_ch1_flt; + reg [15:0] r_timer2_ch2_th; + reg [2:0] r_timer2_ch2_mode; + reg [15:0] r_timer2_ch2_lut; + reg [1:0] r_timer2_ch2_flt; + reg [15:0] r_timer2_ch3_th; + reg [2:0] r_timer2_ch3_mode; + reg [15:0] r_timer2_ch3_lut; + reg [1:0] r_timer2_ch3_flt; + + reg [31:0] r_timer3_th; + reg [7:0] r_timer3_presc; + reg [7:0] r_timer3_in_sel; + reg r_timer3_in_clk; + reg [2:0] r_timer3_in_mode; + reg r_timer3_start; + reg r_timer3_stop; + reg r_timer3_update; + reg r_timer3_arm; + reg r_timer3_rst; + reg r_timer3_saw; + reg [15:0] r_timer3_ch0_th; + reg [2:0] r_timer3_ch0_mode; + reg [15:0] r_timer3_ch0_lut; + reg [1:0] r_timer3_ch0_flt; + reg [15:0] r_timer3_ch1_th; + reg [2:0] r_timer3_ch1_mode; + reg [15:0] r_timer3_ch1_lut; + reg [1:0] r_timer3_ch1_flt; + reg [15:0] r_timer3_ch2_th; + reg [2:0] r_timer3_ch2_mode; + reg [15:0] r_timer3_ch2_lut; + reg [1:0] r_timer3_ch2_flt; + reg [15:0] r_timer3_ch3_th; + reg [2:0] r_timer3_ch3_mode; + reg [15:0] r_timer3_ch3_lut; + reg [1:0] r_timer3_ch3_flt; + + reg [3:0] r_event_sel_0; + reg [3:0] r_event_sel_1; + reg [3:0] r_event_sel_2; + reg [3:0] r_event_sel_3; + reg [3:0] r_event_en; + + reg [3:0] r_clk_en; + wire [7:0] s_apb_addr; + + assign events_en_o = r_event_en; + assign events_sel_0_o = r_event_sel_0; + assign events_sel_1_o = r_event_sel_1; + assign events_sel_2_o = r_event_sel_2; + assign events_sel_3_o = r_event_sel_3; + + assign timer0_start_o = r_timer0_start; + assign timer0_stop_o = r_timer0_stop; + assign timer0_update_o = r_timer0_update; + assign timer0_rst_o = r_timer0_rst; + assign timer0_arm_o = r_timer0_arm; + assign timer0_saw_o = r_timer0_saw; + assign timer0_in_mode_o = r_timer0_in_mode; + assign timer0_in_sel_o = r_timer0_in_sel; + assign timer0_in_clk_o = r_timer0_in_clk; + assign timer0_presc_o = r_timer0_presc; + assign timer0_th_hi_o = r_timer0_th[31:16]; + assign timer0_th_low_o = r_timer0_th[15:0]; + assign timer0_ch0_mode_o = r_timer0_ch0_mode; + assign timer0_ch0_flt_o = r_timer0_ch0_flt; + assign timer0_ch0_th_o = r_timer0_ch0_th; + assign timer0_ch0_lut_o = r_timer0_ch0_lut; + assign timer0_ch1_mode_o = r_timer0_ch1_mode; + assign timer0_ch1_flt_o = r_timer0_ch1_flt; + assign timer0_ch1_th_o = r_timer0_ch1_th; + assign timer0_ch1_lut_o = r_timer0_ch1_lut; + assign timer0_ch2_mode_o = r_timer0_ch2_mode; + assign timer0_ch2_flt_o = r_timer0_ch2_flt; + assign timer0_ch2_th_o = r_timer0_ch2_th; + assign timer0_ch2_lut_o = r_timer0_ch2_lut; + assign timer0_ch3_mode_o = r_timer0_ch3_mode; + assign timer0_ch3_flt_o = r_timer0_ch3_flt; + assign timer0_ch3_th_o = r_timer0_ch3_th; + assign timer0_ch3_lut_o = r_timer0_ch3_lut; + + assign timer1_start_o = r_timer1_start; + assign timer1_stop_o = r_timer1_stop; + assign timer1_update_o = r_timer1_update; + assign timer1_rst_o = r_timer1_rst; + assign timer1_arm_o = r_timer1_arm; + assign timer1_saw_o = r_timer1_saw; + assign timer1_in_mode_o = r_timer1_in_mode; + assign timer1_in_sel_o = r_timer1_in_sel; + assign timer1_in_clk_o = r_timer1_in_clk; + assign timer1_presc_o = r_timer1_presc; + assign timer1_th_hi_o = r_timer1_th[31:16]; + assign timer1_th_low_o = r_timer1_th[15:0]; + assign timer1_ch0_mode_o = r_timer1_ch0_mode; + assign timer1_ch0_flt_o = r_timer1_ch0_flt; + assign timer1_ch0_th_o = r_timer1_ch0_th; + assign timer1_ch0_lut_o = r_timer1_ch0_lut; + assign timer1_ch1_mode_o = r_timer1_ch1_mode; + assign timer1_ch1_flt_o = r_timer1_ch1_flt; + assign timer1_ch1_th_o = r_timer1_ch1_th; + assign timer1_ch1_lut_o = r_timer1_ch1_lut; + assign timer1_ch2_mode_o = r_timer1_ch2_mode; + assign timer1_ch2_flt_o = r_timer1_ch2_flt; + assign timer1_ch2_th_o = r_timer1_ch2_th; + assign timer1_ch2_lut_o = r_timer1_ch2_lut; + assign timer1_ch3_mode_o = r_timer1_ch3_mode; + assign timer1_ch3_flt_o = r_timer1_ch3_flt; + assign timer1_ch3_th_o = r_timer1_ch3_th; + assign timer1_ch3_lut_o = r_timer1_ch3_lut; + + assign timer2_start_o = r_timer2_start; + assign timer2_stop_o = r_timer2_stop; + assign timer2_update_o = r_timer2_update; + assign timer2_rst_o = r_timer2_rst; + assign timer2_arm_o = r_timer2_arm; + assign timer2_saw_o = r_timer2_saw; + assign timer2_in_mode_o = r_timer2_in_mode; + assign timer2_in_sel_o = r_timer2_in_sel; + assign timer2_in_clk_o = r_timer2_in_clk; + assign timer2_presc_o = r_timer2_presc; + assign timer2_th_hi_o = r_timer2_th[31:16]; + assign timer2_th_low_o = r_timer2_th[15:0]; + assign timer2_ch0_mode_o = r_timer2_ch0_mode; + assign timer2_ch0_flt_o = r_timer2_ch0_flt; + assign timer2_ch0_th_o = r_timer2_ch0_th; + assign timer2_ch0_lut_o = r_timer2_ch0_lut; + assign timer2_ch1_mode_o = r_timer2_ch1_mode; + assign timer2_ch1_flt_o = r_timer2_ch1_flt; + assign timer2_ch1_th_o = r_timer2_ch1_th; + assign timer2_ch1_lut_o = r_timer2_ch1_lut; + assign timer2_ch2_mode_o = r_timer2_ch2_mode; + assign timer2_ch2_flt_o = r_timer2_ch2_flt; + assign timer2_ch2_th_o = r_timer2_ch2_th; + assign timer2_ch2_lut_o = r_timer2_ch2_lut; + assign timer2_ch3_mode_o = r_timer2_ch3_mode; + assign timer2_ch3_flt_o = r_timer2_ch3_flt; + assign timer2_ch3_th_o = r_timer2_ch3_th; + assign timer2_ch3_lut_o = r_timer2_ch3_lut; + + assign timer3_start_o = r_timer3_start; + assign timer3_stop_o = r_timer3_stop; + assign timer3_update_o = r_timer3_update; + assign timer3_rst_o = r_timer3_rst; + assign timer3_arm_o = r_timer3_arm; + assign timer3_saw_o = r_timer3_saw; + assign timer3_in_mode_o = r_timer3_in_mode; + assign timer3_in_sel_o = r_timer3_in_sel; + assign timer3_in_clk_o = r_timer3_in_clk; + assign timer3_presc_o = r_timer3_presc; + assign timer3_th_hi_o = r_timer3_th[31:16]; + assign timer3_th_low_o = r_timer3_th[15:0]; + assign timer3_ch0_mode_o = r_timer3_ch0_mode; + assign timer3_ch0_flt_o = r_timer3_ch0_flt; + assign timer3_ch0_th_o = r_timer3_ch0_th; + assign timer3_ch0_lut_o = r_timer3_ch0_lut; + assign timer3_ch1_mode_o = r_timer3_ch1_mode; + assign timer3_ch1_flt_o = r_timer3_ch1_flt; + assign timer3_ch1_th_o = r_timer3_ch1_th; + assign timer3_ch1_lut_o = r_timer3_ch1_lut; + assign timer3_ch2_mode_o = r_timer3_ch2_mode; + assign timer3_ch2_flt_o = r_timer3_ch2_flt; + assign timer3_ch2_th_o = r_timer3_ch2_th; + assign timer3_ch2_lut_o = r_timer3_ch2_lut; + assign timer3_ch3_mode_o = r_timer3_ch3_mode; + assign timer3_ch3_flt_o = r_timer3_ch3_flt; + assign timer3_ch3_th_o = r_timer3_ch3_th; + assign timer3_ch3_lut_o = r_timer3_ch3_lut; + + assign timer0_clk_en_o = r_clk_en[0]; + assign timer1_clk_en_o = r_clk_en[1]; + assign timer2_clk_en_o = r_clk_en[2]; + assign timer3_clk_en_o = r_clk_en[3]; + + assign s_apb_addr = PADDR[9:2]; + + always @(posedge HCLK or negedge HRESETn) begin + if (~HRESETn) begin + r_timer0_th <= 'h0; + r_timer0_in_sel <= 'h0; + r_timer0_in_clk <= 'h0; + r_timer0_in_mode <= 'h0; + r_timer0_presc <= 'h0; + r_timer0_start <= 1'b0; + r_timer0_stop <= 1'b0; + r_timer0_update <= 1'b0; + r_timer0_arm <= 1'b0; + r_timer0_rst <= 1'b0; + r_timer0_saw <= 1'b1; + r_timer0_ch0_th <= 'h0; + r_timer0_ch0_mode <= 'h0; + r_timer0_ch0_lut <= 'h0; + r_timer0_ch0_flt <= 'h0; + r_timer0_ch1_th <= 'h0; + r_timer0_ch1_mode <= 'h0; + r_timer0_ch1_lut <= 'h0; + r_timer0_ch1_flt <= 'h0; + r_timer0_ch2_th <= 'h0; + r_timer0_ch2_mode <= 'h0; + r_timer0_ch2_lut <= 'h0; + r_timer0_ch2_flt <= 'h0; + r_timer0_ch3_th <= 'h0; + r_timer0_ch3_mode <= 'h0; + r_timer0_ch3_lut <= 'h0; + r_timer0_ch3_flt <= 'h0; + + r_timer1_th <= 'h0; + r_timer1_in_sel <= 'h0; + r_timer1_in_clk <= 'h0; + r_timer1_in_mode <= 'h0; + r_timer1_presc <= 'h0; + r_timer1_start <= 1'b0; + r_timer1_stop <= 1'b0; + r_timer1_update <= 1'b0; + r_timer1_rst <= 1'b0; + r_timer1_arm <= 1'b0; + r_timer1_saw <= 1'b1; + r_timer1_ch0_th <= 'h0; + r_timer1_ch0_mode <= 'h0; + r_timer1_ch0_lut <= 'h0; + r_timer1_ch0_flt <= 'h0; + r_timer1_ch1_th <= 'h0; + r_timer1_ch1_mode <= 'h0; + r_timer1_ch1_lut <= 'h0; + r_timer1_ch1_flt <= 'h0; + r_timer1_ch2_th <= 'h0; + r_timer1_ch2_mode <= 'h0; + r_timer1_ch2_lut <= 'h0; + r_timer1_ch2_flt <= 'h0; + r_timer1_ch3_th <= 'h0; + r_timer1_ch3_mode <= 'h0; + r_timer1_ch3_lut <= 'h0; + r_timer1_ch3_flt <= 'h0; + + r_timer2_th <= 'h0; + r_timer2_in_sel <= 'h0; + r_timer2_in_clk <= 'h0; + r_timer2_in_mode <= 'h0; + r_timer2_presc <= 'h0; + r_timer2_start <= 1'b0; + r_timer2_stop <= 1'b0; + r_timer2_update <= 1'b0; + r_timer2_rst <= 1'b0; + r_timer2_arm <= 1'b0; + r_timer2_saw <= 1'b1; + r_timer2_ch0_th <= 'h0; + r_timer2_ch0_mode <= 'h0; + r_timer2_ch0_lut <= 'h0; + r_timer2_ch0_flt <= 'h0; + r_timer2_ch1_th <= 'h0; + r_timer2_ch1_mode <= 'h0; + r_timer2_ch1_lut <= 'h0; + r_timer2_ch1_flt <= 'h0; + r_timer2_ch2_th <= 'h0; + r_timer2_ch2_mode <= 'h0; + r_timer2_ch2_lut <= 'h0; + r_timer2_ch2_flt <= 'h0; + r_timer2_ch3_th <= 'h0; + r_timer2_ch3_mode <= 'h0; + r_timer2_ch3_lut <= 'h0; + r_timer2_ch3_flt <= 'h0; + + r_timer3_th <= 'h0; + r_timer3_in_sel <= 'h0; + r_timer3_in_clk <= 'h0; + r_timer3_in_mode <= 'h0; + r_timer3_presc <= 'h0; + r_timer3_start <= 1'b0; + r_timer3_stop <= 1'b0; + r_timer3_update <= 1'b0; + r_timer3_rst <= 1'b0; + r_timer3_arm <= 1'b0; + r_timer3_saw <= 1'b1; + r_timer3_ch0_th <= 'h0; + r_timer3_ch0_mode <= 'h0; + r_timer3_ch0_lut <= 'h0; + r_timer3_ch0_flt <= 'h0; + r_timer3_ch1_th <= 'h0; + r_timer3_ch1_mode <= 'h0; + r_timer3_ch1_lut <= 'h0; + r_timer3_ch1_flt <= 'h0; + r_timer3_ch2_th <= 'h0; + r_timer3_ch2_mode <= 'h0; + r_timer3_ch2_lut <= 'h0; + r_timer3_ch2_flt <= 'h0; + r_timer3_ch3_th <= 'h0; + r_timer3_ch3_mode <= 'h0; + r_timer3_ch3_lut <= 'h0; + r_timer3_ch3_flt <= 'h0; + + r_event_sel_0 <= 'h0; + r_event_sel_1 <= 'h0; + r_event_sel_2 <= 'h0; + r_event_sel_3 <= 'h0; + r_event_en <= 'h0; + + r_clk_en <= 'h0; + + end else if ((PSEL && PENABLE) && PWRITE) begin + case (s_apb_addr) + `REG_TIM0_TH: + r_timer0_th <= PWDATA; + `REG_TIM0_CMD: + begin + r_timer0_start <= PWDATA[0]; + r_timer0_stop <= PWDATA[1]; + r_timer0_update <= PWDATA[2]; + r_timer0_rst <= PWDATA[3]; + r_timer0_arm <= PWDATA[4]; + end + `REG_TIM0_CFG: + begin + r_timer0_in_sel <= PWDATA[7:0]; + r_timer0_in_mode<= PWDATA[10:8]; + r_timer0_in_clk <= PWDATA[11]; + r_timer0_saw <= PWDATA[12]; + r_timer0_presc <= PWDATA[23:16]; + end + `REG_TIM0_CH0_TH: + begin + r_timer0_ch0_th <= PWDATA[15:0]; + r_timer0_ch0_mode <= PWDATA[18:16]; + end + `REG_TIM0_CH0_LUT: + begin + r_timer0_ch0_lut <= PWDATA[15:0]; + r_timer0_ch0_flt <= PWDATA[17:16]; + end + `REG_TIM0_CH1_TH: + begin + r_timer0_ch1_th <= PWDATA[15:0]; + r_timer0_ch1_mode <= PWDATA[18:16]; + end + `REG_TIM0_CH1_LUT: + begin + r_timer0_ch1_lut <= PWDATA[15:0]; + r_timer0_ch1_flt <= PWDATA[17:16]; + end + `REG_TIM0_CH2_TH: + begin + r_timer0_ch2_th <= PWDATA[15:0]; + r_timer0_ch2_mode <= PWDATA[18:16]; + end + `REG_TIM0_CH2_LUT: + begin + r_timer0_ch2_lut <= PWDATA[15:0]; + r_timer0_ch2_flt <= PWDATA[17:16]; + end + `REG_TIM0_CH3_TH: + begin + r_timer0_ch3_th <= PWDATA[15:0]; + r_timer0_ch3_mode <= PWDATA[18:16]; + end + `REG_TIM0_CH3_LUT: + begin + r_timer0_ch3_lut <= PWDATA[15:0]; + r_timer0_ch3_flt <= PWDATA[17:16]; + end + `REG_TIM1_TH: + r_timer1_th <= PWDATA; + `REG_TIM1_CMD: + begin + r_timer1_start <= PWDATA[0]; + r_timer1_stop <= PWDATA[1]; + r_timer1_update <= PWDATA[2]; + r_timer1_rst <= PWDATA[3]; + r_timer1_arm <= PWDATA[4]; + end + `REG_TIM1_CFG: + begin + r_timer1_in_sel <= PWDATA[7:0]; + r_timer1_in_mode<= PWDATA[10:8]; + r_timer1_in_clk <= PWDATA[11]; + r_timer1_saw <= PWDATA[12]; + r_timer1_presc <= PWDATA[23:16]; + end + `REG_TIM1_CH0_TH: + begin + r_timer1_ch0_th <= PWDATA[15:0]; + r_timer1_ch0_mode <= PWDATA[18:16]; + end + `REG_TIM1_CH0_LUT: + begin + r_timer1_ch0_lut <= PWDATA[15:0]; + r_timer1_ch0_flt <= PWDATA[17:16]; + end + `REG_TIM1_CH1_TH: + begin + r_timer1_ch1_th <= PWDATA[15:0]; + r_timer1_ch1_mode <= PWDATA[18:16]; + end + `REG_TIM1_CH1_LUT: + begin + r_timer1_ch1_lut <= PWDATA[15:0]; + r_timer1_ch1_flt <= PWDATA[17:16]; + end + `REG_TIM1_CH2_TH: + begin + r_timer1_ch2_th <= PWDATA[15:0]; + r_timer1_ch2_mode <= PWDATA[18:16]; + end + `REG_TIM1_CH2_LUT: + begin + r_timer1_ch2_lut <= PWDATA[15:0]; + r_timer1_ch2_flt <= PWDATA[17:16]; + end + `REG_TIM1_CH3_TH: + begin + r_timer1_ch3_th <= PWDATA[15:0]; + r_timer1_ch3_mode <= PWDATA[18:16]; + end + `REG_TIM1_CH3_LUT: + begin + r_timer1_ch3_lut <= PWDATA[15:0]; + r_timer1_ch3_flt <= PWDATA[17:16]; + end + `REG_TIM2_TH: + r_timer2_th <= PWDATA; + `REG_TIM2_CMD: + begin + r_timer2_start <= PWDATA[0]; + r_timer2_stop <= PWDATA[1]; + r_timer2_update <= PWDATA[2]; + r_timer2_rst <= PWDATA[3]; + r_timer2_arm <= PWDATA[4]; + end + `REG_TIM2_CFG: + begin + r_timer2_in_sel <= PWDATA[7:0]; + r_timer2_in_mode<= PWDATA[10:8]; + r_timer2_in_clk <= PWDATA[11]; + r_timer2_saw <= PWDATA[12]; + r_timer2_presc <= PWDATA[23:16]; + end + `REG_TIM2_CH0_TH: + begin + r_timer2_ch0_th <= PWDATA[15:0]; + r_timer2_ch0_mode <= PWDATA[18:16]; + end + `REG_TIM2_CH0_LUT: + begin + r_timer2_ch0_lut <= PWDATA[15:0]; + r_timer2_ch0_flt <= PWDATA[17:16]; + end + `REG_TIM2_CH1_TH: + begin + r_timer2_ch1_th <= PWDATA[15:0]; + r_timer2_ch1_mode <= PWDATA[18:16]; + end + `REG_TIM2_CH1_LUT: + begin + r_timer2_ch1_lut <= PWDATA[15:0]; + r_timer2_ch1_flt <= PWDATA[17:16]; + end + `REG_TIM2_CH2_TH: + begin + r_timer2_ch2_th <= PWDATA[15:0]; + r_timer2_ch2_mode <= PWDATA[18:16]; + end + `REG_TIM2_CH2_LUT: + begin + r_timer2_ch2_lut <= PWDATA[15:0]; + r_timer2_ch2_flt <= PWDATA[17:16]; + end + `REG_TIM2_CH3_TH: + begin + r_timer2_ch3_th <= PWDATA[15:0]; + r_timer2_ch3_mode <= PWDATA[18:16]; + end + `REG_TIM2_CH3_LUT: + begin + r_timer2_ch3_lut <= PWDATA[15:0]; + r_timer2_ch3_flt <= PWDATA[17:16]; + end + `REG_TIM3_TH: + r_timer3_th <= PWDATA; + `REG_TIM3_CMD: + begin + r_timer3_start <= PWDATA[0]; + r_timer3_stop <= PWDATA[1]; + r_timer3_update <= PWDATA[2]; + r_timer3_rst <= PWDATA[3]; + r_timer3_arm <= PWDATA[4]; + end + `REG_TIM3_CFG: + begin + r_timer3_in_sel <= PWDATA[7:0]; + r_timer3_in_mode<= PWDATA[10:8]; + r_timer3_in_clk <= PWDATA[11]; + r_timer3_saw <= PWDATA[12]; + r_timer3_presc <= PWDATA[23:16]; + end + `REG_TIM3_CH0_TH: + begin + r_timer3_ch0_th <= PWDATA[15:0]; + r_timer3_ch0_mode <= PWDATA[18:16]; + end + `REG_TIM3_CH0_LUT: + begin + r_timer3_ch0_lut <= PWDATA[15:0]; + r_timer3_ch0_flt <= PWDATA[17:16]; + end + `REG_TIM3_CH1_TH: + begin + r_timer3_ch1_th <= PWDATA[15:0]; + r_timer3_ch1_mode <= PWDATA[18:16]; + end + `REG_TIM3_CH1_LUT: + begin + r_timer3_ch1_lut <= PWDATA[15:0]; + r_timer3_ch1_flt <= PWDATA[17:16]; + end + `REG_TIM3_CH2_TH: + begin + r_timer3_ch2_th <= PWDATA[15:0]; + r_timer3_ch2_mode <= PWDATA[18:16]; + end + `REG_TIM3_CH2_LUT: + begin + r_timer3_ch2_lut <= PWDATA[15:0]; + r_timer3_ch2_flt <= PWDATA[17:16]; + end + `REG_TIM3_CH3_TH: + begin + r_timer3_ch3_th <= PWDATA[15:0]; + r_timer3_ch3_mode <= PWDATA[18:16]; + end + `REG_TIM3_CH3_LUT: + begin + r_timer3_ch3_lut <= PWDATA[15:0]; + r_timer3_ch3_flt <= PWDATA[17:16]; + end + `REG_EVENT_CFG: + begin + r_event_sel_0 <= PWDATA[3:0]; + r_event_sel_1 <= PWDATA[7:4]; + r_event_sel_2 <= PWDATA[11:8]; + r_event_sel_3 <= PWDATA[15:12]; + r_event_en <= PWDATA[19:16]; + end + `REG_CH_EN: + begin + r_clk_en <= PWDATA[3:0]; + end + endcase // s_apb_addr + end else begin + r_timer0_start <= 1'b0; + r_timer0_stop <= 1'b0; + r_timer0_rst <= 1'b0; + r_timer0_update <= 1'b0; + r_timer0_arm <= 1'b0; + r_timer1_start <= 1'b0; + r_timer1_stop <= 1'b0; + r_timer1_rst <= 1'b0; + r_timer1_update <= 1'b0; + r_timer1_arm <= 1'b0; + r_timer2_start <= 1'b0; + r_timer2_stop <= 1'b0; + r_timer2_rst <= 1'b0; + r_timer2_update <= 1'b0; + r_timer2_arm <= 1'b0; + r_timer3_start <= 1'b0; + r_timer3_stop <= 1'b0; + r_timer3_rst <= 1'b0; + r_timer3_update <= 1'b0; + r_timer3_arm <= 1'b0; + end + end + + always @(*) begin + case (s_apb_addr) + `REG_TIM0_TH: + PRDATA = r_timer0_th; + `REG_TIM1_TH: + PRDATA = r_timer1_th; + `REG_TIM2_TH: + PRDATA = r_timer2_th; + `REG_TIM3_TH: + PRDATA = r_timer3_th; + `REG_TIM0_CFG: + PRDATA = {8'h0,r_timer0_presc,3'h0,r_timer0_saw,r_timer0_in_clk,r_timer0_in_mode,r_timer0_in_sel}; + `REG_TIM0_CH0_TH: + PRDATA = {13'h0,r_timer0_ch0_mode,r_timer0_ch0_th}; + `REG_TIM0_CH0_LUT: + PRDATA = {14'h0,r_timer0_ch0_flt,r_timer0_ch0_lut}; + `REG_TIM0_CH1_TH: + PRDATA = {13'h0,r_timer0_ch1_mode,r_timer0_ch1_th}; + `REG_TIM0_CH1_LUT: + PRDATA = {14'h0,r_timer0_ch1_flt,r_timer0_ch1_lut}; + `REG_TIM0_CH2_TH: + PRDATA = {13'h0,r_timer0_ch2_mode,r_timer0_ch2_th}; + `REG_TIM0_CH2_LUT: + PRDATA = {14'h0,r_timer0_ch2_flt,r_timer0_ch2_lut}; + `REG_TIM0_CH3_TH: + PRDATA = {13'h0,r_timer0_ch3_mode,r_timer0_ch3_th}; + `REG_TIM0_CH3_LUT: + PRDATA = {14'h0,r_timer0_ch3_flt,r_timer0_ch3_lut}; + `REG_TIM1_CFG: + PRDATA = {8'h0,r_timer1_presc,3'h0,r_timer1_saw,r_timer1_in_clk,r_timer1_in_mode,r_timer1_in_sel}; + `REG_TIM1_CH0_TH: + PRDATA = {13'h0,r_timer1_ch0_mode,r_timer1_ch0_th}; + `REG_TIM1_CH0_LUT: + PRDATA = {14'h0,r_timer1_ch0_flt,r_timer1_ch0_lut}; + `REG_TIM1_CH1_TH: + PRDATA = {13'h0,r_timer1_ch1_mode,r_timer1_ch1_th}; + `REG_TIM1_CH1_LUT: + PRDATA = {14'h0,r_timer1_ch1_flt,r_timer1_ch1_lut}; + `REG_TIM1_CH2_TH: + PRDATA = {13'h0,r_timer1_ch2_mode,r_timer1_ch2_th}; + `REG_TIM1_CH2_LUT: + PRDATA = {14'h0,r_timer1_ch2_flt,r_timer1_ch2_lut}; + `REG_TIM1_CH3_TH: + PRDATA = {13'h0,r_timer1_ch3_mode,r_timer1_ch3_th}; + `REG_TIM1_CH3_LUT: + PRDATA = {14'h0,r_timer1_ch3_flt,r_timer1_ch3_lut}; + `REG_TIM2_CFG: + PRDATA = {8'h0,r_timer2_presc,3'h0,r_timer2_saw,r_timer2_in_clk,r_timer2_in_mode,r_timer2_in_sel}; + `REG_TIM2_CH0_TH: + PRDATA = {13'h0,r_timer2_ch0_mode,r_timer2_ch0_th}; + `REG_TIM2_CH0_LUT: + PRDATA = {14'h0,r_timer2_ch0_flt,r_timer2_ch0_lut}; + `REG_TIM2_CH1_TH: + PRDATA = {13'h0,r_timer2_ch1_mode,r_timer2_ch1_th}; + `REG_TIM2_CH1_LUT: + PRDATA = {14'h0,r_timer2_ch1_flt,r_timer2_ch1_lut}; + `REG_TIM2_CH2_TH: + PRDATA = {13'h0,r_timer2_ch2_mode,r_timer2_ch2_th}; + `REG_TIM2_CH2_LUT: + PRDATA = {14'h0,r_timer2_ch2_flt,r_timer2_ch2_lut}; + `REG_TIM2_CH3_TH: + PRDATA = {13'h0,r_timer2_ch3_mode,r_timer2_ch3_th}; + `REG_TIM2_CH3_LUT: + PRDATA = {14'h0,r_timer2_ch3_flt,r_timer2_ch3_lut}; + `REG_TIM3_CFG: + PRDATA = {8'h0,r_timer3_presc,3'h0,r_timer3_saw,r_timer3_in_clk,r_timer3_in_mode,r_timer3_in_sel}; + `REG_TIM3_CH0_TH: + PRDATA = {13'h0,r_timer3_ch0_mode,r_timer3_ch0_th}; + `REG_TIM3_CH0_LUT: + PRDATA = {14'h0,r_timer3_ch0_flt,r_timer3_ch0_lut}; + `REG_TIM3_CH1_TH: + PRDATA = {13'h0,r_timer3_ch1_mode,r_timer3_ch1_th}; + `REG_TIM3_CH1_LUT: + PRDATA = {14'h0,r_timer3_ch1_flt,r_timer3_ch1_lut}; + `REG_TIM3_CH2_TH: + PRDATA = {13'h0,r_timer3_ch2_mode,r_timer3_ch2_th}; + `REG_TIM3_CH2_LUT: + PRDATA = {14'h0,r_timer3_ch2_flt,r_timer3_ch2_lut}; + `REG_TIM3_CH3_TH: + PRDATA = {13'h0,r_timer3_ch3_mode,r_timer3_ch3_th}; + `REG_TIM3_CH3_LUT: + PRDATA = {14'h0,r_timer3_ch3_flt,r_timer3_ch3_lut}; + `REG_TIM0_COUNTER: + PRDATA = {16'h0,timer0_counter_i}; + `REG_TIM1_COUNTER: + PRDATA = {16'h0,timer1_counter_i}; + `REG_TIM2_COUNTER: + PRDATA = {16'h0,timer2_counter_i}; + `REG_TIM3_COUNTER: + PRDATA = {16'h0,timer3_counter_i}; + `REG_EVENT_CFG: + PRDATA = {12'h0,r_event_en,r_event_sel_3,r_event_sel_2,r_event_sel_1,r_event_sel_0}; + `REG_CH_EN: + PRDATA = {28'h0,r_clk_en}; + default: + PRDATA = 'h0; + endcase + end + + + assign PREADY = 1'b1; + assign PSLVERR = 1'b0; + +endmodule diff --git a/rtl/e203/perips/apb_adv_timer/apb_adv_timer.sv b/rtl/e203/perips/apb_adv_timer/apb_adv_timer.sv deleted file mode 100644 index 6ecddcf..0000000 --- a/rtl/e203/perips/apb_adv_timer/apb_adv_timer.sv +++ /dev/null @@ -1,593 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// -- Adaptable modifications made for hbirdv2 SoC. -- -// Copyright 2020 Nuclei System Technology, Inc. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module apb_adv_timer #( - parameter APB_ADDR_WIDTH = 12, - parameter EXTSIG_NUM = 32, - parameter TIMER_NBITS = 16 -) ( - input logic HCLK, - input logic HRESETn, - input logic [APB_ADDR_WIDTH-1:0] PADDR, - input logic [31:0] PWDATA, - input logic PWRITE, - input logic PSEL, - input logic PENABLE, - output logic [31:0] PRDATA, - output logic PREADY, - output logic PSLVERR, - - input logic dft_cg_enable_i, - input logic low_speed_clk_i, - input logic [EXTSIG_NUM-1:0] ext_sig_i, - - output logic [3:0] events_o, - - output logic [3:0] ch_0_o, - output logic [3:0] ch_1_o, - output logic [3:0] ch_2_o, - output logic [3:0] ch_3_o -); - - localparam N_TIMEREXTSIG = EXTSIG_NUM+16; - - logic s_timer0_apb_start; - logic s_timer0_apb_stop; - logic s_timer0_apb_arm; - logic s_timer0_apb_update; - logic s_timer0_apb_rst; - logic s_timer0_apb_saw; - logic [7:0] s_timer0_apb_in_sel; - logic [2:0] s_timer0_apb_in_mode; - logic [7:0] s_timer0_apb_presc; - logic [15:0] s_timer0_apb_th_hi; - logic [15:0] s_timer0_apb_th_low; - logic [2:0] s_timer0_apb_ch0_mode; - logic [1:0] s_timer0_apb_ch0_flt; - logic [15:0] s_timer0_apb_ch0_th; - logic [15:0] s_timer0_apb_ch0_lut; - logic [2:0] s_timer0_apb_ch1_mode; - logic [1:0] s_timer0_apb_ch1_flt; - logic [15:0] s_timer0_apb_ch1_th; - logic [15:0] s_timer0_apb_ch1_lut; - logic [2:0] s_timer0_apb_ch2_mode; - logic [1:0] s_timer0_apb_ch2_flt; - logic [15:0] s_timer0_apb_ch2_th; - logic [15:0] s_timer0_apb_ch2_lut; - logic [2:0] s_timer0_apb_ch3_mode; - logic [1:0] s_timer0_apb_ch3_flt; - logic [15:0] s_timer0_apb_ch3_th; - logic [15:0] s_timer0_apb_ch3_lut; - - logic s_timer1_apb_start; - logic s_timer1_apb_stop; - logic s_timer1_apb_arm; - logic s_timer1_apb_update; - logic s_timer1_apb_rst; - logic s_timer1_apb_saw; - logic [7:0] s_timer1_apb_in_sel; - logic [2:0] s_timer1_apb_in_mode; - logic [7:0] s_timer1_apb_presc; - logic [15:0] s_timer1_apb_th_hi; - logic [15:0] s_timer1_apb_th_low; - logic [2:0] s_timer1_apb_ch0_mode; - logic [1:0] s_timer1_apb_ch0_flt; - logic [15:0] s_timer1_apb_ch0_th; - logic [15:0] s_timer1_apb_ch0_lut; - logic [2:0] s_timer1_apb_ch1_mode; - logic [1:0] s_timer1_apb_ch1_flt; - logic [15:0] s_timer1_apb_ch1_th; - logic [15:0] s_timer1_apb_ch1_lut; - logic [2:0] s_timer1_apb_ch2_mode; - logic [1:0] s_timer1_apb_ch2_flt; - logic [15:0] s_timer1_apb_ch2_th; - logic [15:0] s_timer1_apb_ch2_lut; - logic [2:0] s_timer1_apb_ch3_mode; - logic [1:0] s_timer1_apb_ch3_flt; - logic [15:0] s_timer1_apb_ch3_th; - logic [15:0] s_timer1_apb_ch3_lut; - - logic s_timer2_apb_start; - logic s_timer2_apb_stop; - logic s_timer2_apb_arm; - logic s_timer2_apb_update; - logic s_timer2_apb_rst; - logic s_timer2_apb_saw; - logic [7:0] s_timer2_apb_in_sel; - logic [2:0] s_timer2_apb_in_mode; - logic [7:0] s_timer2_apb_presc; - logic [15:0] s_timer2_apb_th_hi; - logic [15:0] s_timer2_apb_th_low; - logic [2:0] s_timer2_apb_ch0_mode; - logic [1:0] s_timer2_apb_ch0_flt; - logic [15:0] s_timer2_apb_ch0_th; - logic [15:0] s_timer2_apb_ch0_lut; - logic [2:0] s_timer2_apb_ch1_mode; - logic [1:0] s_timer2_apb_ch1_flt; - logic [15:0] s_timer2_apb_ch1_th; - logic [15:0] s_timer2_apb_ch1_lut; - logic [2:0] s_timer2_apb_ch2_mode; - logic [1:0] s_timer2_apb_ch2_flt; - logic [15:0] s_timer2_apb_ch2_th; - logic [15:0] s_timer2_apb_ch2_lut; - logic [2:0] s_timer2_apb_ch3_mode; - logic [1:0] s_timer2_apb_ch3_flt; - logic [15:0] s_timer2_apb_ch3_th; - logic [15:0] s_timer2_apb_ch3_lut; - - logic s_timer3_apb_start; - logic s_timer3_apb_stop; - logic s_timer3_apb_arm; - logic s_timer3_apb_update; - logic s_timer3_apb_rst; - logic s_timer3_apb_saw; - logic [7:0] s_timer3_apb_in_sel; - logic [2:0] s_timer3_apb_in_mode; - logic [7:0] s_timer3_apb_presc; - logic [15:0] s_timer3_apb_th_hi; - logic [15:0] s_timer3_apb_th_low; - logic [2:0] s_timer3_apb_ch0_mode; - logic [1:0] s_timer3_apb_ch0_flt; - logic [15:0] s_timer3_apb_ch0_th; - logic [15:0] s_timer3_apb_ch0_lut; - logic [2:0] s_timer3_apb_ch1_mode; - logic [1:0] s_timer3_apb_ch1_flt; - logic [15:0] s_timer3_apb_ch1_th; - logic [15:0] s_timer3_apb_ch1_lut; - logic [2:0] s_timer3_apb_ch2_mode; - logic [1:0] s_timer3_apb_ch2_flt; - logic [15:0] s_timer3_apb_ch2_th; - logic [15:0] s_timer3_apb_ch2_lut; - logic [2:0] s_timer3_apb_ch3_mode; - logic [1:0] s_timer3_apb_ch3_flt; - logic [15:0] s_timer3_apb_ch3_th; - logic [15:0] s_timer3_apb_ch3_lut; - - logic [3:0] s_event_en; - logic [3:0] s_event_sel_0; - logic [3:0] s_event_sel_1; - logic [3:0] s_event_sel_2; - logic [3:0] s_event_sel_3; - logic s_timer0_apb_in_clk; - logic s_timer1_apb_in_clk; - logic s_timer2_apb_in_clk; - logic s_timer3_apb_in_clk; - - logic [15:0] s_timer0_counter; - logic [15:0] s_timer1_counter; - logic [15:0] s_timer2_counter; - logic [15:0] s_timer3_counter; - - - logic s_timer0_clk_en; - logic s_timer1_clk_en; - logic s_timer2_clk_en; - logic s_timer3_clk_en; - - logic s_clk_timer0; - logic s_clk_timer1; - logic s_clk_timer2; - logic s_clk_timer3; - - - adv_timer_apb_if #( - .APB_ADDR_WIDTH ( APB_ADDR_WIDTH ) - ) u_apb_if ( - .HCLK ( HCLK ), - .HRESETn ( HRESETn ), - .PADDR ( PADDR ), - .PWDATA ( PWDATA ), - .PWRITE ( PWRITE ), - .PSEL ( PSEL ), - .PENABLE ( PENABLE ), - .PRDATA ( PRDATA ), - .PREADY ( PREADY ), - .PSLVERR ( PSLVERR ), - - .events_en_o ( s_event_en ), - .events_sel_0_o ( s_event_sel_0 ), - .events_sel_1_o ( s_event_sel_1 ), - .events_sel_2_o ( s_event_sel_2 ), - .events_sel_3_o ( s_event_sel_3 ), - - .timer0_start_o ( s_timer0_apb_start ), - .timer0_stop_o ( s_timer0_apb_stop ), - .timer0_arm_o ( s_timer0_apb_arm ), - .timer0_update_o ( s_timer0_apb_update ), - .timer0_rst_o ( s_timer0_apb_rst ), - .timer0_saw_o ( s_timer0_apb_saw ), - .timer0_in_sel_o ( s_timer0_apb_in_sel ), - .timer0_in_clk_o ( s_timer0_apb_in_clk ), - .timer0_in_mode_o ( s_timer0_apb_in_mode ), - .timer0_presc_o ( s_timer0_apb_presc ), - .timer0_th_hi_o ( s_timer0_apb_th_hi ), - .timer0_th_low_o ( s_timer0_apb_th_low ), - .timer0_ch0_mode_o ( s_timer0_apb_ch0_mode ), - .timer0_ch0_flt_o ( s_timer0_apb_ch0_flt ), - .timer0_ch0_th_o ( s_timer0_apb_ch0_th ), - .timer0_ch0_lut_o ( s_timer0_apb_ch0_lut ), - .timer0_ch1_mode_o ( s_timer0_apb_ch1_mode ), - .timer0_ch1_flt_o ( s_timer0_apb_ch1_flt ), - .timer0_ch1_th_o ( s_timer0_apb_ch1_th ), - .timer0_ch1_lut_o ( s_timer0_apb_ch1_lut ), - .timer0_ch2_mode_o ( s_timer0_apb_ch2_mode ), - .timer0_ch2_flt_o ( s_timer0_apb_ch2_flt ), - .timer0_ch2_th_o ( s_timer0_apb_ch2_th ), - .timer0_ch2_lut_o ( s_timer0_apb_ch2_lut ), - .timer0_ch3_mode_o ( s_timer0_apb_ch3_mode ), - .timer0_ch3_flt_o ( s_timer0_apb_ch3_flt ), - .timer0_ch3_th_o ( s_timer0_apb_ch3_th ), - .timer0_ch3_lut_o ( s_timer0_apb_ch3_lut ), - .timer0_counter_i ( s_timer0_counter ), - - .timer1_start_o ( s_timer1_apb_start ), - .timer1_stop_o ( s_timer1_apb_stop ), - .timer1_arm_o ( s_timer1_apb_arm ), - .timer1_update_o ( s_timer1_apb_update ), - .timer1_rst_o ( s_timer1_apb_rst ), - .timer1_saw_o ( s_timer1_apb_saw ), - .timer1_in_sel_o ( s_timer1_apb_in_sel ), - .timer1_in_clk_o ( s_timer1_apb_in_clk ), - .timer1_in_mode_o ( s_timer1_apb_in_mode ), - .timer1_presc_o ( s_timer1_apb_presc ), - .timer1_th_hi_o ( s_timer1_apb_th_hi ), - .timer1_th_low_o ( s_timer1_apb_th_low ), - .timer1_ch0_mode_o ( s_timer1_apb_ch0_mode ), - .timer1_ch0_flt_o ( s_timer1_apb_ch0_flt ), - .timer1_ch0_th_o ( s_timer1_apb_ch0_th ), - .timer1_ch0_lut_o ( s_timer1_apb_ch0_lut ), - .timer1_ch1_mode_o ( s_timer1_apb_ch1_mode ), - .timer1_ch1_flt_o ( s_timer1_apb_ch1_flt ), - .timer1_ch1_th_o ( s_timer1_apb_ch1_th ), - .timer1_ch1_lut_o ( s_timer1_apb_ch1_lut ), - .timer1_ch2_mode_o ( s_timer1_apb_ch2_mode ), - .timer1_ch2_flt_o ( s_timer1_apb_ch2_flt ), - .timer1_ch2_th_o ( s_timer1_apb_ch2_th ), - .timer1_ch2_lut_o ( s_timer1_apb_ch2_lut ), - .timer1_ch3_mode_o ( s_timer1_apb_ch3_mode ), - .timer1_ch3_flt_o ( s_timer1_apb_ch3_flt ), - .timer1_ch3_th_o ( s_timer1_apb_ch3_th ), - .timer1_ch3_lut_o ( s_timer1_apb_ch3_lut ), - .timer1_counter_i ( s_timer1_counter ), - - .timer2_start_o ( s_timer2_apb_start ), - .timer2_stop_o ( s_timer2_apb_stop ), - .timer2_arm_o ( s_timer2_apb_arm ), - .timer2_update_o ( s_timer2_apb_update ), - .timer2_rst_o ( s_timer2_apb_rst ), - .timer2_saw_o ( s_timer2_apb_saw ), - .timer2_in_sel_o ( s_timer2_apb_in_sel ), - .timer2_in_clk_o ( s_timer2_apb_in_clk ), - .timer2_in_mode_o ( s_timer2_apb_in_mode ), - .timer2_presc_o ( s_timer2_apb_presc ), - .timer2_th_hi_o ( s_timer2_apb_th_hi ), - .timer2_th_low_o ( s_timer2_apb_th_low ), - .timer2_ch0_mode_o ( s_timer2_apb_ch0_mode ), - .timer2_ch0_flt_o ( s_timer2_apb_ch0_flt ), - .timer2_ch0_th_o ( s_timer2_apb_ch0_th ), - .timer2_ch0_lut_o ( s_timer2_apb_ch0_lut ), - .timer2_ch1_mode_o ( s_timer2_apb_ch1_mode ), - .timer2_ch1_flt_o ( s_timer2_apb_ch1_flt ), - .timer2_ch1_th_o ( s_timer2_apb_ch1_th ), - .timer2_ch1_lut_o ( s_timer2_apb_ch1_lut ), - .timer2_ch2_mode_o ( s_timer2_apb_ch2_mode ), - .timer2_ch2_flt_o ( s_timer2_apb_ch2_flt ), - .timer2_ch2_th_o ( s_timer2_apb_ch2_th ), - .timer2_ch2_lut_o ( s_timer2_apb_ch2_lut ), - .timer2_ch3_mode_o ( s_timer2_apb_ch3_mode ), - .timer2_ch3_flt_o ( s_timer2_apb_ch3_flt ), - .timer2_ch3_th_o ( s_timer2_apb_ch3_th ), - .timer2_ch3_lut_o ( s_timer2_apb_ch3_lut ), - .timer2_counter_i ( s_timer2_counter ), - - .timer3_start_o ( s_timer3_apb_start ), - .timer3_stop_o ( s_timer3_apb_stop ), - .timer3_arm_o ( s_timer3_apb_arm ), - .timer3_update_o ( s_timer3_apb_update ), - .timer3_rst_o ( s_timer3_apb_rst ), - .timer3_saw_o ( s_timer3_apb_saw ), - .timer3_in_sel_o ( s_timer3_apb_in_sel ), - .timer3_in_clk_o ( s_timer3_apb_in_clk ), - .timer3_in_mode_o ( s_timer3_apb_in_mode ), - .timer3_presc_o ( s_timer3_apb_presc ), - .timer3_th_hi_o ( s_timer3_apb_th_hi ), - .timer3_th_low_o ( s_timer3_apb_th_low ), - .timer3_ch0_mode_o ( s_timer3_apb_ch0_mode ), - .timer3_ch0_flt_o ( s_timer3_apb_ch0_flt ), - .timer3_ch0_th_o ( s_timer3_apb_ch0_th ), - .timer3_ch0_lut_o ( s_timer3_apb_ch0_lut ), - .timer3_ch1_mode_o ( s_timer3_apb_ch1_mode ), - .timer3_ch1_flt_o ( s_timer3_apb_ch1_flt ), - .timer3_ch1_th_o ( s_timer3_apb_ch1_th ), - .timer3_ch1_lut_o ( s_timer3_apb_ch1_lut ), - .timer3_ch2_mode_o ( s_timer3_apb_ch2_mode ), - .timer3_ch2_flt_o ( s_timer3_apb_ch2_flt ), - .timer3_ch2_th_o ( s_timer3_apb_ch2_th ), - .timer3_ch2_lut_o ( s_timer3_apb_ch2_lut ), - .timer3_ch3_mode_o ( s_timer3_apb_ch3_mode ), - .timer3_ch3_flt_o ( s_timer3_apb_ch3_flt ), - .timer3_ch3_th_o ( s_timer3_apb_ch3_th ), - .timer3_ch3_lut_o ( s_timer3_apb_ch3_lut ), - .timer3_counter_i ( s_timer3_counter ), - - .timer0_clk_en_o ( s_timer0_clk_en ), - .timer1_clk_en_o ( s_timer1_clk_en ), - .timer2_clk_en_o ( s_timer2_clk_en ), - .timer3_clk_en_o ( s_timer3_clk_en ) - ); - -///////////////////////////////////////////////////////////////////// -// -// TIMER0 -// -///////////////////////////////////////////////////////////////////// - logic [7:0] s_timer0_status; - logic [N_TIMEREXTSIG-1:0] s_timer0_signal; - assign s_timer0_signal = {ch_3_o,ch_2_o,ch_1_o,ch_0_o,ext_sig_i}; - - e203_clkgate i_clk_gate_timer0 - ( - .clk_in(HCLK), - .clock_en(s_timer0_clk_en), - .test_mode(dft_cg_enable_i), - .clk_out(s_clk_timer0) - ); - - timer_module #( - .NUM_BITS(TIMER_NBITS), - .N_EXTSIG(N_TIMEREXTSIG) - ) u_tim0 ( - .clk_i ( s_clk_timer0 ), - .rstn_i ( HRESETn ), - - .cfg_start_i ( s_timer0_apb_start ), - .cfg_stop_i ( s_timer0_apb_stop ), - .cfg_rst_i ( s_timer0_apb_rst ), - .cfg_update_i ( s_timer0_apb_update ), - .cfg_arm_i ( s_timer0_apb_arm ), - - .cfg_sel_i ( s_timer0_apb_in_sel ), - .cfg_sel_clk_i ( s_timer0_apb_in_clk ), - .cfg_mode_i ( s_timer0_apb_in_mode ), - - .cfg_presc_i ( s_timer0_apb_presc ), - - .cfg_sawtooth_i ( s_timer0_apb_saw ), - .cfg_cnt_start_i ( s_timer0_apb_th_low ), - .cfg_cnt_end_i ( s_timer0_apb_th_hi ), - - .cfg_comp_ch0_i ( s_timer0_apb_ch0_th ), - .cfg_comp_op_ch0_i( s_timer0_apb_ch0_mode ), - .cfg_comp_ch1_i ( s_timer0_apb_ch1_th ), - .cfg_comp_op_ch1_i( s_timer0_apb_ch1_mode ), - .cfg_comp_ch2_i ( s_timer0_apb_ch2_th ), - .cfg_comp_op_ch2_i( s_timer0_apb_ch2_mode ), - .cfg_comp_ch3_i ( s_timer0_apb_ch3_th ), - .cfg_comp_op_ch3_i( s_timer0_apb_ch3_mode ), - - .ls_clk_i ( low_speed_clk_i ), - .signal_i ( s_timer0_signal ), - - .counter_o ( s_timer0_counter ), - - .pwm_o ( ch_0_o ), - .status_o ( s_timer0_status ) - ); - -///////////////////////////////////////////////////////////////////// -// -// TIMER0 -// -///////////////////////////////////////////////////////////////////// - logic [7:0] s_timer1_status; - logic [N_TIMEREXTSIG-1:0] s_timer1_signal; - assign s_timer1_signal = {ch_3_o,ch_2_o,ch_1_o,ch_0_o,ext_sig_i}; - - e203_clkgate i_clk_gate_timer1 - ( - .clk_in(HCLK), - .clock_en(s_timer1_clk_en), - .test_mode(dft_cg_enable_i), - .clk_out(s_clk_timer1) - ); - - timer_module #( - .NUM_BITS(TIMER_NBITS), - .N_EXTSIG(N_TIMEREXTSIG) - ) u_tim1 ( - .clk_i ( s_clk_timer1 ), - .rstn_i ( HRESETn ), - - .cfg_start_i ( s_timer1_apb_start ), - .cfg_stop_i ( s_timer1_apb_stop ), - .cfg_rst_i ( s_timer1_apb_rst ), - .cfg_update_i ( s_timer1_apb_update ), - .cfg_arm_i ( s_timer1_apb_arm ), - - .cfg_sel_i ( s_timer1_apb_in_sel ), - .cfg_sel_clk_i ( s_timer1_apb_in_clk ), - .cfg_mode_i ( s_timer1_apb_in_mode ), - - .cfg_presc_i ( s_timer1_apb_presc ), - - .cfg_sawtooth_i ( s_timer1_apb_saw ), - .cfg_cnt_start_i ( s_timer1_apb_th_low ), - .cfg_cnt_end_i ( s_timer1_apb_th_hi ), - - .cfg_comp_ch0_i ( s_timer1_apb_ch0_th ), - .cfg_comp_op_ch0_i( s_timer1_apb_ch0_mode ), - .cfg_comp_ch1_i ( s_timer1_apb_ch1_th ), - .cfg_comp_op_ch1_i( s_timer1_apb_ch1_mode ), - .cfg_comp_ch2_i ( s_timer1_apb_ch2_th ), - .cfg_comp_op_ch2_i( s_timer1_apb_ch2_mode ), - .cfg_comp_ch3_i ( s_timer1_apb_ch3_th ), - .cfg_comp_op_ch3_i( s_timer1_apb_ch3_mode ), - - .ls_clk_i ( low_speed_clk_i ), - .signal_i ( s_timer1_signal ), - - .counter_o ( s_timer1_counter ), - - .pwm_o ( ch_1_o ), - .status_o ( s_timer1_status ) - ); - -///////////////////////////////////////////////////////////////////// -// -// TIMER2 -// -///////////////////////////////////////////////////////////////////// - logic [7:0] s_timer2_status; - logic [N_TIMEREXTSIG-1:0] s_timer2_signal; - assign s_timer2_signal = {ch_3_o,ch_2_o,ch_1_o,ch_0_o,ext_sig_i}; - - e203_clkgate i_clk_gate_timer2 - ( - .clk_in(HCLK), - .clock_en(s_timer2_clk_en), - .test_mode(dft_cg_enable_i), - .clk_out(s_clk_timer2) - ); - - - timer_module #( - .NUM_BITS(TIMER_NBITS), - .N_EXTSIG(N_TIMEREXTSIG) - ) u_tim2 ( - .clk_i ( s_clk_timer2 ), - .rstn_i ( HRESETn ), - - .cfg_start_i ( s_timer2_apb_start ), - .cfg_stop_i ( s_timer2_apb_stop ), - .cfg_rst_i ( s_timer2_apb_rst ), - .cfg_update_i ( s_timer2_apb_update ), - .cfg_arm_i ( s_timer2_apb_arm ), - - .cfg_sel_i ( s_timer2_apb_in_sel ), - .cfg_sel_clk_i ( s_timer2_apb_in_clk ), - .cfg_mode_i ( s_timer2_apb_in_mode ), - - .cfg_presc_i ( s_timer2_apb_presc ), - - .cfg_sawtooth_i ( s_timer2_apb_saw ), - .cfg_cnt_start_i ( s_timer2_apb_th_low ), - .cfg_cnt_end_i ( s_timer2_apb_th_hi ), - - .cfg_comp_ch0_i ( s_timer2_apb_ch0_th ), - .cfg_comp_op_ch0_i( s_timer2_apb_ch0_mode ), - .cfg_comp_ch1_i ( s_timer2_apb_ch1_th ), - .cfg_comp_op_ch1_i( s_timer2_apb_ch1_mode ), - .cfg_comp_ch2_i ( s_timer2_apb_ch2_th ), - .cfg_comp_op_ch2_i( s_timer2_apb_ch2_mode ), - .cfg_comp_ch3_i ( s_timer2_apb_ch3_th ), - .cfg_comp_op_ch3_i( s_timer2_apb_ch3_mode ), - - .ls_clk_i ( low_speed_clk_i ), - .signal_i ( s_timer2_signal ), - - .counter_o ( s_timer2_counter ), - - .pwm_o ( ch_2_o ), - .status_o ( s_timer2_status ) - ); - -///////////////////////////////////////////////////////////////////// -// -// TIMER3 -// -///////////////////////////////////////////////////////////////////// - logic [7:0] s_timer3_status; - logic [N_TIMEREXTSIG-1:0] s_timer3_signal; - assign s_timer3_signal = {ch_3_o,ch_2_o,ch_1_o,ch_0_o,ext_sig_i}; - - e203_clkgate i_clk_gate_timer3 - ( - .clk_in(HCLK), - .clock_en(s_timer3_clk_en), - .test_mode(dft_cg_enable_i), - .clk_out(s_clk_timer3) - ); - - - timer_module #( - .NUM_BITS(TIMER_NBITS), - .N_EXTSIG(N_TIMEREXTSIG) - ) u_tim3 ( - .clk_i ( s_clk_timer3 ), - .rstn_i ( HRESETn ), - - .cfg_start_i ( s_timer3_apb_start ), - .cfg_stop_i ( s_timer3_apb_stop ), - .cfg_rst_i ( s_timer3_apb_rst ), - .cfg_update_i ( s_timer3_apb_update ), - .cfg_arm_i ( s_timer3_apb_arm ), - - .cfg_sel_i ( s_timer3_apb_in_sel ), - .cfg_sel_clk_i ( s_timer3_apb_in_clk ), - .cfg_mode_i ( s_timer3_apb_in_mode ), - - .cfg_presc_i ( s_timer3_apb_presc ), - - .cfg_sawtooth_i ( s_timer3_apb_saw ), - .cfg_cnt_start_i ( s_timer3_apb_th_low ), - .cfg_cnt_end_i ( s_timer3_apb_th_hi ), - - .cfg_comp_ch0_i ( s_timer3_apb_ch0_th ), - .cfg_comp_op_ch0_i( s_timer3_apb_ch0_mode ), - .cfg_comp_ch1_i ( s_timer3_apb_ch1_th ), - .cfg_comp_op_ch1_i( s_timer3_apb_ch1_mode ), - .cfg_comp_ch2_i ( s_timer3_apb_ch2_th ), - .cfg_comp_op_ch2_i( s_timer3_apb_ch2_mode ), - .cfg_comp_ch3_i ( s_timer3_apb_ch3_th ), - .cfg_comp_op_ch3_i( s_timer3_apb_ch3_mode ), - - .ls_clk_i ( low_speed_clk_i ), - .signal_i ( s_timer3_signal ), - - .counter_o ( s_timer3_counter ), - - .pwm_o ( ch_3_o ), - .status_o ( s_timer3_status ) - ); - - logic [15:0] s_event_signals; - logic [1:0] r_event_sync_0; - logic [1:0] r_event_sync_1; - logic [1:0] r_event_sync_2; - logic [1:0] r_event_sync_3; - - assign s_event_signals = {ch_3_o,ch_2_o,ch_1_o,ch_0_o}; - - assign events_o[0] = s_event_en[0] & r_event_sync_0[1] & ~r_event_sync_0[0]; - assign events_o[1] = s_event_en[1] & r_event_sync_1[1] & ~r_event_sync_1[0]; - assign events_o[2] = s_event_en[2] & r_event_sync_2[1] & ~r_event_sync_2[0]; - assign events_o[3] = s_event_en[3] & r_event_sync_3[1] & ~r_event_sync_3[0]; - - always_ff @(posedge HCLK or negedge HRESETn) begin : proc_edgedet - if(~HRESETn) begin - r_event_sync_0 <= 0; - r_event_sync_1 <= 0; - r_event_sync_2 <= 0; - r_event_sync_3 <= 0; - end else begin - if (s_event_en[0]) - r_event_sync_0 <= {s_event_signals[s_event_sel_0],r_event_sync_0[1]}; - if (s_event_en[1]) - r_event_sync_1 <= {s_event_signals[s_event_sel_1],r_event_sync_1[1]}; - if (s_event_en[2]) - r_event_sync_2 <= {s_event_signals[s_event_sel_2],r_event_sync_2[1]}; - if (s_event_en[3]) - r_event_sync_3 <= {s_event_signals[s_event_sel_3],r_event_sync_3[1]}; - end - end - -endmodule // apb_adv_timer diff --git a/rtl/e203/perips/apb_adv_timer/apb_adv_timer.v b/rtl/e203/perips/apb_adv_timer/apb_adv_timer.v new file mode 100644 index 0000000..dbc0186 --- /dev/null +++ b/rtl/e203/perips/apb_adv_timer/apb_adv_timer.v @@ -0,0 +1,606 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module apb_adv_timer #( + parameter APB_ADDR_WIDTH = 12, + parameter EXTSIG_NUM = 32, + parameter TIMER_NBITS = 16 +) +( + input wire HCLK, + input wire HRESETn, + input wire [APB_ADDR_WIDTH - 1:0] PADDR, + input wire [31:0] PWDATA, + input wire PWRITE, + input wire PSEL, + input wire PENABLE, + output wire [31:0] PRDATA, + output wire PREADY, + output wire PSLVERR, + + input wire dft_cg_enable_i, + input wire low_speed_clk_i, + input wire [EXTSIG_NUM - 1:0] ext_sig_i, + + output wire [3:0] events_o, + + output wire [3:0] ch_0_o, + output wire [3:0] ch_1_o, + output wire [3:0] ch_2_o, + output wire [3:0] ch_3_o +); + + localparam N_TIMEREXTSIG = EXTSIG_NUM + 16; + + wire s_timer0_apb_start; + wire s_timer0_apb_stop; + wire s_timer0_apb_arm; + wire s_timer0_apb_update; + wire s_timer0_apb_rst; + wire s_timer0_apb_saw; + wire [7:0] s_timer0_apb_in_sel; + wire [2:0] s_timer0_apb_in_mode; + wire [7:0] s_timer0_apb_presc; + wire [15:0] s_timer0_apb_th_hi; + wire [15:0] s_timer0_apb_th_low; + wire [2:0] s_timer0_apb_ch0_mode; + wire [1:0] s_timer0_apb_ch0_flt; + wire [15:0] s_timer0_apb_ch0_th; + wire [15:0] s_timer0_apb_ch0_lut; + wire [2:0] s_timer0_apb_ch1_mode; + wire [1:0] s_timer0_apb_ch1_flt; + wire [15:0] s_timer0_apb_ch1_th; + wire [15:0] s_timer0_apb_ch1_lut; + wire [2:0] s_timer0_apb_ch2_mode; + wire [1:0] s_timer0_apb_ch2_flt; + wire [15:0] s_timer0_apb_ch2_th; + wire [15:0] s_timer0_apb_ch2_lut; + wire [2:0] s_timer0_apb_ch3_mode; + wire [1:0] s_timer0_apb_ch3_flt; + wire [15:0] s_timer0_apb_ch3_th; + wire [15:0] s_timer0_apb_ch3_lut; + + wire s_timer1_apb_start; + wire s_timer1_apb_stop; + wire s_timer1_apb_arm; + wire s_timer1_apb_update; + wire s_timer1_apb_rst; + wire s_timer1_apb_saw; + wire [7:0] s_timer1_apb_in_sel; + wire [2:0] s_timer1_apb_in_mode; + wire [7:0] s_timer1_apb_presc; + wire [15:0] s_timer1_apb_th_hi; + wire [15:0] s_timer1_apb_th_low; + wire [2:0] s_timer1_apb_ch0_mode; + wire [1:0] s_timer1_apb_ch0_flt; + wire [15:0] s_timer1_apb_ch0_th; + wire [15:0] s_timer1_apb_ch0_lut; + wire [2:0] s_timer1_apb_ch1_mode; + wire [1:0] s_timer1_apb_ch1_flt; + wire [15:0] s_timer1_apb_ch1_th; + wire [15:0] s_timer1_apb_ch1_lut; + wire [2:0] s_timer1_apb_ch2_mode; + wire [1:0] s_timer1_apb_ch2_flt; + wire [15:0] s_timer1_apb_ch2_th; + wire [15:0] s_timer1_apb_ch2_lut; + wire [2:0] s_timer1_apb_ch3_mode; + wire [1:0] s_timer1_apb_ch3_flt; + wire [15:0] s_timer1_apb_ch3_th; + wire [15:0] s_timer1_apb_ch3_lut; + + + wire s_timer2_apb_start; + wire s_timer2_apb_stop; + wire s_timer2_apb_arm; + wire s_timer2_apb_update; + wire s_timer2_apb_rst; + wire s_timer2_apb_saw; + wire [7:0] s_timer2_apb_in_sel; + wire [2:0] s_timer2_apb_in_mode; + wire [7:0] s_timer2_apb_presc; + wire [15:0] s_timer2_apb_th_hi; + wire [15:0] s_timer2_apb_th_low; + wire [2:0] s_timer2_apb_ch0_mode; + wire [1:0] s_timer2_apb_ch0_flt; + wire [15:0] s_timer2_apb_ch0_th; + wire [15:0] s_timer2_apb_ch0_lut; + wire [2:0] s_timer2_apb_ch1_mode; + wire [1:0] s_timer2_apb_ch1_flt; + wire [15:0] s_timer2_apb_ch1_th; + wire [15:0] s_timer2_apb_ch1_lut; + wire [2:0] s_timer2_apb_ch2_mode; + wire [1:0] s_timer2_apb_ch2_flt; + wire [15:0] s_timer2_apb_ch2_th; + wire [15:0] s_timer2_apb_ch2_lut; + wire [2:0] s_timer2_apb_ch3_mode; + wire [1:0] s_timer2_apb_ch3_flt; + wire [15:0] s_timer2_apb_ch3_th; + wire [15:0] s_timer2_apb_ch3_lut; + + + wire s_timer3_apb_start; + wire s_timer3_apb_stop; + wire s_timer3_apb_arm; + wire s_timer3_apb_update; + wire s_timer3_apb_rst; + wire s_timer3_apb_saw; + wire [7:0] s_timer3_apb_in_sel; + wire [2:0] s_timer3_apb_in_mode; + wire [7:0] s_timer3_apb_presc; + wire [15:0] s_timer3_apb_th_hi; + wire [15:0] s_timer3_apb_th_low; + wire [2:0] s_timer3_apb_ch0_mode; + wire [1:0] s_timer3_apb_ch0_flt; + wire [15:0] s_timer3_apb_ch0_th; + wire [15:0] s_timer3_apb_ch0_lut; + wire [2:0] s_timer3_apb_ch1_mode; + wire [1:0] s_timer3_apb_ch1_flt; + wire [15:0] s_timer3_apb_ch1_th; + wire [15:0] s_timer3_apb_ch1_lut; + wire [2:0] s_timer3_apb_ch2_mode; + wire [1:0] s_timer3_apb_ch2_flt; + wire [15:0] s_timer3_apb_ch2_th; + wire [15:0] s_timer3_apb_ch2_lut; + wire [2:0] s_timer3_apb_ch3_mode; + wire [1:0] s_timer3_apb_ch3_flt; + wire [15:0] s_timer3_apb_ch3_th; + wire [15:0] s_timer3_apb_ch3_lut; + + + wire [3:0] s_event_en; + wire [3:0] s_event_sel_0; + wire [3:0] s_event_sel_1; + wire [3:0] s_event_sel_2; + wire [3:0] s_event_sel_3; + + + wire s_timer0_apb_in_clk; + wire s_timer1_apb_in_clk; + wire s_timer2_apb_in_clk; + wire s_timer3_apb_in_clk; + + + wire [15:0] s_timer0_counter; + wire [15:0] s_timer1_counter; + wire [15:0] s_timer2_counter; + wire [15:0] s_timer3_counter; + + + wire s_timer0_clk_en; + wire s_timer1_clk_en; + wire s_timer2_clk_en; + wire s_timer3_clk_en; + wire s_clk_timer0; + wire s_clk_timer1; + wire s_clk_timer2; + wire s_clk_timer3; + + adv_timer_apb_if #( + .APB_ADDR_WIDTH ( APB_ADDR_WIDTH ) + ) u_apb_if ( + .HCLK ( HCLK ), + .HRESETn ( HRESETn ), + .PADDR ( PADDR ), + .PWDATA ( PWDATA ), + .PWRITE ( PWRITE ), + .PSEL ( PSEL ), + .PENABLE ( PENABLE ), + .PRDATA ( PRDATA ), + .PREADY ( PREADY ), + .PSLVERR ( PSLVERR ), + + .events_en_o ( s_event_en ), + .events_sel_0_o ( s_event_sel_0 ), + .events_sel_1_o ( s_event_sel_1 ), + .events_sel_2_o ( s_event_sel_2 ), + .events_sel_3_o ( s_event_sel_3 ), + + .timer0_start_o ( s_timer0_apb_start ), + .timer0_stop_o ( s_timer0_apb_stop ), + .timer0_arm_o ( s_timer0_apb_arm ), + .timer0_update_o ( s_timer0_apb_update ), + .timer0_rst_o ( s_timer0_apb_rst ), + .timer0_saw_o ( s_timer0_apb_saw ), + .timer0_in_sel_o ( s_timer0_apb_in_sel ), + .timer0_in_clk_o ( s_timer0_apb_in_clk ), + .timer0_in_mode_o ( s_timer0_apb_in_mode ), + .timer0_presc_o ( s_timer0_apb_presc ), + .timer0_th_hi_o ( s_timer0_apb_th_hi ), + .timer0_th_low_o ( s_timer0_apb_th_low ), + .timer0_ch0_mode_o ( s_timer0_apb_ch0_mode ), + .timer0_ch0_flt_o ( s_timer0_apb_ch0_flt ), + .timer0_ch0_th_o ( s_timer0_apb_ch0_th ), + .timer0_ch0_lut_o ( s_timer0_apb_ch0_lut ), + .timer0_ch1_mode_o ( s_timer0_apb_ch1_mode ), + .timer0_ch1_flt_o ( s_timer0_apb_ch1_flt ), + .timer0_ch1_th_o ( s_timer0_apb_ch1_th ), + .timer0_ch1_lut_o ( s_timer0_apb_ch1_lut ), + .timer0_ch2_mode_o ( s_timer0_apb_ch2_mode ), + .timer0_ch2_flt_o ( s_timer0_apb_ch2_flt ), + .timer0_ch2_th_o ( s_timer0_apb_ch2_th ), + .timer0_ch2_lut_o ( s_timer0_apb_ch2_lut ), + .timer0_ch3_mode_o ( s_timer0_apb_ch3_mode ), + .timer0_ch3_flt_o ( s_timer0_apb_ch3_flt ), + .timer0_ch3_th_o ( s_timer0_apb_ch3_th ), + .timer0_ch3_lut_o ( s_timer0_apb_ch3_lut ), + .timer0_counter_i ( s_timer0_counter ), + + .timer1_start_o ( s_timer1_apb_start ), + .timer1_stop_o ( s_timer1_apb_stop ), + .timer1_arm_o ( s_timer1_apb_arm ), + .timer1_update_o ( s_timer1_apb_update ), + .timer1_rst_o ( s_timer1_apb_rst ), + .timer1_saw_o ( s_timer1_apb_saw ), + .timer1_in_sel_o ( s_timer1_apb_in_sel ), + .timer1_in_clk_o ( s_timer1_apb_in_clk ), + .timer1_in_mode_o ( s_timer1_apb_in_mode ), + .timer1_presc_o ( s_timer1_apb_presc ), + .timer1_th_hi_o ( s_timer1_apb_th_hi ), + .timer1_th_low_o ( s_timer1_apb_th_low ), + .timer1_ch0_mode_o ( s_timer1_apb_ch0_mode ), + .timer1_ch0_flt_o ( s_timer1_apb_ch0_flt ), + .timer1_ch0_th_o ( s_timer1_apb_ch0_th ), + .timer1_ch0_lut_o ( s_timer1_apb_ch0_lut ), + .timer1_ch1_mode_o ( s_timer1_apb_ch1_mode ), + .timer1_ch1_flt_o ( s_timer1_apb_ch1_flt ), + .timer1_ch1_th_o ( s_timer1_apb_ch1_th ), + .timer1_ch1_lut_o ( s_timer1_apb_ch1_lut ), + .timer1_ch2_mode_o ( s_timer1_apb_ch2_mode ), + .timer1_ch2_flt_o ( s_timer1_apb_ch2_flt ), + .timer1_ch2_th_o ( s_timer1_apb_ch2_th ), + .timer1_ch2_lut_o ( s_timer1_apb_ch2_lut ), + .timer1_ch3_mode_o ( s_timer1_apb_ch3_mode ), + .timer1_ch3_flt_o ( s_timer1_apb_ch3_flt ), + .timer1_ch3_th_o ( s_timer1_apb_ch3_th ), + .timer1_ch3_lut_o ( s_timer1_apb_ch3_lut ), + .timer1_counter_i ( s_timer1_counter ), + + .timer2_start_o ( s_timer2_apb_start ), + .timer2_stop_o ( s_timer2_apb_stop ), + .timer2_arm_o ( s_timer2_apb_arm ), + .timer2_update_o ( s_timer2_apb_update ), + .timer2_rst_o ( s_timer2_apb_rst ), + .timer2_saw_o ( s_timer2_apb_saw ), + .timer2_in_sel_o ( s_timer2_apb_in_sel ), + .timer2_in_clk_o ( s_timer2_apb_in_clk ), + .timer2_in_mode_o ( s_timer2_apb_in_mode ), + .timer2_presc_o ( s_timer2_apb_presc ), + .timer2_th_hi_o ( s_timer2_apb_th_hi ), + .timer2_th_low_o ( s_timer2_apb_th_low ), + .timer2_ch0_mode_o ( s_timer2_apb_ch0_mode ), + .timer2_ch0_flt_o ( s_timer2_apb_ch0_flt ), + .timer2_ch0_th_o ( s_timer2_apb_ch0_th ), + .timer2_ch0_lut_o ( s_timer2_apb_ch0_lut ), + .timer2_ch1_mode_o ( s_timer2_apb_ch1_mode ), + .timer2_ch1_flt_o ( s_timer2_apb_ch1_flt ), + .timer2_ch1_th_o ( s_timer2_apb_ch1_th ), + .timer2_ch1_lut_o ( s_timer2_apb_ch1_lut ), + .timer2_ch2_mode_o ( s_timer2_apb_ch2_mode ), + .timer2_ch2_flt_o ( s_timer2_apb_ch2_flt ), + .timer2_ch2_th_o ( s_timer2_apb_ch2_th ), + .timer2_ch2_lut_o ( s_timer2_apb_ch2_lut ), + .timer2_ch3_mode_o ( s_timer2_apb_ch3_mode ), + .timer2_ch3_flt_o ( s_timer2_apb_ch3_flt ), + .timer2_ch3_th_o ( s_timer2_apb_ch3_th ), + .timer2_ch3_lut_o ( s_timer2_apb_ch3_lut ), + .timer2_counter_i ( s_timer2_counter ), + + .timer3_start_o ( s_timer3_apb_start ), + .timer3_stop_o ( s_timer3_apb_stop ), + .timer3_arm_o ( s_timer3_apb_arm ), + .timer3_update_o ( s_timer3_apb_update ), + .timer3_rst_o ( s_timer3_apb_rst ), + .timer3_saw_o ( s_timer3_apb_saw ), + .timer3_in_sel_o ( s_timer3_apb_in_sel ), + .timer3_in_clk_o ( s_timer3_apb_in_clk ), + .timer3_in_mode_o ( s_timer3_apb_in_mode ), + .timer3_presc_o ( s_timer3_apb_presc ), + .timer3_th_hi_o ( s_timer3_apb_th_hi ), + .timer3_th_low_o ( s_timer3_apb_th_low ), + .timer3_ch0_mode_o ( s_timer3_apb_ch0_mode ), + .timer3_ch0_flt_o ( s_timer3_apb_ch0_flt ), + .timer3_ch0_th_o ( s_timer3_apb_ch0_th ), + .timer3_ch0_lut_o ( s_timer3_apb_ch0_lut ), + .timer3_ch1_mode_o ( s_timer3_apb_ch1_mode ), + .timer3_ch1_flt_o ( s_timer3_apb_ch1_flt ), + .timer3_ch1_th_o ( s_timer3_apb_ch1_th ), + .timer3_ch1_lut_o ( s_timer3_apb_ch1_lut ), + .timer3_ch2_mode_o ( s_timer3_apb_ch2_mode ), + .timer3_ch2_flt_o ( s_timer3_apb_ch2_flt ), + .timer3_ch2_th_o ( s_timer3_apb_ch2_th ), + .timer3_ch2_lut_o ( s_timer3_apb_ch2_lut ), + .timer3_ch3_mode_o ( s_timer3_apb_ch3_mode ), + .timer3_ch3_flt_o ( s_timer3_apb_ch3_flt ), + .timer3_ch3_th_o ( s_timer3_apb_ch3_th ), + .timer3_ch3_lut_o ( s_timer3_apb_ch3_lut ), + .timer3_counter_i ( s_timer3_counter ), + + .timer0_clk_en_o ( s_timer0_clk_en ), + .timer1_clk_en_o ( s_timer1_clk_en ), + .timer2_clk_en_o ( s_timer2_clk_en ), + .timer3_clk_en_o ( s_timer3_clk_en ) + ); + + ///////////////////////////////////////////////////////////////////// + // + // TIMER0 + // + ///////////////////////////////////////////////////////////////////// + wire [7:0] s_timer0_status; + wire [N_TIMEREXTSIG - 1:0] s_timer0_signal; + + assign s_timer0_signal = {ch_3_o, ch_2_o, ch_1_o, ch_0_o, ext_sig_i}; + + e203_clkgate i_clk_gate_timer0( + + .clk_in (HCLK ), + .clock_en (s_timer0_clk_en), + .test_mode(dft_cg_enable_i), + .clk_out (s_clk_timer0 ) + + ); + + timer_module #( + .NUM_BITS ( TIMER_NBITS ), + .N_EXTSIG ( N_TIMEREXTSIG ) + ) u_tim0 ( + .clk_i ( s_clk_timer0 ), + .rstn_i ( HRESETn ), + + .cfg_start_i ( s_timer0_apb_start ), + .cfg_stop_i ( s_timer0_apb_stop ), + .cfg_rst_i ( s_timer0_apb_rst ), + .cfg_update_i ( s_timer0_apb_update ), + .cfg_arm_i ( s_timer0_apb_arm ), + + .cfg_sel_i ( s_timer0_apb_in_sel ), + .cfg_sel_clk_i ( s_timer0_apb_in_clk ), + .cfg_mode_i ( s_timer0_apb_in_mode ), + + .cfg_presc_i ( s_timer0_apb_presc ), + + .cfg_sawtooth_i ( s_timer0_apb_saw ), + .cfg_cnt_start_i ( s_timer0_apb_th_low ), + .cfg_cnt_end_i ( s_timer0_apb_th_hi ), + + .cfg_comp_ch0_i ( s_timer0_apb_ch0_th ), + .cfg_comp_op_ch0_i( s_timer0_apb_ch0_mode ), + .cfg_comp_ch1_i ( s_timer0_apb_ch1_th ), + .cfg_comp_op_ch1_i( s_timer0_apb_ch1_mode ), + .cfg_comp_ch2_i ( s_timer0_apb_ch2_th ), + .cfg_comp_op_ch2_i( s_timer0_apb_ch2_mode ), + .cfg_comp_ch3_i ( s_timer0_apb_ch3_th ), + .cfg_comp_op_ch3_i( s_timer0_apb_ch3_mode ), + + .ls_clk_i ( low_speed_clk_i ), + .signal_i ( s_timer0_signal ), + + .counter_o ( s_timer0_counter ), + + .pwm_o ( ch_0_o ), + .status_o ( s_timer0_status ) + ); + + + ///////////////////////////////////////////////////////////////////// + // + // TIMER1 + // + ///////////////////////////////////////////////////////////////////// + wire [7:0] s_timer1_status; + wire [N_TIMEREXTSIG - 1:0] s_timer1_signal; + + assign s_timer1_signal = {ch_3_o, ch_2_o, ch_1_o, ch_0_o, ext_sig_i}; + + e203_clkgate i_clk_gate_timer1( + + .clk_in (HCLK ), + .clock_en (s_timer1_clk_en), + .test_mode(dft_cg_enable_i), + .clk_out (s_clk_timer1 ) + + ); + + timer_module #( + .NUM_BITS ( TIMER_NBITS ), + .N_EXTSIG ( N_TIMEREXTSIG ) + ) u_tim1 ( + .clk_i ( s_clk_timer1 ), + .rstn_i ( HRESETn ), + + .cfg_start_i ( s_timer1_apb_start ), + .cfg_stop_i ( s_timer1_apb_stop ), + .cfg_rst_i ( s_timer1_apb_rst ), + .cfg_update_i ( s_timer1_apb_update ), + .cfg_arm_i ( s_timer1_apb_arm ), + + .cfg_sel_i ( s_timer1_apb_in_sel ), + .cfg_sel_clk_i ( s_timer1_apb_in_clk ), + .cfg_mode_i ( s_timer1_apb_in_mode ), + + .cfg_presc_i ( s_timer1_apb_presc ), + + .cfg_sawtooth_i ( s_timer1_apb_saw ), + .cfg_cnt_start_i ( s_timer1_apb_th_low ), + .cfg_cnt_end_i ( s_timer1_apb_th_hi ), + + .cfg_comp_ch0_i ( s_timer1_apb_ch0_th ), + .cfg_comp_op_ch0_i( s_timer1_apb_ch0_mode ), + .cfg_comp_ch1_i ( s_timer1_apb_ch1_th ), + .cfg_comp_op_ch1_i( s_timer1_apb_ch1_mode ), + .cfg_comp_ch2_i ( s_timer1_apb_ch2_th ), + .cfg_comp_op_ch2_i( s_timer1_apb_ch2_mode ), + .cfg_comp_ch3_i ( s_timer1_apb_ch3_th ), + .cfg_comp_op_ch3_i( s_timer1_apb_ch3_mode ), + + .ls_clk_i ( low_speed_clk_i ), + .signal_i ( s_timer1_signal ), + + .counter_o ( s_timer1_counter ), + + .pwm_o ( ch_1_o ), + .status_o ( s_timer1_status ) + ); + + + ///////////////////////////////////////////////////////////////////// + // + // TIMER2 + // + ///////////////////////////////////////////////////////////////////// + wire [7:0] s_timer2_status; + wire [N_TIMEREXTSIG - 1:0] s_timer2_signal; + + assign s_timer2_signal = {ch_3_o, ch_2_o, ch_1_o, ch_0_o, ext_sig_i}; + + e203_clkgate i_clk_gate_timer2( + + .clk_in (HCLK ), + .clock_en (s_timer2_clk_en), + .test_mode(dft_cg_enable_i), + .clk_out (s_clk_timer2 ) + + ); + + + timer_module #( + .NUM_BITS ( TIMER_NBITS ), + .N_EXTSIG ( N_TIMEREXTSIG ) + ) u_tim2 ( + .clk_i ( s_clk_timer2 ), + .rstn_i ( HRESETn ), + + .cfg_start_i ( s_timer2_apb_start ), + .cfg_stop_i ( s_timer2_apb_stop ), + .cfg_rst_i ( s_timer2_apb_rst ), + .cfg_update_i ( s_timer2_apb_update ), + .cfg_arm_i ( s_timer2_apb_arm ), + + .cfg_sel_i ( s_timer2_apb_in_sel ), + .cfg_sel_clk_i ( s_timer2_apb_in_clk ), + .cfg_mode_i ( s_timer2_apb_in_mode ), + + .cfg_presc_i ( s_timer2_apb_presc ), + + .cfg_sawtooth_i ( s_timer2_apb_saw ), + .cfg_cnt_start_i ( s_timer2_apb_th_low ), + .cfg_cnt_end_i ( s_timer2_apb_th_hi ), + + .cfg_comp_ch0_i ( s_timer2_apb_ch0_th ), + .cfg_comp_op_ch0_i( s_timer2_apb_ch0_mode ), + .cfg_comp_ch1_i ( s_timer2_apb_ch1_th ), + .cfg_comp_op_ch1_i( s_timer2_apb_ch1_mode ), + .cfg_comp_ch2_i ( s_timer2_apb_ch2_th ), + .cfg_comp_op_ch2_i( s_timer2_apb_ch2_mode ), + .cfg_comp_ch3_i ( s_timer2_apb_ch3_th ), + .cfg_comp_op_ch3_i( s_timer2_apb_ch3_mode ), + + .ls_clk_i ( low_speed_clk_i ), + .signal_i ( s_timer2_signal ), + + .counter_o ( s_timer2_counter ), + + .pwm_o ( ch_2_o ), + .status_o ( s_timer2_status ) + ); + + + ///////////////////////////////////////////////////////////////////// + // + // TIMER3 + // + ///////////////////////////////////////////////////////////////////// + wire [7:0] s_timer3_status; + wire [N_TIMEREXTSIG - 1:0] s_timer3_signal; + + assign s_timer3_signal = {ch_3_o, ch_2_o, ch_1_o, ch_0_o, ext_sig_i}; + + e203_clkgate i_clk_gate_timer3( + + .clk_in (HCLK ), + .clock_en (s_timer3_clk_en), + .test_mode(dft_cg_enable_i), + .clk_out (s_clk_timer3 ) + + ); + + + timer_module #( + .NUM_BITS ( TIMER_NBITS ), + .N_EXTSIG ( N_TIMEREXTSIG ) + ) u_tim3 ( + .clk_i ( s_clk_timer3 ), + .rstn_i ( HRESETn ), + + .cfg_start_i ( s_timer3_apb_start ), + .cfg_stop_i ( s_timer3_apb_stop ), + .cfg_rst_i ( s_timer3_apb_rst ), + .cfg_update_i ( s_timer3_apb_update ), + .cfg_arm_i ( s_timer3_apb_arm ), + + .cfg_sel_i ( s_timer3_apb_in_sel ), + .cfg_sel_clk_i ( s_timer3_apb_in_clk ), + .cfg_mode_i ( s_timer3_apb_in_mode ), + + .cfg_presc_i ( s_timer3_apb_presc ), + + .cfg_sawtooth_i ( s_timer3_apb_saw ), + .cfg_cnt_start_i ( s_timer3_apb_th_low ), + .cfg_cnt_end_i ( s_timer3_apb_th_hi ), + + .cfg_comp_ch0_i ( s_timer3_apb_ch0_th ), + .cfg_comp_op_ch0_i( s_timer3_apb_ch0_mode ), + .cfg_comp_ch1_i ( s_timer3_apb_ch1_th ), + .cfg_comp_op_ch1_i( s_timer3_apb_ch1_mode ), + .cfg_comp_ch2_i ( s_timer3_apb_ch2_th ), + .cfg_comp_op_ch2_i( s_timer3_apb_ch2_mode ), + .cfg_comp_ch3_i ( s_timer3_apb_ch3_th ), + .cfg_comp_op_ch3_i( s_timer3_apb_ch3_mode ), + + .ls_clk_i ( low_speed_clk_i ), + .signal_i ( s_timer3_signal ), + + .counter_o ( s_timer3_counter ), + + .pwm_o ( ch_3_o ), + .status_o ( s_timer3_status ) + ); + + + wire [15:0] s_event_signals; + reg [1:0] r_event_sync_0; + reg [1:0] r_event_sync_1; + reg [1:0] r_event_sync_2; + reg [1:0] r_event_sync_3; + + assign s_event_signals = {ch_3_o, ch_2_o, ch_1_o, ch_0_o}; + + assign events_o[0] = (s_event_en[0] & r_event_sync_0[1]) & ~r_event_sync_0[0]; + assign events_o[1] = (s_event_en[1] & r_event_sync_1[1]) & ~r_event_sync_1[0]; + assign events_o[2] = (s_event_en[2] & r_event_sync_2[1]) & ~r_event_sync_2[0]; + assign events_o[3] = (s_event_en[3] & r_event_sync_3[1]) & ~r_event_sync_3[0]; + + always @(posedge HCLK or negedge HRESETn) begin : proc_edgedet + if (~HRESETn) begin + r_event_sync_0 <= 0; + r_event_sync_1 <= 0; + r_event_sync_2 <= 0; + r_event_sync_3 <= 0; + end else begin + if (s_event_en[0]) r_event_sync_0 <= {s_event_signals[s_event_sel_0], r_event_sync_0[1]}; + if (s_event_en[1]) r_event_sync_1 <= {s_event_signals[s_event_sel_1], r_event_sync_1[1]}; + if (s_event_en[2]) r_event_sync_2 <= {s_event_signals[s_event_sel_2], r_event_sync_2[1]}; + if (s_event_en[3]) r_event_sync_3 <= {s_event_signals[s_event_sel_3], r_event_sync_3[1]}; + end + end + +endmodule diff --git a/rtl/e203/perips/apb_adv_timer/comparator.sv b/rtl/e203/perips/apb_adv_timer/comparator.sv deleted file mode 100644 index 41edbe7..0000000 --- a/rtl/e203/perips/apb_adv_timer/comparator.sv +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -`define OP_SET 3'b000 -`define OP_TOGRST 3'b001 -`define OP_SETRST 3'b010 -`define OP_TOG 3'b011 -`define OP_RST 3'b100 -`define OP_TOGSET 3'b101 -`define OP_RSTSET 3'b110 - - - - -module comparator #( - parameter NUM_BITS = 16 -) ( - input logic clk_i, - input logic rstn_i, - - input logic ctrl_active_i, - input logic ctrl_update_i, - input logic ctrl_rst_i, - - input logic [NUM_BITS-1:0] cfg_comp_i, - input logic [2:0] cfg_comp_op_i, - - input logic timer_end_i, - input logic timer_valid_i, - input logic timer_sawtooth_i, - input logic [NUM_BITS-1:0] timer_count_i, - - output logic result_o - -); - logic [NUM_BITS-1:0] r_comp; - logic [2:0] r_comp_op; - - logic r_value; - logic r_active; - logic r_is_2nd_event; - - logic s_match; - logic s_2nd_event; - - assign s_match = timer_valid_i & (r_comp == timer_count_i); - - assign s_2nd_event = timer_sawtooth_i ? timer_end_i : s_match; - - assign result_o = r_value; - - always_ff @(posedge clk_i or negedge rstn_i) begin : proc_r_comp - if(~rstn_i) begin - r_comp <= 0; - r_comp_op <= 0; - end else begin - if (ctrl_update_i) //if first enable or explicit update is iven - begin - r_comp <= cfg_comp_i; - r_comp_op <= cfg_comp_op_i; - end - end - end - - always_ff @(posedge clk_i or negedge rstn_i) begin : proc_r_value - if(~rstn_i) begin - r_value <= 0; - r_is_2nd_event <= 1'b0; - end else begin - if (ctrl_rst_i) - begin - r_value <= 1'b0; - r_is_2nd_event <= 1'b0; - end - else if (timer_valid_i && ctrl_active_i) - begin - case(r_comp_op) - `OP_SET: - r_value <= s_match ? 1'b1 : r_value; - `OP_TOGRST: - begin - if(timer_sawtooth_i) - begin - if(s_match) - r_value <= ~r_value; - else if(s_2nd_event) - r_value <= 1'b0; - end - else - begin - if(s_match && !r_is_2nd_event) - begin - r_value <= ~r_value; - r_is_2nd_event <= 1'b1; - end - else if(s_match && r_is_2nd_event) - begin - r_value <= 1'b0; - r_is_2nd_event <= 1'b0; - end - end - end - `OP_SETRST: - begin - if(timer_sawtooth_i) - begin - if(s_match) - r_value <= 1'b1; - else if(s_2nd_event) - r_value <= 1'b0; - end - else - begin - if(s_match && !r_is_2nd_event) - begin - r_value <= 1'b1; - r_is_2nd_event <= 1'b1; - end - else if(s_match && r_is_2nd_event) - begin - r_value <= 1'b0; - r_is_2nd_event <= 1'b0; - end - end - end - `OP_TOG: - r_value <= s_match ? ~r_value : r_value; - `OP_RST: - r_value <= s_match ? 1'b0 : r_value; - `OP_TOGSET: - begin - if(timer_sawtooth_i) - begin - if(s_match) - r_value <= ~r_value; - else if(s_2nd_event) - r_value <= 1'b1; - end - else - begin - if(s_match && !r_is_2nd_event) - begin - r_value <= ~r_value; - r_is_2nd_event <= 1'b1; - end - else if(s_match && r_is_2nd_event) - begin - r_value <= 1'b1; - r_is_2nd_event <= 1'b0; - end - end - end - `OP_RSTSET: - begin - if(timer_sawtooth_i) - begin - if(s_match) - r_value <= 1'b0; - else if(s_2nd_event) - r_value <= 1'b1; - end - else - begin - if(s_match && !r_is_2nd_event) - begin - r_value <= 1'b0; - r_is_2nd_event <= 1'b1; - end - else if(s_match && r_is_2nd_event) - begin - r_value <= 1'b1; - r_is_2nd_event <= 1'b0; - end - end - end - default: - begin - r_value <= r_value; - r_is_2nd_event <= 1'b0; - end - endcase // r_comp_op - end - end - end - - -endmodule // comparator diff --git a/rtl/e203/perips/apb_adv_timer/comparator.v b/rtl/e203/perips/apb_adv_timer/comparator.v new file mode 100644 index 0000000..18aa28d --- /dev/null +++ b/rtl/e203/perips/apb_adv_timer/comparator.v @@ -0,0 +1,153 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +`define OP_SET 3'b000 +`define OP_TOGRST 3'b001 +`define OP_SETRST 3'b010 +`define OP_TOG 3'b011 +`define OP_RST 3'b100 +`define OP_TOGSET 3'b101 +`define OP_RSTSET 3'b110 + + +module comparator #( + parameter NUM_BITS = 16 +) ( + input wire clk_i, + input wire rstn_i, + input wire ctrl_active_i, + input wire ctrl_update_i, + input wire ctrl_rst_i, + input wire [NUM_BITS - 1:0] cfg_comp_i, + input wire [2:0] cfg_comp_op_i, + input wire timer_end_i, + input wire timer_valid_i, + input wire timer_sawtooth_i, + input wire [NUM_BITS - 1:0] timer_count_i, + output wire result_o +); + + reg [NUM_BITS - 1:0] r_comp; + reg [2:0] r_comp_op; + + reg r_value; + wire r_active; + reg r_is_2nd_event; + + wire s_match; + wire s_2nd_event; + + assign s_match = timer_valid_i & (r_comp == timer_count_i); + assign s_2nd_event = timer_sawtooth_i ? timer_end_i : s_match; + assign result_o = r_value; + + always @(posedge clk_i or negedge rstn_i) begin : proc_r_comp + if (~rstn_i) begin + r_comp <= 0; + r_comp_op <= 0; + end else if (ctrl_update_i) begin //if first enable or explicit update is iven + r_comp <= cfg_comp_i; + r_comp_op <= cfg_comp_op_i; + end + end + + always @(posedge clk_i or negedge rstn_i) begin : proc_r_value + if (~rstn_i) begin + r_value <= 0; + r_is_2nd_event <= 1'b0; + end else if (ctrl_rst_i) begin + r_value <= 1'b0; + r_is_2nd_event <= 1'b0; + end else if (timer_valid_i && ctrl_active_i) begin + case(r_comp_op) + `OP_SET: + r_value <= s_match ? 1'b1 : r_value; + `OP_TOGRST: + begin + if(timer_sawtooth_i) begin + if(s_match) + r_value <= ~r_value; + else if(s_2nd_event) + r_value <= 1'b0; + end else begin + if(s_match && !r_is_2nd_event) begin + r_value <= ~r_value; + r_is_2nd_event <= 1'b1; + end else if(s_match && r_is_2nd_event) begin + r_value <= 1'b0; + r_is_2nd_event <= 1'b0; + end + end + end + `OP_SETRST: + begin + if(timer_sawtooth_i) begin + if(s_match) + r_value <= 1'b1; + else if(s_2nd_event) + r_value <= 1'b0; + end else begin + if(s_match && !r_is_2nd_event) begin + r_value <= 1'b1; + r_is_2nd_event <= 1'b1; + end else if(s_match && r_is_2nd_event) begin + r_value <= 1'b0; + r_is_2nd_event <= 1'b0; + end + end + end + `OP_TOG: + r_value <= s_match ? ~r_value : r_value; + `OP_RST: + r_value <= s_match ? 1'b0 : r_value; + `OP_TOGSET: + begin + if(timer_sawtooth_i) begin + if(s_match) + r_value <= ~r_value; + else if(s_2nd_event) + r_value <= 1'b1; + end else begin + if(s_match && !r_is_2nd_event) begin + r_value <= ~r_value; + r_is_2nd_event <= 1'b1; + end else if(s_match && r_is_2nd_event) begin + r_value <= 1'b1; + r_is_2nd_event <= 1'b0; + end + end + end + `OP_RSTSET: + begin + if(timer_sawtooth_i) begin + if(s_match) + r_value <= 1'b0; + else if(s_2nd_event) + r_value <= 1'b1; + end else begin + if(s_match && !r_is_2nd_event) begin + r_value <= 1'b0; + r_is_2nd_event <= 1'b1; + end else if(s_match && r_is_2nd_event) begin + r_value <= 1'b1; + r_is_2nd_event <= 1'b0; + end + end + end + default: + begin + r_value <= r_value; + r_is_2nd_event <= 1'b0; + end + endcase // r_comp_op + end + end +endmodule diff --git a/rtl/e203/perips/apb_adv_timer/input_stage.sv b/rtl/e203/perips/apb_adv_timer/input_stage.sv deleted file mode 100644 index cbaf0df..0000000 --- a/rtl/e203/perips/apb_adv_timer/input_stage.sv +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module input_stage #( - parameter EXTSIG_NUM = 32 -) ( - input logic clk_i, - input logic rstn_i, - - input logic ctrl_active_i, - input logic ctrl_update_i, - - input logic ctrl_arm_i, - - input logic cnt_end_i, - - input logic [7:0] cfg_sel_i, - input logic cfg_sel_clk_i, - input logic [2:0] cfg_mode_i, - - input logic ls_clk_i, - input logic [EXTSIG_NUM-1:0] signal_i, - output logic event_o - -); - - logic s_rise; - logic s_rise_ls_clk; - logic s_fall; - logic s_int_evnt; - logic s_event; - - logic r_active; - logic r_event; - logic r_oldval; - logic s_int_sig; - logic [7:0] r_sel; - logic [2:0] r_mode; - logic r_armed; - logic [2:0] r_ls_clk_sync; - - - assign s_rise = ~r_oldval & s_int_sig; - assign s_fall = r_oldval & ~s_int_sig; - assign s_rise_ls_clk = ~r_ls_clk_sync[2] & r_ls_clk_sync[1]; - - always_ff @(posedge clk_i or negedge rstn_i) begin : proc_r_ls_clk_sync - if(~rstn_i) begin - r_ls_clk_sync <= 'h0; - end else begin - r_ls_clk_sync <= {r_ls_clk_sync[1:0],ls_clk_i}; - end - end - - always_ff @(posedge clk_i or negedge rstn_i) begin : proc_r_mode - if(~rstn_i) begin - r_mode <= 0; - r_sel <= 0; - end else begin - if (ctrl_update_i) - begin - r_mode <= cfg_mode_i; - r_sel <= cfg_sel_i; - end - end - end - - always_comb begin : proc_event_o - if(cfg_sel_clk_i) - event_o = s_int_evnt & s_rise_ls_clk; - else - event_o = s_int_evnt; - end - - always_comb begin : proc_s_int_evnt - case (r_mode) - 3'b000: - s_int_evnt = 1'b1; - 3'b001: - s_int_evnt = ~s_int_sig; - 3'b010: - s_int_evnt = s_int_sig; - 3'b011: - s_int_evnt = s_rise; - 3'b100: - s_int_evnt = s_fall; - 3'b101: - s_int_evnt = s_rise | s_fall; - 3'b110: - begin - if(r_armed) - s_int_evnt = s_rise ? 1'b1 : r_event; - else - s_int_evnt = 1'b0; - end - 3'b111: - begin - if(r_armed) - s_int_evnt = s_fall ? 1'b1 : r_event; - else - s_int_evnt = 1'b0; - end - endcase // cfg_mode_i - end - - - always_comb begin : proc_int_sig - s_int_sig = 0; - for (int i=0;i s_th_rx); - + assign events_o = s_rise_int_tx | s_rise_int_rx; assign s_int_status = {s_rise_int_rx, s_rise_int_tx}; - - always_comb - begin + + always @(*) begin spi_oe0 = 1'b0; spi_oe1 = 1'b0; spi_oe2 = 1'b0; spi_oe3 = 1'b0; - case(spi_mode) - `SPI_STD: - begin - spi_oe0 = 1'b1; - spi_oe1 = 1'b0; - spi_oe2 = 1'b0; - spi_oe3 = 1'b0; - end - - `SPI_QUAD_TX: - begin - spi_oe0 = 1'b1; - spi_oe1 = 1'b1; - spi_oe2 = 1'b1; - spi_oe3 = 1'b1; - end - - `SPI_QUAD_RX : - begin - spi_oe0 = 1'b0; - spi_oe1 = 1'b0; - spi_oe2 = 1'b0; - spi_oe3 = 1'b0; - end + case (spi_mode) + `SPI_STD: begin + spi_oe0 = 1'b1; + spi_oe1 = 1'b0; + spi_oe2 = 1'b0; + spi_oe3 = 1'b0; + end + `SPI_QUAD_TX: begin + spi_oe0 = 1'b1; + spi_oe1 = 1'b1; + spi_oe2 = 1'b1; + spi_oe3 = 1'b1; + end + `SPI_QUAD_RX: begin + spi_oe0 = 1'b0; + spi_oe1 = 1'b0; + spi_oe2 = 1'b0; + spi_oe3 = 1'b0; + end endcase end diff --git a/rtl/e203/perips/apb_spi_master/spi_master_apb_if.sv b/rtl/e203/perips/apb_spi_master/spi_master_apb_if.sv deleted file mode 100644 index 6a5a482..0000000 --- a/rtl/e203/perips/apb_spi_master/spi_master_apb_if.sv +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// -- Adaptable modifications made for hbirdv2 SoC. -- -// Copyright 2020 Nuclei System Technology, Inc. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -`define log2(VALUE) ((VALUE) < ( 1 ) ? 0 : (VALUE) < ( 2 ) ? 1 : (VALUE) < ( 4 ) ? 2 : (VALUE) < ( 8 ) ? 3 : (VALUE) < ( 16 ) ? 4 : (VALUE) < ( 32 ) ? 5 : (VALUE) < ( 64 ) ? 6 : (VALUE) < ( 128 ) ? 7 : (VALUE) < ( 256 ) ? 8 : (VALUE) < ( 512 ) ? 9 : (VALUE) < ( 1024 ) ? 10 : (VALUE) < ( 2048 ) ? 11 : (VALUE) < ( 4096 ) ? 12 : (VALUE) < ( 8192 ) ? 13 : (VALUE) < ( 16384 ) ? 14 : (VALUE) < ( 32768 ) ? 15 : (VALUE) < ( 65536 ) ? 16 : (VALUE) < ( 131072 ) ? 17 : (VALUE) < ( 262144 ) ? 18 : (VALUE) < ( 524288 ) ? 19 : (VALUE) < ( 1048576 ) ? 20 : (VALUE) < ( 1048576 * 2 ) ? 21 : (VALUE) < ( 1048576 * 4 ) ? 22 : (VALUE) < ( 1048576 * 8 ) ? 23 : (VALUE) < ( 1048576 * 16 ) ? 24 : 25) - -`define REG_STATUS 4'b0000 // BASEREG + 0x00 -`define REG_CLKDIV 4'b0001 // BASEREG + 0x04 -`define REG_SPICMD 4'b0010 // BASEREG + 0x08 -`define REG_SPIADR 4'b0011 // BASEREG + 0x0C -`define REG_SPILEN 4'b0100 // BASEREG + 0x10 -`define REG_SPIDUM 4'b0101 // BASEREG + 0x14 -`define REG_TXFIFO 4'b0110 // BASEREG + 0x18 -`define REG_RXFIFO 4'b1000 // BASEREG + 0x20 -`define REG_INTCFG 4'b1001 // BASEREG + 0x24 -`define REG_INTSTA 4'b1010 // BASEREG + 0x28 - -module spi_master_apb_if -#( - parameter BUFFER_DEPTH = 10, - parameter APB_ADDR_WIDTH = 12, //APB slaves are 4KB by default - parameter LOG_BUFFER_DEPTH = `log2(BUFFER_DEPTH) -) -( - input logic HCLK, - input logic HRESETn, - input logic [APB_ADDR_WIDTH-1:0] PADDR, - input logic [31:0] PWDATA, - input logic PWRITE, - input logic PSEL, - input logic PENABLE, - output logic [31:0] PRDATA, - output logic PREADY, - output logic PSLVERR, - - output logic [7:0] spi_clk_div, - output logic spi_clk_div_valid, - input logic [31:0] spi_status, - output logic [31:0] spi_addr, - output logic [5:0] spi_addr_len, - output logic [31:0] spi_cmd, - output logic [5:0] spi_cmd_len, - output logic [3:0] spi_csreg, - output logic [15:0] spi_data_len, - output logic [15:0] spi_dummy_rd, - output logic [15:0] spi_dummy_wr, - output logic [LOG_BUFFER_DEPTH:0] spi_int_th_tx, - output logic [LOG_BUFFER_DEPTH:0] spi_int_th_rx, - output logic spi_int_en, - input logic [31:0] spi_int_status, - output logic spi_swrst, - output logic spi_rd, - output logic spi_wr, - output logic spi_qrd, - output logic spi_qwr, - output logic [31:0] spi_data_tx, - output logic spi_data_tx_valid, - input logic spi_data_tx_ready, - input logic [31:0] spi_data_rx, - input logic spi_data_rx_valid, - output logic spi_data_rx_ready -); - - logic [3:0] write_address; - logic [3:0] read_address; - - assign write_address = PADDR[5:2]; - assign read_address = PADDR[5:2]; - - assign PSLVERR = 1'b0; - assign PREADY = 1'b1; - - always @( posedge HCLK or negedge HRESETn ) - begin - if ( HRESETn == 1'b0 ) - begin - spi_swrst <= 1'b0; - spi_rd <= 1'b0; - spi_wr <= 1'b0; - spi_qrd <= 1'b0; - spi_qwr <= 1'b0; - spi_clk_div_valid <= 1'b0; - spi_clk_div <= '0; - spi_cmd <= '0; - spi_addr <= '0; - spi_cmd_len <= '0; - spi_addr_len <= '0; - spi_data_len <= '0; - spi_dummy_rd <= '0; - spi_dummy_wr <= '0; - spi_csreg <= '0; - spi_int_th_tx <= '0; - spi_int_th_rx <= '0; - spi_int_en <= 1'b0; - end - else if (PSEL && PENABLE && PWRITE) - begin - spi_swrst <= 1'b0; - spi_rd <= 1'b0; - spi_wr <= 1'b0; - spi_qrd <= 1'b0; - spi_qwr <= 1'b0; - spi_clk_div_valid <= 1'b0; - - case(write_address) - - `REG_STATUS: - begin - spi_rd <= PWDATA[0]; - spi_wr <= PWDATA[1]; - spi_qrd <= PWDATA[2]; - spi_qwr <= PWDATA[3]; - spi_swrst <= PWDATA[4]; - spi_csreg <= PWDATA[11:8]; - end - - `REG_CLKDIV: - begin - spi_clk_div <= PWDATA[7:0]; - spi_clk_div_valid <= 1'b1; - end - - `REG_SPICMD: - spi_cmd <= PWDATA; - - `REG_SPIADR: - spi_addr <= PWDATA; - - `REG_SPILEN: - begin - spi_cmd_len <= PWDATA[5:0]; - spi_addr_len <= PWDATA[13:8]; - spi_data_len[7:0] <= PWDATA[23:16]; - spi_data_len[15:8] <= PWDATA[31:24]; - end - - `REG_SPIDUM: - begin - spi_dummy_rd[7:0] <= PWDATA[7:0]; - spi_dummy_rd[15:8] <= PWDATA[15:8]; - spi_dummy_wr[7:0] <= PWDATA[23:16]; - spi_dummy_wr[15:8] <= PWDATA[31:24]; - end - - `REG_INTCFG: - begin - spi_int_th_tx <= PWDATA[ LOG_BUFFER_DEPTH: 0]; - spi_int_th_rx <= PWDATA[ 8 + LOG_BUFFER_DEPTH: 8]; - spi_int_en <= PWDATA[31]; - end - endcase - end - else - begin - spi_swrst <= 1'b0; - spi_rd <= 1'b0; - spi_wr <= 1'b0; - spi_qrd <= 1'b0; - spi_qwr <= 1'b0; - spi_clk_div_valid <= 1'b0; - end - end // SLAVE_REG_WRITE_PROC - - - // implement slave model register read mux - always_comb - begin - case(read_address) - `REG_STATUS: - PRDATA = spi_status; - `REG_CLKDIV: - PRDATA = {24'h00_0000,spi_clk_div}; - `REG_SPICMD: - PRDATA = spi_cmd; - `REG_SPIADR: - PRDATA = spi_addr; - `REG_SPILEN: - PRDATA = {spi_data_len,2'b00,spi_addr_len,2'b00,spi_cmd_len}; - `REG_SPIDUM: - PRDATA = {spi_dummy_wr,spi_dummy_rd}; - `REG_RXFIFO: - PRDATA = spi_data_rx; - `REG_INTCFG: - begin - PRDATA = '0; - PRDATA[ LOG_BUFFER_DEPTH: 0] = spi_int_th_tx; - PRDATA[ 8 + LOG_BUFFER_DEPTH: 8] = spi_int_th_rx; - PRDATA[31] = spi_int_en; - end - `REG_INTSTA: - PRDATA = spi_int_status; - default: - PRDATA = '0; - endcase - end // SLAVE_REG_READ_PROC - - assign spi_data_tx = PWDATA; - assign spi_data_tx_valid = PSEL & PENABLE & PWRITE & (write_address == `REG_TXFIFO); - assign spi_data_rx_ready = PSEL & PENABLE & ~PWRITE & (read_address == `REG_RXFIFO); - -endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_apb_if.v b/rtl/e203/perips/apb_spi_master/spi_master_apb_if.v new file mode 100644 index 0000000..adae1d5 --- /dev/null +++ b/rtl/e203/perips/apb_spi_master/spi_master_apb_if.v @@ -0,0 +1,179 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +`define log2(VALUE) ((VALUE) < ( 1 ) ? 0 : (VALUE) < ( 2 ) ? 1 : (VALUE) < ( 4 ) ? 2 : (VALUE) < ( 8 ) ? 3 : (VALUE) < ( 16 ) ? 4 : (VALUE) < ( 32 ) ? 5 : (VALUE) < ( 64 ) ? 6 : (VALUE) < ( 128 ) ? 7 : (VALUE) < ( 256 ) ? 8 : (VALUE) < ( 512 ) ? 9 : (VALUE) < ( 1024 ) ? 10 : (VALUE) < ( 2048 ) ? 11 : (VALUE) < ( 4096 ) ? 12 : (VALUE) < ( 8192 ) ? 13 : (VALUE) < ( 16384 ) ? 14 : (VALUE) < ( 32768 ) ? 15 : (VALUE) < ( 65536 ) ? 16 : (VALUE) < ( 131072 ) ? 17 : (VALUE) < ( 262144 ) ? 18 : (VALUE) < ( 524288 ) ? 19 : (VALUE) < ( 1048576 ) ? 20 : (VALUE) < ( 1048576 * 2 ) ? 21 : (VALUE) < ( 1048576 * 4 ) ? 22 : (VALUE) < ( 1048576 * 8 ) ? 23 : (VALUE) < ( 1048576 * 16 ) ? 24 : 25) + +`define REG_STATUS 4'b0000 // BASEREG + 0x00 +`define REG_CLKDIV 4'b0001 // BASEREG + 0x04 +`define REG_SPICMD 4'b0010 // BASEREG + 0x08 +`define REG_SPIADR 4'b0011 // BASEREG + 0x0C +`define REG_SPILEN 4'b0100 // BASEREG + 0x10 +`define REG_SPIDUM 4'b0101 // BASEREG + 0x14 +`define REG_TXFIFO 4'b0110 // BASEREG + 0x18 +`define REG_RXFIFO 4'b1000 // BASEREG + 0x20 +`define REG_INTCFG 4'b1001 // BASEREG + 0x24 +`define REG_INTSTA 4'b1010 // BASEREG + 0x28 + +module spi_master_apb_if +#( + parameter BUFFER_DEPTH = 10, + parameter APB_ADDR_WIDTH = 12, //APB slaves are 4KB by default + parameter LOG_BUFFER_DEPTH = `log2(BUFFER_DEPTH) +) +( + input wire HCLK, + input wire HRESETn, + input wire [APB_ADDR_WIDTH - 1:0] PADDR, + input wire [31:0] PWDATA, + input wire PWRITE, + input wire PSEL, + input wire PENABLE, + output reg [31:0] PRDATA, + output wire PREADY, + output wire PSLVERR, + + output reg [7:0] spi_clk_div, + output reg spi_clk_div_valid, + input wire [31:0] spi_status, + output reg [31:0] spi_addr, + output reg [5:0] spi_addr_len, + output reg [31:0] spi_cmd, + output reg [5:0] spi_cmd_len, + output reg [3:0] spi_csreg, + output reg [15:0] spi_data_len, + output reg [15:0] spi_dummy_rd, + output reg [15:0] spi_dummy_wr, + output reg [LOG_BUFFER_DEPTH:0] spi_int_th_tx, + output reg [LOG_BUFFER_DEPTH:0] spi_int_th_rx, + output reg spi_int_en, + input wire [31:0] spi_int_status, + output reg spi_swrst, + output reg spi_rd, + output reg spi_wr, + output reg spi_qrd, + output reg spi_qwr, + output wire [31:0] spi_data_tx, + output wire spi_data_tx_valid, + input wire spi_data_tx_ready, + input wire [31:0] spi_data_rx, + input wire spi_data_rx_valid, + output wire spi_data_rx_ready +); + + wire [3:0] write_address; + wire [3:0] read_address; + + assign write_address = PADDR[5:2]; + assign read_address = PADDR[5:2]; + + assign PSLVERR = 1'b0; + assign PREADY = 1'b1; + + always @(posedge HCLK or negedge HRESETn) begin + if (HRESETn == 1'b0) begin + spi_swrst <= 1'b0; + spi_rd <= 1'b0; + spi_wr <= 1'b0; + spi_qrd <= 1'b0; + spi_qwr <= 1'b0; + spi_clk_div_valid <= 1'b0; + spi_clk_div <= 'b0; + spi_cmd <= 'b0; + spi_addr <= 'b0; + spi_cmd_len <= 'b0; + spi_addr_len <= 'b0; + spi_data_len <= 'b0; + spi_dummy_rd <= 'b0; + spi_dummy_wr <= 'b0; + spi_csreg <= 'b0; + spi_int_th_tx <= 'b0; + spi_int_th_rx <= 'b0; + spi_int_en <= 1'b0; + end else if (PSEL && PENABLE && PWRITE) begin + spi_swrst <= 1'b0; + spi_rd <= 1'b0; + spi_wr <= 1'b0; + spi_qrd <= 1'b0; + spi_qwr <= 1'b0; + spi_clk_div_valid <= 1'b0; + + case (write_address) + `REG_STATUS: begin + spi_rd <= PWDATA[0]; + spi_wr <= PWDATA[1]; + spi_qrd <= PWDATA[2]; + spi_qwr <= PWDATA[3]; + spi_swrst <= PWDATA[4]; + spi_csreg <= PWDATA[11:8]; + end + `REG_CLKDIV: begin + spi_clk_div <= PWDATA[7:0]; + spi_clk_div_valid <= 1'b1; + end + `REG_SPICMD: spi_cmd <= PWDATA; + `REG_SPIADR: spi_addr <= PWDATA; + `REG_SPILEN: begin + spi_cmd_len <= PWDATA[5:0]; + spi_addr_len <= PWDATA[13:8]; + spi_data_len[7:0] <= PWDATA[23:16]; + spi_data_len[15:8] <= PWDATA[31:24]; + end + `REG_SPIDUM: begin + spi_dummy_rd[7:0] <= PWDATA[7:0]; + spi_dummy_rd[15:8] <= PWDATA[15:8]; + spi_dummy_wr[7:0] <= PWDATA[23:16]; + spi_dummy_wr[15:8] <= PWDATA[31:24]; + end + `REG_INTCFG: begin + spi_int_th_tx <= PWDATA[LOG_BUFFER_DEPTH:0]; + spi_int_th_rx <= PWDATA[8 + LOG_BUFFER_DEPTH:8]; + spi_int_en <= PWDATA[31]; + end + endcase + end else begin + spi_swrst <= 1'b0; + spi_rd <= 1'b0; + spi_wr <= 1'b0; + spi_qrd <= 1'b0; + spi_qwr <= 1'b0; + spi_clk_div_valid <= 1'b0; + end + end // SLAVE_REG_WRITE_PROC + + + // implement slave model register read mux + always @(*) begin + case (read_address) + `REG_STATUS: PRDATA = spi_status; + `REG_CLKDIV: PRDATA = {24'h0, spi_clk_div}; + `REG_SPICMD: PRDATA = spi_cmd; + `REG_SPIADR: PRDATA = spi_addr; + `REG_SPILEN: PRDATA = {spi_data_len, 2'b00, spi_addr_len, 2'b00, spi_cmd_len}; + `REG_SPIDUM: PRDATA = {spi_dummy_wr, spi_dummy_rd}; + `REG_RXFIFO: PRDATA = spi_data_rx; + `REG_INTCFG: begin + PRDATA = 'b0; + PRDATA[LOG_BUFFER_DEPTH:0] = spi_int_th_tx; + PRDATA[8 + LOG_BUFFER_DEPTH:8] = spi_int_th_rx; + PRDATA[31] = spi_int_en; + end + `REG_INTSTA: PRDATA = spi_int_status; + default: PRDATA = 'b0; + endcase + end // SLAVE_REG_READ_PROC + + assign spi_data_tx = PWDATA; + assign spi_data_tx_valid = ((PSEL & PENABLE) & PWRITE) & (write_address == `REG_TXFIFO); + assign spi_data_rx_ready = ((PSEL & PENABLE) & ~PWRITE) & (read_address == `REG_RXFIFO); + + +endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_clkgen.sv b/rtl/e203/perips/apb_spi_master/spi_master_clkgen.sv deleted file mode 100644 index 614b15b..0000000 --- a/rtl/e203/perips/apb_spi_master/spi_master_clkgen.sv +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module spi_master_clkgen -( - input logic clk, - input logic rstn, - input logic en, - input logic [7:0] clk_div, - input logic clk_div_valid, - output logic spi_clk, - output logic spi_fall, - output logic spi_rise -); - - logic [7:0] counter_trgt; - logic [7:0] counter_trgt_next; - logic [7:0] counter; - logic [7:0] counter_next; - - logic spi_clk_next; - logic running; - - always_comb - begin - spi_rise = 1'b0; - spi_fall = 1'b0; - if (clk_div_valid) - counter_trgt_next = clk_div; - else - counter_trgt_next = counter_trgt; - - if (counter == counter_trgt) - begin - counter_next = 0; - spi_clk_next = ~spi_clk; - if(spi_clk == 1'b0) - spi_rise = running; - else - spi_fall = running; - end - else - begin - counter_next = counter + 1; - spi_clk_next = spi_clk; - end - end - - always_ff @(posedge clk, negedge rstn) - begin - if (rstn == 1'b0) - begin - counter_trgt <= 'h0; - counter <= 'h0; - spi_clk <= 1'b0; - running <= 1'b0; - end - else - begin - counter_trgt <= counter_trgt_next; - if ( !((spi_clk==1'b0)&&(~en)) ) - begin - running <= 1'b1; - spi_clk <= spi_clk_next; - counter <= counter_next; - end - else - running <= 1'b0; - end - end - - - -endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_clkgen.v b/rtl/e203/perips/apb_spi_master/spi_master_clkgen.v new file mode 100644 index 0000000..3f68335 --- /dev/null +++ b/rtl/e203/perips/apb_spi_master/spi_master_clkgen.v @@ -0,0 +1,75 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module spi_master_clkgen ( + input wire clk, + input wire rstn, + input wire en, + input wire [7:0] clk_div, + input wire clk_div_valid, + output reg spi_clk, + output reg spi_fall, + output reg spi_rise +); + + reg [7:0] counter_trgt; + reg [7:0] counter_trgt_next; + reg [7:0] counter; + reg [7:0] counter_next; + + reg spi_clk_next; + reg running; + + always @(*) begin + spi_rise = 1'b0; + spi_fall = 1'b0; + + if (clk_div_valid) + counter_trgt_next = clk_div; + else + counter_trgt_next = counter_trgt; + + if (counter == counter_trgt) begin + counter_next = 0; + spi_clk_next = ~spi_clk; + + if (spi_clk == 1'b0) + spi_rise = running; + else + spi_fall = running; + + end else begin + counter_next = counter + 1; + spi_clk_next = spi_clk; + end + end + + always @(posedge clk or negedge rstn) begin + if (rstn == 1'b0) begin + counter_trgt <= 'h0; + counter <= 'h0; + spi_clk <= 1'b0; + running <= 1'b0; + end else begin + counter_trgt <= counter_trgt_next; + + if (!((spi_clk == 1'b0) && ~en)) begin + running <= 1'b1; + spi_clk <= spi_clk_next; + counter <= counter_next; + end else + running <= 1'b0; + end + end + + +endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_controller.sv b/rtl/e203/perips/apb_spi_master/spi_master_controller.sv deleted file mode 100644 index 345761b..0000000 --- a/rtl/e203/perips/apb_spi_master/spi_master_controller.sv +++ /dev/null @@ -1,560 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -`define SPI_STD 2'b00 -`define SPI_QUAD_TX 2'b01 -`define SPI_QUAD_RX 2'b10 - -module spi_master_controller -( - input logic clk, - input logic rstn, - output logic eot, - input logic [7:0] spi_clk_div, - input logic spi_clk_div_valid, - output logic [6:0] spi_status, - input logic [31:0] spi_addr, - input logic [5:0] spi_addr_len, - input logic [31:0] spi_cmd, - input logic [5:0] spi_cmd_len, - input logic [15:0] spi_data_len, - input logic [15:0] spi_dummy_rd, - input logic [15:0] spi_dummy_wr, - input logic [3:0] spi_csreg, - input logic spi_swrst, //FIXME Not used at all - input logic spi_rd, - input logic spi_wr, - input logic spi_qrd, - input logic spi_qwr, - input logic [31:0] spi_ctrl_data_tx, - input logic spi_ctrl_data_tx_valid, - output logic spi_ctrl_data_tx_ready, - output logic [31:0] spi_ctrl_data_rx, - output logic spi_ctrl_data_rx_valid, - input logic spi_ctrl_data_rx_ready, - output logic spi_clk, - output logic spi_csn0, - output logic spi_csn1, - output logic spi_csn2, - output logic spi_csn3, - output logic [1:0] spi_mode, - output logic spi_sdo0, - output logic spi_sdo1, - output logic spi_sdo2, - output logic spi_sdo3, - input logic spi_sdi0, - input logic spi_sdi1, - input logic spi_sdi2, - input logic spi_sdi3 -); - - logic spi_rise; - logic spi_fall; - - logic spi_clock_en; - - logic spi_en_tx; - logic spi_en_rx; - - logic [15:0] counter_tx; - logic counter_tx_valid; - logic [15:0] counter_rx; - logic counter_rx_valid; - - logic [31:0] data_to_tx; - logic data_to_tx_valid; - logic data_to_tx_ready; - - logic en_quad; - logic en_quad_int; - logic do_tx; //FIXME NOT USED at all!! - logic do_rx; - - logic tx_done; - logic rx_done; - - logic [1:0] s_spi_mode; - - logic ctrl_data_valid; - - logic spi_cs; - - logic tx_clk_en; - logic rx_clk_en; - - enum logic [2:0] {DATA_NULL,DATA_EMPTY,DATA_CMD,DATA_ADDR,DATA_FIFO} ctrl_data_mux; - - enum logic [4:0] {IDLE,CMD,ADDR,MODE,DUMMY,DATA_TX,DATA_RX,WAIT_EDGE} state,state_next; - - assign en_quad = spi_qrd | spi_qwr | en_quad_int; - - spi_master_clkgen u_clkgen - ( - .clk ( clk ), - .rstn ( rstn ), - .en ( spi_clock_en ), - .clk_div ( spi_clk_div ), - .clk_div_valid ( spi_clk_div_valid ), - .spi_clk ( spi_clk ), - .spi_fall ( spi_fall ), - .spi_rise ( spi_rise ) - ); - - spi_master_tx u_txreg - ( - .clk ( clk ), - .rstn ( rstn ), - .en ( spi_en_tx ), - .tx_edge ( spi_fall ), - .tx_done ( tx_done ), - .sdo0 ( spi_sdo0 ), - .sdo1 ( spi_sdo1 ), - .sdo2 ( spi_sdo2 ), - .sdo3 ( spi_sdo3 ), - .en_quad_in ( en_quad ), - .counter_in ( counter_tx ), - .counter_in_upd ( counter_tx_valid ), - .data ( data_to_tx ), - .data_valid ( data_to_tx_valid ), - .data_ready ( data_to_tx_ready ), - .clk_en_o ( tx_clk_en ) - ); - - spi_master_rx u_rxreg - ( - .clk ( clk ), - .rstn ( rstn ), - .en ( spi_en_rx ), - .rx_edge ( spi_rise ), - .rx_done ( rx_done ), - .sdi0 ( spi_sdi0 ), - .sdi1 ( spi_sdi1 ), - .sdi2 ( spi_sdi2 ), - .sdi3 ( spi_sdi3 ), - .en_quad_in ( en_quad ), - .counter_in ( counter_rx ), - .counter_in_upd ( counter_rx_valid ), - .data ( spi_ctrl_data_rx ), - .data_valid ( spi_ctrl_data_rx_valid ), - .data_ready ( spi_ctrl_data_rx_ready ), - .clk_en_o ( rx_clk_en ) - ); - - always_comb - begin - data_to_tx = 'h0; - data_to_tx_valid = 1'b0; - spi_ctrl_data_tx_ready = 1'b0; - - case(ctrl_data_mux) - DATA_NULL: - begin - data_to_tx = '0; - data_to_tx_valid = 1'b0; - spi_ctrl_data_tx_ready = 1'b0; - end - - DATA_EMPTY: - begin - data_to_tx = '0; - data_to_tx_valid = 1'b1; - end - - DATA_CMD: - begin - data_to_tx = spi_cmd; - data_to_tx_valid = ctrl_data_valid; - spi_ctrl_data_tx_ready = 1'b0; - end - - DATA_ADDR: - begin - data_to_tx = spi_addr; - data_to_tx_valid = ctrl_data_valid; - spi_ctrl_data_tx_ready = 1'b0; - end - - DATA_FIFO: - begin - data_to_tx = spi_ctrl_data_tx; - data_to_tx_valid = spi_ctrl_data_tx_valid; - spi_ctrl_data_tx_ready = data_to_tx_ready; - end - endcase - end - - always_comb - begin - spi_cs = 1'b1; - spi_clock_en = 1'b0; - counter_tx = '0; - counter_tx_valid = 1'b0; - counter_rx = '0; - counter_rx_valid = 1'b0; - state_next = state; - ctrl_data_mux = DATA_NULL; - ctrl_data_valid = 1'b0; - spi_en_rx = 1'b0; - spi_en_tx = 1'b0; - spi_status = '0; - s_spi_mode = `SPI_QUAD_RX; - eot = 1'b0; - case(state) - IDLE: - begin - spi_status[0] = 1'b1; - s_spi_mode = `SPI_QUAD_RX; - if (spi_rd || spi_wr || spi_qrd || spi_qwr) - begin - spi_cs = 1'b0; - spi_clock_en = 1'b1; - - if (spi_cmd_len != 0) - begin - s_spi_mode = (spi_qrd | spi_qwr) ? `SPI_QUAD_TX : `SPI_STD; - counter_tx = {8'h0,spi_cmd_len}; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_CMD; - ctrl_data_valid = 1'b1; - spi_en_tx = 1'b1; - state_next = CMD; - end - else if (spi_addr_len != 0) - begin - s_spi_mode = (spi_qrd | spi_qwr) ? `SPI_QUAD_TX : `SPI_STD; - counter_tx = {8'h0,spi_addr_len}; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_ADDR; - ctrl_data_valid = 1'b1; - spi_en_tx = 1'b1; - state_next = ADDR; - end - else if (spi_data_len != 0) - begin - if (spi_rd || spi_qrd) - begin - s_spi_mode = (spi_qrd) ? `SPI_QUAD_RX : `SPI_STD; - if(spi_dummy_rd != 0) - begin - counter_tx = en_quad ? {spi_dummy_rd[13:0],2'b00} : spi_dummy_rd; - counter_tx_valid = 1'b1; - spi_en_tx = 1'b1; - ctrl_data_mux = DATA_EMPTY; - state_next = DUMMY; - end - else - begin - counter_rx = spi_data_len; - counter_rx_valid = 1'b1; - spi_en_rx = 1'b1; - state_next = DATA_RX; - end - end - else - begin - s_spi_mode = (spi_qwr) ? `SPI_QUAD_TX : `SPI_STD; - if(spi_dummy_wr != 0) - begin - counter_tx = en_quad ? {spi_dummy_wr[13:0],2'b00} : spi_dummy_wr; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_EMPTY; - spi_en_tx = 1'b1; - state_next = DUMMY; - end - else - begin - counter_tx = spi_data_len; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_FIFO; - ctrl_data_valid = 1'b0; - spi_en_tx = 1'b1; - state_next = DATA_TX; - end - end - end - end - else - begin - spi_cs = 1'b1; - state_next = IDLE; - end - end - - CMD: - begin - spi_status[1] = 1'b1; - spi_cs = 1'b0; - spi_clock_en = 1'b1; - s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; - if (tx_done) - begin - if (spi_addr_len != 0) - begin - s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; - counter_tx = {8'h0,spi_addr_len}; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_ADDR; - ctrl_data_valid = 1'b1; - spi_en_tx = 1'b1; - state_next = ADDR; - end - else if (spi_data_len != 0) - begin - if (do_rx) - begin - s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; - if(spi_dummy_rd != 0) - begin - counter_tx = en_quad ? {spi_dummy_rd[13:0],2'b00} : spi_dummy_rd; - counter_tx_valid = 1'b1; - spi_en_tx = 1'b1; - ctrl_data_mux = DATA_EMPTY; - state_next = DUMMY; - end - else - begin - counter_rx = spi_data_len; - counter_rx_valid = 1'b1; - spi_en_rx = 1'b1; - state_next = DATA_RX; - end - end - else - begin - s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; - if(spi_dummy_wr != 0) - begin - counter_tx = en_quad ? {spi_dummy_wr[13:0],2'b00} : spi_dummy_wr; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_EMPTY; - spi_en_tx = 1'b1; - state_next = DUMMY; - end - else - begin - counter_tx = spi_data_len; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_FIFO; - ctrl_data_valid = 1'b1; - spi_en_tx = 1'b1; - state_next = DATA_TX; - end - end - end - else - begin - state_next = IDLE; - end - end - else - begin - spi_en_tx = 1'b1; - state_next = CMD; - end - end - - ADDR: - begin - spi_en_tx = 1'b1; - spi_status[2] = 1'b1; - spi_cs = 1'b0; - spi_clock_en = 1'b1; - s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; - - if (tx_done) - begin - if (spi_data_len != 0) - begin - if (do_rx) - begin - s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; - if(spi_dummy_rd != 0) - begin - counter_tx = en_quad ? {spi_dummy_rd[13:0],2'b00} : spi_dummy_rd; - counter_tx_valid = 1'b1; - spi_en_tx = 1'b1; - ctrl_data_mux = DATA_EMPTY; - state_next = DUMMY; - end - else - begin - counter_rx = spi_data_len; - counter_rx_valid = 1'b1; - spi_en_rx = 1'b1; - state_next = DATA_RX; - end - end - else - begin - s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; - spi_en_tx = 1'b1; - - if(spi_dummy_wr != 0) begin - counter_tx = en_quad ? {spi_dummy_wr[13:0],2'b00} : spi_dummy_wr; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_EMPTY; - state_next = DUMMY; - end else begin - counter_tx = spi_data_len; - counter_tx_valid = 1'b1; - ctrl_data_mux = DATA_FIFO; - ctrl_data_valid = 1'b1; - state_next = DATA_TX; - end - end - end - else - begin - state_next = IDLE; - end - end - end - - MODE: - begin - spi_status[3] = 1'b1; - spi_cs = 1'b0; - spi_clock_en = 1'b1; - spi_en_tx = 1'b1; - end - - DUMMY: - begin - spi_en_tx = 1'b1; - spi_status[4] = 1'b1; - spi_cs = 1'b0; - spi_clock_en = 1'b1; - s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; - - if (tx_done) begin - if (spi_data_len != 0) begin - if (do_rx) begin - counter_rx = spi_data_len; - counter_rx_valid = 1'b1; - spi_en_rx = 1'b1; - state_next = DATA_RX; - end else begin - counter_tx = spi_data_len; - counter_tx_valid = 1'b1; - s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; - - spi_clock_en = tx_clk_en; - spi_en_tx = 1'b1; - state_next = DATA_TX; - end - end - else - begin - eot = 1'b1; - state_next = IDLE; - end - end - else - begin - ctrl_data_mux = DATA_EMPTY; - spi_en_tx = 1'b1; - state_next = DUMMY; - end - end - - DATA_TX: - begin - spi_status[5] = 1'b1; - spi_cs = 1'b0; - spi_clock_en = tx_clk_en; - ctrl_data_mux = DATA_FIFO; - ctrl_data_valid = 1'b1; - spi_en_tx = 1'b1; - s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; - - if (tx_done) begin - eot = 1'b1; - state_next = IDLE; - spi_clock_en = 1'b0; - end else begin - state_next = DATA_TX; - end - end - - DATA_RX: - begin - spi_status[6] = 1'b1; - spi_cs = 1'b0; - spi_clock_en = rx_clk_en; - s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; - - if (rx_done) begin - state_next = WAIT_EDGE; - end else begin - spi_en_rx = 1'b1; - state_next = DATA_RX; - end - end - WAIT_EDGE: - begin - spi_status[6] = 1'b1; - spi_cs = 1'b0; - spi_clock_en = 1'b0; - s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; - - if (spi_fall) begin - eot = 1'b1; - state_next = IDLE; - end else begin - state_next = WAIT_EDGE; - end - end - endcase - end - - - always_ff @(posedge clk, negedge rstn) - begin - if (rstn == 1'b0) - begin - state <= IDLE; - en_quad_int <= 1'b0; - do_rx <= 1'b0; - do_tx <= 1'b0; - spi_mode <= `SPI_QUAD_RX; - end - else - begin - state <= state_next; - spi_mode <= s_spi_mode; - if (spi_qrd || spi_qwr) - en_quad_int <= 1'b1; - else if (state_next == IDLE) - en_quad_int <= 1'b0; - - if (spi_rd || spi_qrd) - begin - do_rx <= 1'b1; - do_tx <= 1'b0; - end - else if (spi_wr || spi_qwr) - begin - do_rx <= 1'b0; - do_tx <= 1'b1; - end - else if (state_next == IDLE) - begin - do_rx <= 1'b0; - do_tx <= 1'b0; - end - end - end - - assign spi_csn0 = ~spi_csreg[0] | spi_cs; - assign spi_csn1 = ~spi_csreg[1] | spi_cs; - assign spi_csn2 = ~spi_csreg[2] | spi_cs; - assign spi_csn3 = ~spi_csreg[3] | spi_cs; - -endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_controller.v b/rtl/e203/perips/apb_spi_master/spi_master_controller.v new file mode 100644 index 0000000..300f6b1 --- /dev/null +++ b/rtl/e203/perips/apb_spi_master/spi_master_controller.v @@ -0,0 +1,497 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +`define SPI_STD 2'b00 +`define SPI_QUAD_TX 2'b01 +`define SPI_QUAD_RX 2'b10 + +module spi_master_controller ( + input wire clk, + input wire rstn, + output reg eot, + input wire [7:0] spi_clk_div, + input wire spi_clk_div_valid, + output reg [6:0] spi_status, + input wire [31:0] spi_addr, + input wire [5:0] spi_addr_len, + input wire [31:0] spi_cmd, + input wire [5:0] spi_cmd_len, + input wire [15:0] spi_data_len, + input wire [15:0] spi_dummy_rd, + input wire [15:0] spi_dummy_wr, + input wire [3:0] spi_csreg, + input wire spi_swrst, //FIXME Not used at all + input wire spi_rd, + input wire spi_wr, + input wire spi_qrd, + input wire spi_qwr, + input wire [31:0] spi_ctrl_data_tx, + input wire spi_ctrl_data_tx_valid, + output reg spi_ctrl_data_tx_ready, + output wire [31:0] spi_ctrl_data_rx, + output wire spi_ctrl_data_rx_valid, + input wire spi_ctrl_data_rx_ready, + output wire spi_clk, + output wire spi_csn0, + output wire spi_csn1, + output wire spi_csn2, + output wire spi_csn3, + output reg [1:0] spi_mode, + output wire spi_sdo0, + output wire spi_sdo1, + output wire spi_sdo2, + output wire spi_sdo3, + input wire spi_sdi0, + input wire spi_sdi1, + input wire spi_sdi2, + input wire spi_sdi3 +); + + localparam [2:0] DATA_NULL = 0; + localparam [2:0] DATA_EMPTY = 1; + localparam [2:0] DATA_CMD = 2; + localparam [2:0] DATA_ADDR = 3; + localparam [2:0] DATA_FIFO = 4; + + localparam [4:0] IDLE = 0; + localparam [4:0] CMD = 1; + localparam [4:0] ADDR = 2; + localparam [4:0] MODE = 3; + localparam [4:0] DUMMY = 4; + localparam [4:0] DATA_TX = 5; + localparam [4:0] DATA_RX = 6; + localparam [4:0] WAIT_EDGE = 7; + + + wire spi_rise; + wire spi_fall; + + reg spi_clock_en; + + reg spi_en_tx; + reg spi_en_rx; + + reg [15:0] counter_tx; + reg counter_tx_valid; + reg [15:0] counter_rx; + reg counter_rx_valid; + + reg [31:0] data_to_tx; + reg data_to_tx_valid; + wire data_to_tx_ready; + + wire en_quad; + reg en_quad_int; + reg do_tx; //FIXME NOT USED at all!! + reg do_rx; + + wire tx_done; + wire rx_done; + + reg [1:0] s_spi_mode; + + reg ctrl_data_valid; + + reg spi_cs; + + wire tx_clk_en; + wire rx_clk_en; + + reg [2:0] ctrl_data_mux; + reg [4:0] state; + reg [4:0] state_next; + + + assign en_quad = (spi_qrd | spi_qwr) | en_quad_int; + + spi_master_clkgen u_clkgen + ( + .clk ( clk ), + .rstn ( rstn ), + .en ( spi_clock_en ), + .clk_div ( spi_clk_div ), + .clk_div_valid ( spi_clk_div_valid ), + .spi_clk ( spi_clk ), + .spi_fall ( spi_fall ), + .spi_rise ( spi_rise ) + ); + + spi_master_tx u_txreg + ( + .clk ( clk ), + .rstn ( rstn ), + .en ( spi_en_tx ), + .tx_edge ( spi_fall ), + .tx_done ( tx_done ), + .sdo0 ( spi_sdo0 ), + .sdo1 ( spi_sdo1 ), + .sdo2 ( spi_sdo2 ), + .sdo3 ( spi_sdo3 ), + .en_quad_in ( en_quad ), + .counter_in ( counter_tx ), + .counter_in_upd ( counter_tx_valid ), + .data ( data_to_tx ), + .data_valid ( data_to_tx_valid ), + .data_ready ( data_to_tx_ready ), + .clk_en_o ( tx_clk_en ) + ); + + spi_master_rx u_rxreg + ( + .clk ( clk ), + .rstn ( rstn ), + .en ( spi_en_rx ), + .rx_edge ( spi_rise ), + .rx_done ( rx_done ), + .sdi0 ( spi_sdi0 ), + .sdi1 ( spi_sdi1 ), + .sdi2 ( spi_sdi2 ), + .sdi3 ( spi_sdi3 ), + .en_quad_in ( en_quad ), + .counter_in ( counter_rx ), + .counter_in_upd ( counter_rx_valid ), + .data ( spi_ctrl_data_rx ), + .data_valid ( spi_ctrl_data_rx_valid ), + .data_ready ( spi_ctrl_data_rx_ready ), + .clk_en_o ( rx_clk_en ) + ); + + always @(*) begin + data_to_tx = 'h0; + data_to_tx_valid = 1'b0; + spi_ctrl_data_tx_ready = 1'b0; + + case (ctrl_data_mux) + DATA_NULL: begin + data_to_tx = 'b0; + data_to_tx_valid = 1'b0; + spi_ctrl_data_tx_ready = 1'b0; + end + DATA_EMPTY: begin + data_to_tx = 'b0; + data_to_tx_valid = 1'b1; + end + DATA_CMD: begin + data_to_tx = spi_cmd; + data_to_tx_valid = ctrl_data_valid; + spi_ctrl_data_tx_ready = 1'b0; + end + DATA_ADDR: begin + data_to_tx = spi_addr; + data_to_tx_valid = ctrl_data_valid; + spi_ctrl_data_tx_ready = 1'b0; + end + DATA_FIFO: begin + data_to_tx = spi_ctrl_data_tx; + data_to_tx_valid = spi_ctrl_data_tx_valid; + spi_ctrl_data_tx_ready = data_to_tx_ready; + end + endcase + end + + always @(*) begin + spi_cs = 1'b1; + spi_clock_en = 1'b0; + counter_tx = 'b0; + counter_tx_valid = 1'b0; + counter_rx = 'b0; + counter_rx_valid = 1'b0; + state_next = state; + ctrl_data_mux = DATA_NULL; + ctrl_data_valid = 1'b0; + spi_en_rx = 1'b0; + spi_en_tx = 1'b0; + spi_status = 'b0; + s_spi_mode = `SPI_QUAD_RX; + eot = 1'b0; + case (state) + IDLE: begin + spi_status[0] = 1'b1; + s_spi_mode = `SPI_QUAD_RX; + + if (spi_rd || spi_wr || spi_qrd || spi_qwr) begin + spi_cs = 1'b0; + spi_clock_en = 1'b1; + + if (spi_cmd_len != 0) begin + s_spi_mode = (spi_qrd | spi_qwr) ? `SPI_QUAD_TX : `SPI_STD; + counter_tx = {8'h00, spi_cmd_len}; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_CMD; + ctrl_data_valid = 1'b1; + spi_en_tx = 1'b1; + state_next = CMD; + end else if (spi_addr_len != 0) begin + s_spi_mode = (spi_qrd | spi_qwr) ? `SPI_QUAD_TX : `SPI_STD; + counter_tx = {8'h00, spi_addr_len}; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_ADDR; + ctrl_data_valid = 1'b1; + spi_en_tx = 1'b1; + state_next = ADDR; + end else if (spi_data_len != 0) + if (spi_rd || spi_qrd) begin + s_spi_mode = (spi_qrd) ? `SPI_QUAD_RX : `SPI_STD; + + if (spi_dummy_rd != 0) begin + counter_tx = (en_quad) ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd; + counter_tx_valid = 1'b1; + spi_en_tx = 1'b1; + ctrl_data_mux = DATA_EMPTY; + state_next = DUMMY; + end else begin + counter_rx = spi_data_len; + counter_rx_valid = 1'b1; + spi_en_rx = 1'b1; + state_next = DATA_RX; + end + end else begin + s_spi_mode = (spi_qwr) ? `SPI_QUAD_TX : `SPI_STD; + + if (spi_dummy_wr != 0) begin + counter_tx = (en_quad) ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_EMPTY; + spi_en_tx = 1'b1; + state_next = DUMMY; + end else begin + counter_tx = spi_data_len; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_FIFO; + ctrl_data_valid = 1'b0; + spi_en_tx = 1'b1; + state_next = DATA_TX; + end + end + end else begin + spi_cs = 1'b1; + state_next = IDLE; + end + end + CMD: begin + spi_status[1] = 1'b1; + spi_cs = 1'b0; + spi_clock_en = 1'b1; + s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; + + if (tx_done) begin + if (spi_addr_len != 0) begin + s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; + counter_tx = {8'h00, spi_addr_len}; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_ADDR; + ctrl_data_valid = 1'b1; + spi_en_tx = 1'b1; + state_next = ADDR; + end else if (spi_data_len != 0) begin + if (do_rx) begin + s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; + if (spi_dummy_rd != 0) begin + counter_tx = (en_quad) ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd; + counter_tx_valid = 1'b1; + spi_en_tx = 1'b1; + ctrl_data_mux = DATA_EMPTY; + state_next = DUMMY; + end else begin + counter_rx = spi_data_len; + counter_rx_valid = 1'b1; + spi_en_rx = 1'b1; + state_next = DATA_RX; + end + end else begin + s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; + if (spi_dummy_wr != 0) begin + counter_tx = (en_quad) ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_EMPTY; + spi_en_tx = 1'b1; + state_next = DUMMY; + end else begin + counter_tx = spi_data_len; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_FIFO; + ctrl_data_valid = 1'b1; + spi_en_tx = 1'b1; + state_next = DATA_TX; + end + end + end else begin + state_next = IDLE; + end + end else begin + spi_en_tx = 1'b1; + state_next = CMD; + end + end + ADDR: begin + spi_en_tx = 1'b1; + spi_status[2] = 1'b1; + spi_cs = 1'b0; + spi_clock_en = 1'b1; + s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; + if (tx_done) begin + if (spi_data_len != 0) begin + if (do_rx) begin + s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; + if (spi_dummy_rd != 0) begin + counter_tx = (en_quad) ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd; + counter_tx_valid = 1'b1; + spi_en_tx = 1'b1; + ctrl_data_mux = DATA_EMPTY; + state_next = DUMMY; + end else begin + counter_rx = spi_data_len; + counter_rx_valid = 1'b1; + spi_en_rx = 1'b1; + state_next = DATA_RX; + end + end else begin + s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; + spi_en_tx = 1'b1; + + if (spi_dummy_wr != 0) begin + counter_tx = (en_quad) ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_EMPTY; + state_next = DUMMY; + end else begin + counter_tx = spi_data_len; + counter_tx_valid = 1'b1; + ctrl_data_mux = DATA_FIFO; + ctrl_data_valid = 1'b1; + state_next = DATA_TX; + end + end + end else begin + state_next = IDLE; + end + end + end + MODE: begin + spi_status[3] = 1'b1; + spi_cs = 1'b0; + spi_clock_en = 1'b1; + spi_en_tx = 1'b1; + end + DUMMY: begin + spi_en_tx = 1'b1; + spi_status[4] = 1'b1; + spi_cs = 1'b0; + spi_clock_en = 1'b1; + s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; + + if (tx_done) begin + if (spi_data_len != 0) begin + if (do_rx) begin + counter_rx = spi_data_len; + counter_rx_valid = 1'b1; + spi_en_rx = 1'b1; + state_next = DATA_RX; + end else begin + counter_tx = spi_data_len; + counter_tx_valid = 1'b1; + s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; + spi_clock_en = tx_clk_en; + spi_en_tx = 1'b1; + state_next = DATA_TX; + end + end else begin + eot = 1'b1; + state_next = IDLE; + end + end else begin + ctrl_data_mux = DATA_EMPTY; + spi_en_tx = 1'b1; + state_next = DUMMY; + end + end + DATA_TX: begin + spi_status[5] = 1'b1; + spi_cs = 1'b0; + spi_clock_en = tx_clk_en; + ctrl_data_mux = DATA_FIFO; + ctrl_data_valid = 1'b1; + spi_en_tx = 1'b1; + s_spi_mode = (en_quad) ? `SPI_QUAD_TX : `SPI_STD; + + if (tx_done) begin + eot = 1'b1; + state_next = IDLE; + spi_clock_en = 1'b0; + end else begin + state_next = DATA_TX; + end + end + DATA_RX: begin + spi_status[6] = 1'b1; + spi_cs = 1'b0; + spi_clock_en = rx_clk_en; + s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; + + if (rx_done) begin + state_next = WAIT_EDGE; + end else begin + spi_en_rx = 1'b1; + state_next = DATA_RX; + end + end + WAIT_EDGE: begin + spi_status[6] = 1'b1; + spi_cs = 1'b0; + spi_clock_en = 1'b0; + s_spi_mode = (en_quad) ? `SPI_QUAD_RX : `SPI_STD; + + if (spi_fall) begin + eot = 1'b1; + state_next = IDLE; + end else begin + state_next = WAIT_EDGE; + end + end + endcase + end + + + always @(posedge clk or negedge rstn) begin + if (rstn == 1'b0) begin + state <= IDLE; + en_quad_int <= 1'b0; + do_rx <= 1'b0; + do_tx <= 1'b0; + spi_mode <= `SPI_QUAD_RX; + end else begin + state <= state_next; + spi_mode <= s_spi_mode; + + if (spi_qrd || spi_qwr) + en_quad_int <= 1'b1; + else if (state_next == IDLE) + en_quad_int <= 1'b0; + + if (spi_rd || spi_qrd) begin + do_rx <= 1'b1; + do_tx <= 1'b0; + end else if (spi_wr || spi_qwr) begin + do_rx <= 1'b0; + do_tx <= 1'b1; + end else if (state_next == IDLE) begin + do_rx <= 1'b0; + do_tx <= 1'b0; + end + end + end + + assign spi_csn0 = ~spi_csreg[0] | spi_cs; + assign spi_csn1 = ~spi_csreg[1] | spi_cs; + assign spi_csn2 = ~spi_csreg[2] | spi_cs; + assign spi_csn3 = ~spi_csreg[3] | spi_cs; + +endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_fifo.sv b/rtl/e203/perips/apb_spi_master/spi_master_fifo.sv deleted file mode 100644 index 746d5de..0000000 --- a/rtl/e203/perips/apb_spi_master/spi_master_fifo.sv +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -`define log2(VALUE) ((VALUE) < ( 1 ) ? 0 : (VALUE) < ( 2 ) ? 1 : (VALUE) < ( 4 ) ? 2 : (VALUE) < ( 8 ) ? 3 : (VALUE) < ( 16 ) ? 4 : (VALUE) < ( 32 ) ? 5 : (VALUE) < ( 64 ) ? 6 : (VALUE) < ( 128 ) ? 7 : (VALUE) < ( 256 ) ? 8 : (VALUE) < ( 512 ) ? 9 : (VALUE) < ( 1024 ) ? 10 : (VALUE) < ( 2048 ) ? 11 : (VALUE) < ( 4096 ) ? 12 : (VALUE) < ( 8192 ) ? 13 : (VALUE) < ( 16384 ) ? 14 : (VALUE) < ( 32768 ) ? 15 : (VALUE) < ( 65536 ) ? 16 : (VALUE) < ( 131072 ) ? 17 : (VALUE) < ( 262144 ) ? 18 : (VALUE) < ( 524288 ) ? 19 : (VALUE) < ( 1048576 ) ? 20 : (VALUE) < ( 1048576 * 2 ) ? 21 : (VALUE) < ( 1048576 * 4 ) ? 22 : (VALUE) < ( 1048576 * 8 ) ? 23 : (VALUE) < ( 1048576 * 16 ) ? 24 : 25) - -module spi_master_fifo -#( - parameter DATA_WIDTH = 32, - parameter BUFFER_DEPTH = 2, - parameter LOG_BUFFER_DEPTH = `log2(BUFFER_DEPTH) -) -( - input logic clk_i, - input logic rst_ni, - - input logic clr_i, - - output logic [LOG_BUFFER_DEPTH:0] elements_o, - - output logic [DATA_WIDTH-1 : 0] data_o, - output logic valid_o, - input logic ready_i, - - input logic valid_i, - input logic [DATA_WIDTH-1 : 0] data_i, - output logic ready_o -); - - // Internal data structures - logic [LOG_BUFFER_DEPTH-1:0] pointer_in; // location to which we last wrote - logic [LOG_BUFFER_DEPTH-1:0] pointer_out; // location from which we last sent - logic [LOG_BUFFER_DEPTH:0] elements; // number of elements in the buffer - logic [DATA_WIDTH-1:0] buffer [BUFFER_DEPTH - 1 : 0]; - - wire full; - - integer loop1; - - assign full = (elements == BUFFER_DEPTH); - assign elements_o = elements; - - always_ff @(posedge clk_i, negedge rst_ni) - begin: elements_sequential - if (rst_ni == 1'b0) - elements <= 0; - else - begin - if (clr_i) - elements <= 0; - else - begin - // ------------------ - // Are we filling up? - // ------------------ - // One out, none in - if (ready_i && valid_o && (!valid_i || full)) - elements <= elements - 1; - // None out, one in - else if ((!valid_o || !ready_i) && valid_i && !full) - elements <= elements + 1; - // Else, either one out and one in, or none out and none in - stays unchanged - end - end - end - - always_ff @(posedge clk_i, negedge rst_ni) - begin: buffers_sequential - if (rst_ni == 1'b0) - begin - for (loop1 = 0 ; loop1 < BUFFER_DEPTH ; loop1 = loop1 + 1) - buffer[loop1] <= 0; - end - else - begin - // Update the memory - if (valid_i && !full) - buffer[pointer_in] <= data_i; - end - end - - always_ff @(posedge clk_i, negedge rst_ni) - begin: sequential - if (rst_ni == 1'b0) - begin - pointer_out <= 0; - pointer_in <= 0; - end - else - begin - if(clr_i) - begin - pointer_out <= 0; - pointer_in <= 0; - end - else - begin - // ------------------------------------ - // Check what to do with the input side - // ------------------------------------ - // We have some input, increase by 1 the input pointer - if (valid_i && !full) - begin - if (pointer_in == $unsigned(BUFFER_DEPTH - 1)) - pointer_in <= 0; - else - pointer_in <= pointer_in + 1; - end - // Else we don't have any input, the input pointer stays the same - - // ------------------------------------- - // Check what to do with the output side - // ------------------------------------- - // We had pushed one flit out, we can try to go for the next one - if (ready_i && valid_o) - begin - if (pointer_out == $unsigned(BUFFER_DEPTH - 1)) - pointer_out <= 0; - else - pointer_out <= pointer_out + 1; - end - // Else stay on the same output location - end - end - end - - // Update output ports - assign data_o = buffer[pointer_out]; - assign valid_o = (elements != 0); - - assign ready_o = ~full; - -endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_fifo.v b/rtl/e203/perips/apb_spi_master/spi_master_fifo.v new file mode 100644 index 0000000..59f5435 --- /dev/null +++ b/rtl/e203/perips/apb_spi_master/spi_master_fifo.v @@ -0,0 +1,114 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +`define log2(VALUE) ((VALUE) < ( 1 ) ? 0 : (VALUE) < ( 2 ) ? 1 : (VALUE) < ( 4 ) ? 2 : (VALUE) < ( 8 ) ? 3 : (VALUE) < ( 16 ) ? 4 : (VALUE) < ( 32 ) ? 5 : (VALUE) < ( 64 ) ? 6 : (VALUE) < ( 128 ) ? 7 : (VALUE) < ( 256 ) ? 8 : (VALUE) < ( 512 ) ? 9 : (VALUE) < ( 1024 ) ? 10 : (VALUE) < ( 2048 ) ? 11 : (VALUE) < ( 4096 ) ? 12 : (VALUE) < ( 8192 ) ? 13 : (VALUE) < ( 16384 ) ? 14 : (VALUE) < ( 32768 ) ? 15 : (VALUE) < ( 65536 ) ? 16 : (VALUE) < ( 131072 ) ? 17 : (VALUE) < ( 262144 ) ? 18 : (VALUE) < ( 524288 ) ? 19 : (VALUE) < ( 1048576 ) ? 20 : (VALUE) < ( 1048576 * 2 ) ? 21 : (VALUE) < ( 1048576 * 4 ) ? 22 : (VALUE) < ( 1048576 * 8 ) ? 23 : (VALUE) < ( 1048576 * 16 ) ? 24 : 25) + +module spi_master_fifo +#( + parameter DATA_WIDTH = 32, + parameter BUFFER_DEPTH = 2, + parameter LOG_BUFFER_DEPTH = `log2(BUFFER_DEPTH) +) +( + input wire clk_i, + input wire rst_ni, + input wire clr_i, + output wire [LOG_BUFFER_DEPTH:0] elements_o, + output wire [DATA_WIDTH - 1:0] data_o, + output wire valid_o, + input wire ready_i, + input wire valid_i, + input wire [DATA_WIDTH - 1:0] data_i, + output wire ready_o +); + + // Internal data structures + reg [LOG_BUFFER_DEPTH - 1:0] pointer_in; // location to which we last wrote + reg [LOG_BUFFER_DEPTH - 1:0] pointer_out; // location from which we last sent + reg [LOG_BUFFER_DEPTH:0] elements; // number of elements in the buffer + reg [DATA_WIDTH - 1:0] buffer [BUFFER_DEPTH - 1:0]; + + + wire full; + integer loop1; + + assign full = (elements == BUFFER_DEPTH); + assign elements_o = elements; + + always @(posedge clk_i or negedge rst_ni) begin : elements_sequential + if (rst_ni == 1'b0) + elements <= 0; + else if (clr_i) + elements <= 0; + // ------------------ + // Are we filling up? + // ------------------ + // One out, none in + else if ((ready_i && valid_o) && (!valid_i || full)) + elements <= elements - 1; + // None out, one in + else if (((!valid_o || !ready_i) && valid_i) && !full) + elements <= elements + 1; + // Else, either one out and one in, or none out and none in - stays unchanged + end + + + always @(posedge clk_i or negedge rst_ni) begin : buffers_sequential + if (rst_ni == 1'b0) begin + for (loop1 = 0; loop1 < BUFFER_DEPTH; loop1 = loop1 + 1) + buffer[loop1] <= 0; + end + else if (valid_i && !full) + // Update the memory + buffer[pointer_in] <= data_i; + end + + + always @(posedge clk_i or negedge rst_ni) begin : sequential + if (rst_ni == 1'b0) begin + pointer_out <= 0; + pointer_in <= 0; + end else if (clr_i) begin + pointer_out <= 0; + pointer_in <= 0; + end else begin + // ------------------------------------ + // Check what to do with the input side + // ------------------------------------ + // We have some input, increase by 1 the input pointer + if (valid_i && !full) begin + if (pointer_in == $unsigned(BUFFER_DEPTH - 1)) + pointer_in <= 0; + else + pointer_in <= pointer_in + 1; + end + // Else we don't have any input, the input pointer stays the same + + // ------------------------------------- + // Check what to do with the output side + // ------------------------------------- + // We had pushed one flit out, we can try to go for the next one + if (ready_i && valid_o) begin + if (pointer_out == $unsigned(BUFFER_DEPTH - 1)) + pointer_out <= 0; + else + pointer_out <= pointer_out + 1; + end + // Else stay on the same output location + end + end + + // Update output ports + assign data_o = buffer[pointer_out]; + assign valid_o = (elements != 0); + assign ready_o = ~full; + +endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_rx.sv b/rtl/e203/perips/apb_spi_master/spi_master_rx.sv deleted file mode 100644 index e61d0ae..0000000 --- a/rtl/e203/perips/apb_spi_master/spi_master_rx.sv +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// -- Adaptable modifications made for hbirdv2 SoC. -- -// Copyright 2020 Nuclei System Technology, Inc. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module spi_master_rx -( - input logic clk, - input logic rstn, - input logic en, - input logic rx_edge, - output logic rx_done, - input logic sdi0, - input logic sdi1, - input logic sdi2, - input logic sdi3, - input logic en_quad_in, - input logic [15:0] counter_in, - input logic counter_in_upd, - output logic [31:0] data, - input logic data_ready, - output logic data_valid, - output logic clk_en_o -); - - logic [31:0] data_int; - logic [31:0] data_int_next; - logic [15:0] counter; - logic [15:0] counter_trgt; - logic [15:0] counter_next; - logic [15:0] counter_trgt_next; - logic done; - logic reg_done; - enum logic [1:0] { IDLE, RECEIVE, WAIT_FIFO, WAIT_FIFO_DONE } rx_CS, rx_NS; - - - assign reg_done = (!en_quad_in && (counter[4:0] == 5'b11111)) || (en_quad_in && (counter[2:0] == 3'b111)); - - assign data = data_int_next; - assign rx_done = done; - - always_comb - begin - if (counter_in_upd) - counter_trgt_next = (en_quad_in) ? {2'b00,counter_in[15:2]} : counter_in; - else - counter_trgt_next = counter_trgt; - end - - assign done = (counter == counter_trgt-1) && rx_edge; - - always_comb - begin - rx_NS = rx_CS; - clk_en_o = 1'b0; - data_int_next = data_int; - data_valid = 1'b0; - counter_next = counter; - - case (rx_CS) - IDLE: begin - clk_en_o = 1'b0; - - // check first if there is available space instead of later - if (en) begin - rx_NS = RECEIVE; - end - end - - RECEIVE: begin - clk_en_o = 1'b1; - - if (rx_edge) begin - counter_next = counter + 1; - - if (en_quad_in) - data_int_next = {data_int[27:0],sdi3,sdi2,sdi1,sdi0}; - else - data_int_next = {data_int[30:0],sdi1}; - - if (rx_done) begin - counter_next = 0; - data_valid = 1'b1; - - if (data_ready) - rx_NS = IDLE; - else - rx_NS = WAIT_FIFO_DONE; - end else if (reg_done) begin - data_valid = 1'b1; - - if (~data_ready) begin - // no space in the FIFO, wait for free space - clk_en_o = 1'b0; - rx_NS = WAIT_FIFO; - end - end - end - end - - WAIT_FIFO_DONE: begin - data_valid = 1'b1; - if (data_ready) - rx_NS = IDLE; - end - - WAIT_FIFO: begin - data_valid = 1'b1; - if (data_ready) - rx_NS = RECEIVE; - end - endcase - end - - - always_ff @(posedge clk, negedge rstn) - begin - if (rstn == 0) - begin - counter <= 0; - counter_trgt <= 'h8; - data_int <= '0; - rx_CS <= IDLE; - end - else - begin - counter <= counter_next; - counter_trgt <= counter_trgt_next; - data_int <= data_int_next; - rx_CS <= rx_NS; - end - end - -endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_rx.v b/rtl/e203/perips/apb_spi_master/spi_master_rx.v new file mode 100644 index 0000000..9de86cd --- /dev/null +++ b/rtl/e203/perips/apb_spi_master/spi_master_rx.v @@ -0,0 +1,132 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module spi_master_rx ( + input wire clk, + input wire rstn, + input wire en, + input wire rx_edge, + output wire rx_done, + input wire sdi0, + input wire sdi1, + input wire sdi2, + input wire sdi3, + input wire en_quad_in, + input wire [15:0] counter_in, + input wire counter_in_upd, + output wire [31:0] data, + input wire data_ready, + output reg data_valid, + output reg clk_en_o +); + localparam [1:0] IDLE = 0; + localparam [1:0] RECEIVE = 1; + localparam [1:0] WAIT_FIFO = 2; + localparam [1:0] WAIT_FIFO_DONE = 3; + + reg [31:0] data_int; + reg [31:0] data_int_next; + reg [15:0] counter; + reg [15:0] counter_trgt; + reg [15:0] counter_next; + reg [15:0] counter_trgt_next; + wire done; + wire reg_done; + + reg [1:0] rx_CS; + reg [1:0] rx_NS; + + assign reg_done = (!en_quad_in && (counter[4:0] == 5'b11111)) || (en_quad_in && (counter[2:0] == 3'b111)); + assign data = data_int_next; + assign rx_done = done; + + always @(*) begin + if (counter_in_upd) + counter_trgt_next = (en_quad_in ? {2'b00, counter_in[15:2]} : counter_in); + else + counter_trgt_next = counter_trgt; + end + + assign done = (counter == (counter_trgt - 1)) && rx_edge; + + always @(*) begin + rx_NS = rx_CS; + clk_en_o = 1'b0; + data_int_next = data_int; + data_valid = 1'b0; + counter_next = counter; + + case (rx_CS) + IDLE: begin + clk_en_o = 1'b0; + + // check first if there is available space instead of later + if (en) rx_NS = RECEIVE; + end + RECEIVE: begin + clk_en_o = 1'b1; + + if (rx_edge) begin + counter_next = counter + 1; + + if (en_quad_in) + data_int_next = {data_int[27:0], sdi3, sdi2, sdi1, sdi0}; + else + data_int_next = {data_int[30:0], sdi1}; + + if (rx_done) begin + counter_next = 0; + data_valid = 1'b1; + + if (data_ready) + rx_NS = IDLE; + else + rx_NS = WAIT_FIFO_DONE; + + end else if (reg_done) begin + data_valid = 1'b1; + + if (~data_ready) begin + // no space in the FIFO, wait for free space + clk_en_o = 1'b0; + rx_NS = WAIT_FIFO; + end + end + end + end + WAIT_FIFO_DONE: begin + data_valid = 1'b1; + if (data_ready) rx_NS = IDLE; + end + WAIT_FIFO: begin + data_valid = 1'b1; + if (data_ready) rx_NS = RECEIVE; + end + endcase + end + + + always @(posedge clk or negedge rstn) begin + if (rstn == 0) begin + counter <= 0; + counter_trgt <= 'h8; + data_int <= 'b0; + rx_CS <= IDLE; + end else begin + counter <= counter_next; + counter_trgt <= counter_trgt_next; + data_int <= data_int_next; + rx_CS <= rx_NS; + end + end + +endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_tx.sv b/rtl/e203/perips/apb_spi_master/spi_master_tx.sv deleted file mode 100644 index 20c22dc..0000000 --- a/rtl/e203/perips/apb_spi_master/spi_master_tx.sv +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module spi_master_tx -( - input logic clk, - input logic rstn, - input logic en, - input logic tx_edge, - output logic tx_done, - output logic sdo0, - output logic sdo1, - output logic sdo2, - output logic sdo3, - input logic en_quad_in, - input logic [15:0] counter_in, - input logic counter_in_upd, - input logic [31:0] data, - input logic data_valid, - output logic data_ready, - output logic clk_en_o -); - - logic [31:0] data_int; - logic [31:0] data_int_next; - logic [15:0] counter; - logic [15:0] counter_trgt; - logic [15:0] counter_next; - logic [15:0] counter_trgt_next; - logic done; - logic reg_done; - - enum logic [0:0] { IDLE, TRANSMIT } tx_CS, tx_NS; - - assign sdo0 = (en_quad_in) ? data_int[28] : data_int[31]; - assign sdo1 = data_int[29]; - assign sdo2 = data_int[30]; - assign sdo3 = data_int[31]; - - assign tx_done = done; - - assign reg_done = (!en_quad_in && (counter[4:0] == 5'b11111)) || (en_quad_in && (counter[2:0] == 3'b111)); - - always_comb - begin - if (counter_in_upd) - counter_trgt_next = (en_quad_in) ? {2'b00,counter_in[15:2]} : counter_in; - else - counter_trgt_next = counter_trgt; - end - - assign done = (counter == counter_trgt-1) && tx_edge; - - always_comb - begin - tx_NS = tx_CS; - clk_en_o = 1'b0; - data_int_next = data_int; - data_ready = 1'b0; - counter_next = counter; - - case (tx_CS) - IDLE: begin - clk_en_o = 1'b0; - - if (en && data_valid) begin - data_int_next = data; - data_ready = 1'b1; - tx_NS = TRANSMIT; - end - end - - TRANSMIT: begin - clk_en_o = 1'b1; - - if (tx_edge) begin - counter_next = counter + 1; - data_int_next = (en_quad_in) ? {data_int[27:0],4'b0000} : {data_int[30:0],1'b0}; - - if (tx_done) begin - counter_next = 0; - - if (en && data_valid) begin - data_int_next = data; - data_ready = 1'b1; - tx_NS = TRANSMIT; - end else begin - clk_en_o = 1'b0; - tx_NS = IDLE; - end - end else if (reg_done) begin - if (data_valid) begin - data_int_next = data; - data_ready = 1'b1; - end else begin - clk_en_o = 1'b0; - tx_NS = IDLE; - end - end - end - end - endcase - end - - always_ff @(posedge clk, negedge rstn) - begin - if (~rstn) - begin - counter <= 0; - counter_trgt <= 'h8; - data_int <= 'h0; - tx_CS <= IDLE; - end - else - begin - counter <= counter_next; - counter_trgt <= counter_trgt_next; - data_int <= data_int_next; - tx_CS <= tx_NS; - end - end -endmodule diff --git a/rtl/e203/perips/apb_spi_master/spi_master_tx.v b/rtl/e203/perips/apb_spi_master/spi_master_tx.v new file mode 100644 index 0000000..798cfb8 --- /dev/null +++ b/rtl/e203/perips/apb_spi_master/spi_master_tx.v @@ -0,0 +1,128 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module spi_master_tx ( + input wire clk, + input wire rstn, + input wire en, + input wire tx_edge, + output wire tx_done, + output wire sdo0, + output wire sdo1, + output wire sdo2, + output wire sdo3, + input wire en_quad_in, + input wire [15:0] counter_in, + input wire counter_in_upd, + input wire [31:0] data, + input wire data_valid, + output reg data_ready, + output reg clk_en_o +); + localparam [0:0] IDLE = 0; + localparam [0:0] TRANSMIT = 1; + + reg [31:0] data_int; + reg [31:0] data_int_next; + reg [15:0] counter; + reg [15:0] counter_trgt; + reg [15:0] counter_next; + reg [15:0] counter_trgt_next; + + wire done; + wire reg_done; + + reg [0:0] tx_CS; + reg [0:0] tx_NS; + + assign sdo0 = (en_quad_in ? data_int[28] : data_int[31]); + assign sdo1 = data_int[29]; + assign sdo2 = data_int[30]; + assign sdo3 = data_int[31]; + + assign tx_done = done; + assign reg_done = (!en_quad_in && (counter[4:0] == 5'b11111)) || (en_quad_in && (counter[2:0] == 3'b111)); + + always @(*) begin + if (counter_in_upd) + counter_trgt_next = (en_quad_in ? {2'b00, counter_in[15:2]} : counter_in); + else + counter_trgt_next = counter_trgt; + end + + assign done = (counter == (counter_trgt - 1)) && tx_edge; + + always @(*) begin + tx_NS = tx_CS; + clk_en_o = 1'b0; + data_int_next = data_int; + data_ready = 1'b0; + counter_next = counter; + + case (tx_CS) + IDLE: begin + clk_en_o = 1'b0; + + if (en && data_valid) begin + data_int_next = data; + data_ready = 1'b1; + tx_NS = TRANSMIT; + end + end + TRANSMIT: begin + clk_en_o = 1'b1; + + if (tx_edge) begin + counter_next = counter + 1; + data_int_next = (en_quad_in ? {data_int[27:0], 4'b0000} : {data_int[30:0], 1'b0}); + + if (tx_done) begin + counter_next = 0; + + if (en && data_valid) begin + data_int_next = data; + data_ready = 1'b1; + tx_NS = TRANSMIT; + end else begin + clk_en_o = 1'b0; + tx_NS = IDLE; + end + end else if (reg_done) begin + if (data_valid) begin + data_int_next = data; + data_ready = 1'b1; + end else begin + clk_en_o = 1'b0; + tx_NS = IDLE; + end + end + end + end + endcase + end + + + always @(posedge clk or negedge rstn) begin + if (~rstn) begin + counter <= 0; + counter_trgt <= 'h8; + data_int <= 'h0; + tx_CS <= IDLE; + end else begin + counter <= counter_next; + counter_trgt <= counter_trgt_next; + data_int <= data_int_next; + tx_CS <= tx_NS; + end + end + +endmodule diff --git a/rtl/e203/perips/apb_uart/apb_uart.sv b/rtl/e203/perips/apb_uart/apb_uart.sv deleted file mode 100644 index 0861af7..0000000 --- a/rtl/e203/perips/apb_uart/apb_uart.sv +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// -- Adaptable modifications made for hbirdv2 SoC. -- -// Copyright 2020 Nuclei System Technology, Inc. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module apb_uart_sv -#( - parameter APB_ADDR_WIDTH = 12 //APB slaves are 4KB by default -) -( - input logic CLK, - input logic RSTN, - /* verilator lint_off UNUSED */ - input logic [APB_ADDR_WIDTH-1:0] PADDR, - /* lint_on */ - input logic [31:0] PWDATA, - input logic PWRITE, - input logic PSEL, - input logic PENABLE, - output logic [31:0] PRDATA, - output logic PREADY, - output logic PSLVERR, - - input logic rx_i, // Receiver input - output logic tx_o, // Transmitter output - - output logic event_o // interrupt/event output -); - // register addresses - parameter RBR = 3'h0, THR = 3'h0, DLL = 3'h0, IER = 3'h1, DLM = 3'h1, IIR = 3'h2, - FCR = 3'h2, LCR = 3'h3, MCR = 3'h4, LSR = 3'h5, MSR = 3'h6, SCR = 3'h7; - - parameter TX_FIFO_DEPTH = 16; // in bytes - parameter RX_FIFO_DEPTH = 16; // in bytes - - logic [2:0] register_adr; - logic [9:0][7:0] regs_q, regs_n; - logic [1:0] trigger_level_n, trigger_level_q; - - // receive buffer register, read only - logic [7:0] rx_data; - // parity error - logic parity_error; - logic [3:0] IIR_o; - logic [3:0] clr_int; - - /* verilator lint_off UNOPTFLAT */ - // tx flow control - logic tx_ready; - /* lint_on */ - - // rx flow control - logic apb_rx_ready; - logic rx_valid; - - logic tx_fifo_clr_n, tx_fifo_clr_q; - logic rx_fifo_clr_n, rx_fifo_clr_q; - - logic fifo_tx_valid; - logic tx_valid; - logic fifo_rx_valid; - logic fifo_rx_ready; - logic rx_ready; - - logic [7:0] fifo_tx_data; - logic [8:0] fifo_rx_data; - - logic [7:0] tx_data; - logic [$clog2(TX_FIFO_DEPTH):0] tx_elements; - logic [$clog2(RX_FIFO_DEPTH):0] rx_elements; - - // TODO: check that stop bits are really not necessary here - uart_rx uart_rx_i - ( - .clk_i ( CLK ), - .rstn_i ( RSTN ), - .rx_i ( rx_i ), - .cfg_en_i ( 1'b1 ), - .cfg_div_i ( {regs_q[DLM + 'd8], regs_q[DLL + 'd8]} ), - .cfg_parity_en_i ( regs_q[LCR][3] ), - .cfg_parity_sel_i ( regs_q[LCR][5:4] ), - .cfg_bits_i ( regs_q[LCR][1:0] ), - // .cfg_stop_bits_i ( regs_q[LCR][2] ), - /* verilator lint_off PINCONNECTEMPTY */ - .busy_o ( ), - /* lint_on */ - .err_o ( parity_error ), - .err_clr_i ( 1'b0 ), - .rx_data_o ( rx_data ), - .rx_valid_o ( rx_valid ), - .rx_ready_i ( rx_ready ) - ); - - uart_tx uart_tx_i - ( - .clk_i ( CLK ), - .rstn_i ( RSTN ), - .tx_o ( tx_o ), - /* verilator lint_off PINCONNECTEMPTY */ - .busy_o ( ), - /* lint_on */ - .cfg_en_i ( 1'b1 ), - .cfg_div_i ( {regs_q[DLM + 'd8], regs_q[DLL + 'd8]} ), - .cfg_parity_en_i ( regs_q[LCR][3] ), - .cfg_parity_sel_i ( regs_q[LCR][5:4] ), - .cfg_bits_i ( regs_q[LCR][1:0] ), - .cfg_stop_bits_i ( regs_q[LCR][2] ), - - .tx_data_i ( tx_data ), - .tx_valid_i ( tx_valid ), - .tx_ready_o ( tx_ready ) - ); - - io_generic_fifo - #( - .DATA_WIDTH ( 9 ), - .BUFFER_DEPTH ( RX_FIFO_DEPTH ) - ) - uart_rx_fifo_i - ( - .clk_i ( CLK ), - .rstn_i ( RSTN ), - - .clr_i ( rx_fifo_clr_q ), - - .elements_o ( rx_elements ), - - .data_o ( fifo_rx_data ), - .valid_o ( fifo_rx_valid ), - .ready_i ( fifo_rx_ready ), - - .valid_i ( rx_valid ), - .data_i ( { parity_error, rx_data } ), - .ready_o ( rx_ready ) - ); - - io_generic_fifo - #( - .DATA_WIDTH ( 8 ), - .BUFFER_DEPTH ( TX_FIFO_DEPTH ) - ) - uart_tx_fifo_i - ( - .clk_i ( CLK ), - .rstn_i ( RSTN ), - - .clr_i ( tx_fifo_clr_q ), - - .elements_o ( tx_elements ), - - .data_o ( tx_data ), - .valid_o ( tx_valid ), - .ready_i ( tx_ready ), - - .valid_i ( fifo_tx_valid ), - .data_i ( fifo_tx_data ), - // not needed since we are getting the status via the fifo population - .ready_o ( ) - ); - - uart_interrupt - #( - .TX_FIFO_DEPTH (TX_FIFO_DEPTH), - .RX_FIFO_DEPTH (RX_FIFO_DEPTH) - ) - uart_interrupt_i - ( - .clk_i ( CLK ), - .rstn_i ( RSTN ), - - - .IER_i ( regs_q[IER][2:0] ), // interrupt enable register - - .error_i ( regs_n[LSR][2] ), - .rx_elements_i ( rx_elements ), - .tx_elements_i ( tx_elements ), - .trigger_level_i ( trigger_level_q ), - - .clr_int_i ( clr_int ), // one hot - - .interrupt_o ( event_o ), - .IIR_o ( IIR_o ) - - ); - - // UART Registers - - // register write and update logic - always_comb - begin - regs_n = regs_q; - trigger_level_n = trigger_level_q; - - fifo_tx_valid = 1'b0; - tx_fifo_clr_n = 1'b0; // self clearing - rx_fifo_clr_n = 1'b0; // self clearing - - // rx status - regs_n[LSR][0] = fifo_rx_valid; // fifo is empty - - // parity error on receiving part has occured - regs_n[LSR][2] = fifo_rx_data[8]; // parity error is detected when element is retrieved - - // tx status register - regs_n[LSR][5] = ~ (|tx_elements); // fifo is empty - regs_n[LSR][6] = tx_ready & ~ (|tx_elements); // shift register and fifo are empty - - if (PSEL && PENABLE && PWRITE) - begin - case (register_adr) - - THR: // either THR or DLL - begin - if (regs_q[LCR][7]) // Divisor Latch Access Bit (DLAB) - begin - regs_n[DLL + 'd8] = PWDATA[7:0]; - end - else - begin - fifo_tx_data = PWDATA[7:0]; - fifo_tx_valid = 1'b1; - end - end - - IER: // either IER or DLM - begin - if (regs_q[LCR][7]) // Divisor Latch Access Bit (DLAB) - regs_n[DLM + 'd8] = PWDATA[7:0]; - else - regs_n[IER] = PWDATA[7:0]; - end - - LCR: - regs_n[LCR] = PWDATA[7:0]; - - FCR: // write only register, fifo control register - begin - rx_fifo_clr_n = PWDATA[1]; - tx_fifo_clr_n = PWDATA[2]; - trigger_level_n = PWDATA[7:6]; - end - - endcase - - end - - end - - // register read logic - always_comb - begin - PRDATA = 'b0; - apb_rx_ready = 1'b0; - fifo_rx_ready = 1'b0; - clr_int = 4'b0; - - if (PSEL && PENABLE && !PWRITE) - begin - case (register_adr) - RBR: // either RBR or DLL - begin - if (regs_q[LCR][7]) // Divisor Latch Access Bit (DLAB) - PRDATA = {24'b0, regs_q[DLL + 'd8]}; - else - begin - - fifo_rx_ready = 1'b1; - - PRDATA = {24'b0, fifo_rx_data[7:0]}; - - clr_int = 4'b1000; // clear Received Data Available interrupt - end - end - - LSR: // Line Status Register - begin - PRDATA = {24'b0, regs_q[LSR]}; - clr_int = 4'b1100; // clear parrity interrupt error - end - - LCR: // Line Control Register - PRDATA = {24'b0, regs_q[LCR]}; - - IER: // either IER or DLM - begin - if (regs_q[LCR][7]) // Divisor Latch Access Bit (DLAB) - PRDATA = {24'b0, regs_q[DLM + 'd8]}; - else - PRDATA = {24'b0, regs_q[IER]}; - end - - IIR: // interrupt identification register read only - begin - PRDATA = {24'b0, 1'b1, 1'b1, 2'b0, IIR_o}; - clr_int = 4'b0100; // clear Transmitter Holding Register Empty - end - - default: - PRDATA = '0; - endcase - end - end - - // synchronouse part - always_ff @(posedge CLK, negedge RSTN) - begin - if(~RSTN) - begin - - regs_q[IER] <= 8'h0; - regs_q[IIR] <= 8'h1; - regs_q[LCR] <= 8'h0; - regs_q[MCR] <= 8'h0; - regs_q[LSR] <= 8'h60; - regs_q[MSR] <= 8'h0; - regs_q[SCR] <= 8'h0; - regs_q[DLM + 'd8] <= 8'h0; - regs_q[DLL + 'd8] <= 8'h0; - - trigger_level_q <= 2'b00; - tx_fifo_clr_q <= 1'b0; - rx_fifo_clr_q <= 1'b0; - - end - else - begin - regs_q <= regs_n; - - trigger_level_q <= trigger_level_n; - tx_fifo_clr_q <= tx_fifo_clr_n; - rx_fifo_clr_q <= rx_fifo_clr_n; - - end - end - - assign register_adr = {PADDR[4:2]}; - // APB logic: we are always ready to capture the data into our regs - // not supporting transfare failure - assign PREADY = 1'b1; - assign PSLVERR = 1'b0; -endmodule diff --git a/rtl/e203/perips/apb_uart/apb_uart.v b/rtl/e203/perips/apb_uart/apb_uart.v new file mode 100644 index 0000000..d322302 --- /dev/null +++ b/rtl/e203/perips/apb_uart/apb_uart.v @@ -0,0 +1,299 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module apb_uart_sv +#( + parameter APB_ADDR_WIDTH = 12 //APB slaves are 4KB by default +) +( + input wire CLK, + input wire RSTN, + input wire [APB_ADDR_WIDTH - 1:0] PADDR, + input wire [31:0] PWDATA, + input wire PWRITE, + input wire PSEL, + input wire PENABLE, + output reg [31:0] PRDATA, + output wire PREADY, + output wire PSLVERR, + input wire rx_i, // Receiver input + output wire tx_o, // Transmitter output + output wire event_o // interrupt/event output + +); + + // register addresses + parameter RBR = 3'h0, THR = 3'h0, DLL = 3'h0, IER = 3'h1, DLM = 3'h1, IIR = 3'h2, + FCR = 3'h2, LCR = 3'h3, MCR = 3'h4, LSR = 3'h5, MSR = 3'h6, SCR = 3'h7; + + parameter TX_FIFO_DEPTH = 16; // in bytes + parameter RX_FIFO_DEPTH = 16; // in bytes + + + wire [2:0] register_adr; + reg [79:0] regs_q, regs_n; + reg [1:0] trigger_level_n, trigger_level_q; + + + // receive buffer register, read only + wire [7:0] rx_data; + // parity error + wire parity_error; + wire [3:0] IIR_o; + reg [3:0] clr_int; + // tx flow control + wire tx_ready; + // rx flow control + reg apb_rx_ready; + wire rx_valid; + + reg tx_fifo_clr_n, tx_fifo_clr_q; + reg rx_fifo_clr_n, rx_fifo_clr_q; + + reg fifo_tx_valid; + wire tx_valid; + wire fifo_rx_valid; + reg fifo_rx_ready; + wire rx_ready; + + reg [7:0] fifo_tx_data; + wire [8:0] fifo_rx_data; + wire [7:0] tx_data; + + wire [$clog2(TX_FIFO_DEPTH):0] tx_elements; + wire [$clog2(RX_FIFO_DEPTH):0] rx_elements; + + // TODO: check that stop bits are really not necessary here + uart_rx uart_rx_i( + .clk_i ( CLK ), + .rstn_i ( RSTN ), + .rx_i ( rx_i ), + .cfg_en_i ( 1'b1 ), + .cfg_div_i ( {regs_q[(DLM + 'd8) * 8+:8], regs_q[(DLL + 'd8) * 8+:8]} ), + .cfg_parity_en_i ( regs_q[(LCR * 8) + 3] ), + .cfg_parity_sel_i ( regs_q[(LCR * 8) + 5-:2] ), + .cfg_bits_i ( regs_q[(LCR * 8) + 1-:2] ), + // .cfg_stop_bits_i ( regs_q[(LCR * 8) + 2] ), + .busy_o ( ), + .err_o ( parity_error ), + .err_clr_i ( 1'b0 ), + .rx_data_o ( rx_data ), + .rx_valid_o ( rx_valid ), + .rx_ready_i ( rx_ready ) + ); + + uart_tx uart_tx_i( + .clk_i ( CLK ), + .rstn_i ( RSTN ), + .tx_o ( tx_o ), + .busy_o ( ), + .cfg_en_i ( 1'b1 ), + .cfg_div_i ( {regs_q[(DLM + 'd8) * 8+:8], regs_q[(DLL + 'd8) * 8+:8]} ), + .cfg_parity_en_i ( regs_q[(LCR * 8) + 3] ), + .cfg_parity_sel_i ( regs_q[(LCR * 8) + 5-:2] ), + .cfg_bits_i ( regs_q[(LCR * 8) + 1-:2] ), + .cfg_stop_bits_i ( regs_q[(LCR * 8) + 2] ), + .tx_data_i ( tx_data ), + .tx_valid_i ( tx_valid ), + .tx_ready_o ( tx_ready ) + ); + + io_generic_fifo #( + .DATA_WIDTH (9), + .BUFFER_DEPTH (RX_FIFO_DEPTH) + ) uart_rx_fifo_i( + .clk_i ( CLK ), + .rstn_i ( RSTN ), + .clr_i ( rx_fifo_clr_q ), + .elements_o ( rx_elements ), + .data_o ( fifo_rx_data ), + .valid_o ( fifo_rx_valid ), + .ready_i ( fifo_rx_ready ), + .valid_i ( rx_valid ), + .data_i ( {parity_error, rx_data} ), + .ready_o ( rx_ready ) + ); + + io_generic_fifo #( + .DATA_WIDTH (8), + .BUFFER_DEPTH (TX_FIFO_DEPTH) + ) uart_tx_fifo_i( + .clk_i ( CLK ), + .rstn_i ( RSTN ), + .clr_i ( tx_fifo_clr_q ), + .elements_o ( tx_elements ), + .data_o ( tx_data ), + .valid_o ( tx_valid ), + .ready_i ( tx_ready ), + .valid_i ( fifo_tx_valid ), + .data_i ( fifo_tx_data ), + // not needed since we are getting the status via the fifo population + .ready_o ( ) + ); + + uart_interrupt #( + .TX_FIFO_DEPTH (TX_FIFO_DEPTH), + .RX_FIFO_DEPTH (RX_FIFO_DEPTH) + ) uart_interrupt_i( + .clk_i ( CLK ), + .rstn_i ( RSTN ), + .IER_i ( regs_q[(IER * 8) + 2-:3] ), // interrupt enable register + .error_i ( regs_n[(LSR * 8) + 2] ), + .rx_elements_i ( rx_elements ), + .tx_elements_i ( tx_elements ), + .trigger_level_i ( trigger_level_q ), + .clr_int_i ( clr_int ), // one hot + .interrupt_o ( event_o ), + .IIR_o ( IIR_o ) + ); + + // UART Registers + // register write and update logic + always @(*) begin + regs_n = regs_q; + trigger_level_n = trigger_level_q; + + fifo_tx_valid = 1'b0; + tx_fifo_clr_n = 1'b0; // self clearing + rx_fifo_clr_n = 1'b0; // self clearing + + // rx status + regs_n[LSR * 8] = fifo_rx_valid; // fifo is empty + + // parity error on receiving part has occured + regs_n[(LSR * 8) + 2] = fifo_rx_data[8]; // parity error is detected when element is retrieved + + // tx status register + regs_n[(LSR * 8) + 5] = ~(|tx_elements); // fifo is empty + regs_n[(LSR * 8) + 6] = tx_ready & ~(|tx_elements); // shift register and fifo are empty + + if (PSEL && PENABLE && PWRITE) + begin + case (register_adr) + THR: // either THR or DLL + begin + if (regs_q[(LCR * 8) + 7]) begin // Divisor Latch Access Bit (DLAB) + regs_n[(DLL + 'd8) * 8+:8] = PWDATA[7:0]; + end else begin + fifo_tx_data = PWDATA[7:0]; + fifo_tx_valid = 1'b1; + end + end + + IER: // either IER or DLM + begin + if (regs_q[(LCR * 8) + 7]) // Divisor Latch Access Bit (DLAB) + regs_n[(DLM + 'd8) * 8+:8] = PWDATA[7:0]; + else + regs_n[IER * 8+:8] = PWDATA[7:0]; + end + + LCR: + regs_n[LCR * 8+:8] = PWDATA[7:0]; + + FCR: // write only register, fifo control register + begin + rx_fifo_clr_n = PWDATA[1]; + tx_fifo_clr_n = PWDATA[2]; + trigger_level_n = PWDATA[7:6]; + end + endcase + end + + end + + + // register read logic + always @(*) begin + PRDATA = 'b0; + apb_rx_ready = 1'b0; + fifo_rx_ready = 1'b0; + clr_int = 4'b0; + + if (PSEL && PENABLE && !PWRITE) + begin + case (register_adr) + RBR: // either RBR or DLL + begin + if (regs_q[(LCR * 8) + 7]) // Divisor Latch Access Bit (DLAB) + PRDATA = {24'b0, regs_q[(DLL + 'd8) * 8+:8]}; + else begin + fifo_rx_ready = 1'b1; + PRDATA = {24'b0, fifo_rx_data[7:0]}; + clr_int = 4'b1000; // clear Received Data Available interrupt + end + end + + LSR: // Line Status Register + begin + PRDATA = {24'b0, regs_q[LSR * 8+:8]}; + clr_int = 4'b1100; // clear parrity interrupt error + end + + LCR: // Line Control Register + PRDATA = {24'b0, regs_q[LCR * 8+:8]}; + + IER: // either IER or DLM + begin + if (regs_q[(LCR * 8) + 7]) // Divisor Latch Access Bit (DLAB) + PRDATA = {24'b0, regs_q[(DLM + 'd8) * 8+:8]}; + else + PRDATA = {24'b0, regs_q[IER * 8+:8]}; + end + + IIR: // interrupt identification register read only + begin + PRDATA = {24'b0, 1'b1, 1'b1, 2'b0, IIR_o}; + clr_int = 4'b0100; // clear Transmitter Holding Register Empty + end + + default: + PRDATA = 'b0; + endcase + end + end + + + // synchronouse part + always @(posedge CLK or negedge RSTN) begin + if(~RSTN) begin + + regs_q[IER * 8+:8] <= 8'h00; + regs_q[IIR * 8+:8] <= 8'h01; + regs_q[LCR * 8+:8] <= 8'h00; + regs_q[MCR * 8+:8] <= 8'h00; + regs_q[LSR * 8+:8] <= 8'h60; + regs_q[MSR * 8+:8] <= 8'h00; + regs_q[SCR * 8+:8] <= 8'h00; + regs_q[(DLM + 'd8) * 8+:8] <= 8'h00; + regs_q[(DLL + 'd8) * 8+:8] <= 8'h00; + + trigger_level_q <= 2'b00; + tx_fifo_clr_q <= 1'b0; + rx_fifo_clr_q <= 1'b0; + + end else begin + regs_q <= regs_n; + trigger_level_q <= trigger_level_n; + tx_fifo_clr_q <= tx_fifo_clr_n; + rx_fifo_clr_q <= rx_fifo_clr_n; + end + end + + + assign register_adr = {PADDR[4:2]}; + // APB logic: we are always ready to capture the data into our regs + // not supporting transfare failure + assign PREADY = 1'b1; + assign PSLVERR = 1'b0; + +endmodule diff --git a/rtl/e203/perips/apb_uart/io_generic_fifo.sv b/rtl/e203/perips/apb_uart/io_generic_fifo.sv deleted file mode 100644 index 5a1ab42..0000000 --- a/rtl/e203/perips/apb_uart/io_generic_fifo.sv +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module io_generic_fifo -#( - parameter DATA_WIDTH = 32, - parameter BUFFER_DEPTH = 2, - parameter LOG_BUFFER_DEPTH = $clog2(BUFFER_DEPTH) -) -( - input logic clk_i, - input logic rstn_i, - - input logic clr_i, - - output logic [LOG_BUFFER_DEPTH:0] elements_o, - - output logic [DATA_WIDTH-1 : 0] data_o, - output logic valid_o, - input logic ready_i, - - input logic valid_i, - input logic [DATA_WIDTH-1 : 0] data_i, - output logic ready_o -); - - // Internal data structures - /* verilator lint_off WIDTH */ - logic [LOG_BUFFER_DEPTH-1:0] pointer_in; // location to which we last wrote - logic [LOG_BUFFER_DEPTH-1:0] pointer_out; // location from which we last sent - /* lint_off */ - logic [LOG_BUFFER_DEPTH:0] elements; // number of elements in the buffer - logic [DATA_WIDTH-1:0] buffer [BUFFER_DEPTH - 1 : 0]; - - logic full; - - int unsigned loop1; - - assign full = (elements == BUFFER_DEPTH); - assign elements_o = elements; - - always_ff @(posedge clk_i, negedge rstn_i) - begin: elements_sequential - if (rstn_i == 1'b0) - elements <= 0; - else - begin - if (clr_i) - elements <= 0; - else - begin - // ------------------ - // Are we filling up? - // ------------------ - // One out, none in - if (ready_i && valid_o && (!valid_i || full)) - elements <= elements - 1; - // None out, one in - else if ((!valid_o || !ready_i) && valid_i && !full) - elements <= elements + 1; - // Else, either one out and one in, or none out and none in - stays unchanged - end - end - end - - always_ff @(posedge clk_i, negedge rstn_i) - begin: buffers_sequential - if (rstn_i == 1'b0) - begin - for (loop1 = 0 ; loop1 < BUFFER_DEPTH ; loop1 = loop1 + 1) - buffer[loop1] <= 0; - end - else - begin - // Update the memory - if (valid_i && !full) - buffer[pointer_in] <= data_i; - end - end - - always_ff @(posedge clk_i, negedge rstn_i) - begin: sequential - if (rstn_i == 1'b0) - begin - pointer_out <= 0; - pointer_in <= 0; - end - else - begin - if(clr_i) - begin - pointer_out <= 0; - pointer_in <= 0; - end - else - begin - // ------------------------------------ - // Check what to do with the input side - // ------------------------------------ - // We have some input, increase by 1 the input pointer - if (valid_i && !full) - begin - if (pointer_in == $unsigned(BUFFER_DEPTH - 1)) - pointer_in <= 0; - else - pointer_in <= pointer_in + 1; - end - // Else we don't have any input, the input pointer stays the same - - // ------------------------------------- - // Check what to do with the output side - // ------------------------------------- - // We had pushed one flit out, we can try to go for the next one - if (ready_i && valid_o) - begin - if (pointer_out == $unsigned(BUFFER_DEPTH - 1)) - pointer_out <= 0; - else - pointer_out <= pointer_out + 1; - end - // Else stay on the same output location - end - end - end - - // Update output ports - assign data_o = buffer[pointer_out]; - assign valid_o = (elements != 0); - - assign ready_o = ~full; - -endmodule \ No newline at end of file diff --git a/rtl/e203/perips/apb_uart/io_generic_fifo.v b/rtl/e203/perips/apb_uart/io_generic_fifo.v new file mode 100644 index 0000000..8e67d31 --- /dev/null +++ b/rtl/e203/perips/apb_uart/io_generic_fifo.v @@ -0,0 +1,113 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module io_generic_fifo +#( + parameter DATA_WIDTH = 32, + parameter BUFFER_DEPTH = 2, + parameter LOG_BUFFER_DEPTH = $clog2(BUFFER_DEPTH) +) +( + input wire clk_i, + input wire rstn_i, + input wire clr_i, + output wire [LOG_BUFFER_DEPTH:0] elements_o, + output wire [DATA_WIDTH - 1:0] data_o, + output wire valid_o, + input wire ready_i, + input wire valid_i, + input wire [DATA_WIDTH - 1:0] data_i, + output wire ready_o +); + // Internal data structures + reg [LOG_BUFFER_DEPTH - 1:0] pointer_in; // location to which we last wrote + reg [LOG_BUFFER_DEPTH - 1:0] pointer_out; // location from which we last sent + + reg [LOG_BUFFER_DEPTH:0] elements; // number of elements in the buffer + reg [DATA_WIDTH - 1:0] buffer [BUFFER_DEPTH - 1:0]; + wire full; + + + assign full = (elements == BUFFER_DEPTH); + assign elements_o = elements; + + always @(posedge clk_i or negedge rstn_i) begin : elements_sequential + if (rstn_i == 1'b0) + elements <= 0; + else if (clr_i) + elements <= 0; + // ------------------ + // Are we filling up? + // ------------------ + // One out, none in + else if ((ready_i && valid_o) && (!valid_i || full)) + elements <= elements - 1; + // None out, one in + else if (((!valid_o || !ready_i) && valid_i) && !full) + elements <= elements + 1; + // Else, either one out and one in, or none out and none in - stays unchanged + end + + integer loop1; + always @(posedge clk_i or negedge rstn_i) begin : buffers_sequential + if (rstn_i == 1'b0) begin + for (loop1 = 0; loop1 < BUFFER_DEPTH; loop1 = loop1 + 1) begin + buffer[loop1] <= 0; + end + end else if (valid_i && !full) begin + buffer[pointer_in] <= data_i; // Update the memory + end + end + + always @(posedge clk_i or negedge rstn_i) begin : sequential + if (rstn_i == 1'b0) begin + pointer_out <= 0; + pointer_in <= 0; + end else if (clr_i) begin + pointer_out <= 0; + pointer_in <= 0; + end else begin + + // ------------------------------------ + // Check what to do with the input side + // ------------------------------------ + // We have some input, increase by 1 the input pointer + if (valid_i && !full) begin + if (pointer_in == $unsigned(BUFFER_DEPTH - 1)) + pointer_in <= 0; + else + pointer_in <= pointer_in + 1; + end + // Else we don't have any input, the input pointer stays the same + + + // ------------------------------------- + // Check what to do with the output side + // ------------------------------------- + // We had pushed one flit out, we can try to go for the next one + if (ready_i && valid_o) begin + if (pointer_out == $unsigned(BUFFER_DEPTH - 1)) + pointer_out <= 0; + else + pointer_out <= pointer_out + 1; + end + // Else stay on the same output location + end + end + + + // Update output ports + assign data_o = buffer[pointer_out]; + assign valid_o = (elements != 0); + assign ready_o = ~full; + +endmodule diff --git a/rtl/e203/perips/apb_uart/uart_interrupt.sv b/rtl/e203/perips/apb_uart/uart_interrupt.v similarity index 56% rename from rtl/e203/perips/apb_uart/uart_interrupt.sv rename to rtl/e203/perips/apb_uart/uart_interrupt.v index b0956d3..482a7d1 100644 --- a/rtl/e203/perips/apb_uart/uart_interrupt.sv +++ b/rtl/e203/perips/apb_uart/uart_interrupt.v @@ -16,85 +16,74 @@ module uart_interrupt parameter RX_FIFO_DEPTH = 32 ) ( - input logic clk_i, - input logic rstn_i, + input wire clk_i, + input wire rstn_i, // registers - input logic [2:0] IER_i, // interrupt enable register + input wire [2:0] IER_i, // interrupt enable register // control logic - input logic error_i, - input logic [$clog2(RX_FIFO_DEPTH):0] rx_elements_i, - input logic [$clog2(TX_FIFO_DEPTH):0] tx_elements_i, - input logic [1:0] trigger_level_i, + input wire error_i, + input wire [$clog2(RX_FIFO_DEPTH):0] rx_elements_i, + input wire [$clog2(TX_FIFO_DEPTH):0] tx_elements_i, + input wire [1:0] trigger_level_i, - input logic [3:0] clr_int_i, // one hot + input wire [3:0] clr_int_i, // one hot - output logic interrupt_o, - output logic [3:0] IIR_o + output wire interrupt_o, + output wire [3:0] IIR_o ); - logic [3:0] iir_n, iir_q; - logic trigger_level_reached; + reg [3:0] iir_n; + reg [3:0] iir_q; + reg trigger_level_reached; - always_comb - begin + always @(*) begin trigger_level_reached = 1'b0; case (trigger_level_i) 2'b00: if ($unsigned(rx_elements_i) == 1) - trigger_level_reached = 1'b1; + trigger_level_reached = 1'b1; 2'b01: if ($unsigned(rx_elements_i) == 4) - trigger_level_reached = 1'b1; + trigger_level_reached = 1'b1; 2'b10: if ($unsigned(rx_elements_i) == 8) - trigger_level_reached = 1'b1; + trigger_level_reached = 1'b1; 2'b11: if ($unsigned(rx_elements_i) == 14) - trigger_level_reached = 1'b1; + trigger_level_reached = 1'b1; endcase end - always_comb - begin - if (clr_int_i == 4'b0) - begin + always @(*) begin + if (clr_int_i == 4'b0) begin // Receive data parity error if (IER_i[2] & error_i) - iir_n = 4'b1100; + iir_n = 4'b1100; // Trigger level reached in FIFO mode else if (IER_i[0] & trigger_level_reached) - iir_n = 4'b1000; + iir_n = 4'b1000; // Transmitter holding register empty - else if (IER_i[1] & tx_elements_i == 0) - iir_n = 4'b0100; - else - iir_n = iir_q; + else if (IER_i[1] & (tx_elements_i == 0)) + iir_n = 4'b0100; + else + iir_n = iir_q; + end else begin + iir_n = iir_q & ~clr_int_i; end - else - begin - iir_n = iir_q & ~(clr_int_i); - end - end - always_ff @(posedge clk_i, negedge rstn_i) - begin + always @(posedge clk_i or negedge rstn_i) begin if (~rstn_i) - begin - iir_q <= 4'b0001; - end + iir_q <= 4'b0001; else - begin - iir_q <= iir_n; - end + iir_q <= iir_n; end assign IIR_o = iir_q; assign interrupt_o = ~iir_q[0]; endmodule - diff --git a/rtl/e203/perips/apb_uart/uart_rx.sv b/rtl/e203/perips/apb_uart/uart_rx.sv deleted file mode 100644 index 17b2b9f..0000000 --- a/rtl/e203/perips/apb_uart/uart_rx.sv +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// -- Adaptable modifications made for hbirdv2 SoC. -- -// Copyright 2020 Nuclei System Technology, Inc. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module uart_rx ( - input logic clk_i, - input logic rstn_i, - input logic rx_i, - input logic [15:0] cfg_div_i, - input logic cfg_en_i, - input logic cfg_parity_en_i, - input logic [1:0] cfg_parity_sel_i, - input logic [1:0] cfg_bits_i, - // input logic cfg_stop_bits_i, - output logic busy_o, - output logic err_o, - input logic err_clr_i, - output logic [7:0] rx_data_o, - output logic rx_valid_o, - input logic rx_ready_i - ); - - enum logic [2:0] {IDLE,START_BIT,DATA,SAVE_DATA,PARITY,STOP_BIT} CS, NS; - - logic [7:0] reg_data; - logic [7:0] reg_data_next; - - logic [2:0] reg_rx_sync; - - - logic [2:0] reg_bit_count; - logic [2:0] reg_bit_count_next; - - logic [2:0] s_target_bits; - - logic parity_bit; - logic parity_bit_next; - - logic sampleData; - - logic [15:0] baud_cnt; - logic baudgen_en; - logic bit_done; - - logic start_bit; - logic set_error; - logic s_rx_fall; - - - assign busy_o = (CS != IDLE); - - always_comb - begin - case(cfg_bits_i) - 2'b00: - s_target_bits = 3'h4; - 2'b01: - s_target_bits = 3'h5; - 2'b10: - s_target_bits = 3'h6; - 2'b11: - s_target_bits = 3'h7; - endcase - end - - always_comb - begin - NS = CS; - sampleData = 1'b0; - reg_bit_count_next = reg_bit_count; - reg_data_next = reg_data; - rx_valid_o = 1'b0; - baudgen_en = 1'b0; - start_bit = 1'b0; - parity_bit_next = parity_bit; - set_error = 1'b0; - - case(CS) - IDLE: - begin - if (s_rx_fall) - begin - NS = START_BIT; - baudgen_en = 1'b1; - start_bit = 1'b1; - end - end - - START_BIT: - begin - parity_bit_next = 1'b0; - baudgen_en = 1'b1; - start_bit = 1'b1; - if (bit_done) - NS = DATA; - end - - DATA: - begin - baudgen_en = 1'b1; - parity_bit_next = parity_bit ^ reg_rx_sync[2]; - case(cfg_bits_i) - 2'b00: - reg_data_next = {3'b000,reg_rx_sync[2],reg_data[4:1]}; - 2'b01: - reg_data_next = {2'b00,reg_rx_sync[2],reg_data[5:1]}; - 2'b10: - reg_data_next = {1'b0,reg_rx_sync[2],reg_data[6:1]}; - 2'b11: - reg_data_next = {reg_rx_sync[2],reg_data[7:1]}; - endcase - - if (bit_done) - begin - sampleData = 1'b1; - if (reg_bit_count == s_target_bits) - begin - reg_bit_count_next = 'h0; - NS = SAVE_DATA; - end - else - begin - reg_bit_count_next = reg_bit_count + 1; - end - end - end - SAVE_DATA: - begin - baudgen_en = 1'b1; - rx_valid_o = 1'b1; - if(rx_ready_i) - if (cfg_parity_en_i) - NS = PARITY; - else - NS = STOP_BIT; - end - PARITY: - begin - baudgen_en = 1'b1; - if (bit_done) - begin - case(cfg_parity_sel_i) - 2'b00: - begin - if(reg_rx_sync[2] != ~parity_bit) - set_error = 1'b1; - end - 2'b01: - begin - if(reg_rx_sync[2] != parity_bit) - set_error = 1'b1; - end - 2'b10: - begin - if(reg_rx_sync[2] != 1'b0) - set_error = 1'b1; - end - 2'b11: - begin - if(reg_rx_sync[2] != 1'b1) - set_error = 1'b1; - end - endcase - NS = STOP_BIT; - end - end - STOP_BIT: - begin - baudgen_en = 1'b1; - if (bit_done) - begin - NS = IDLE; - end - end - default: - NS = IDLE; - endcase - end - - always_ff @(posedge clk_i or negedge rstn_i) - begin - if (rstn_i == 1'b0) - begin - CS <= IDLE; - reg_data <= 8'hFF; - reg_bit_count <= 'h0; - parity_bit <= 1'b0; - end - else - begin - if(bit_done) - parity_bit <= parity_bit_next; - if(sampleData) - reg_data <= reg_data_next; - - reg_bit_count <= reg_bit_count_next; - if(cfg_en_i) - CS <= NS; - else - CS <= IDLE; - end - end - - assign s_rx_fall = ~reg_rx_sync[1] & reg_rx_sync[2]; - always_ff @(posedge clk_i or negedge rstn_i) - begin - if (rstn_i == 1'b0) - reg_rx_sync <= 3'b111; - else - begin - if (cfg_en_i) - reg_rx_sync <= {reg_rx_sync[1:0],rx_i}; - else - reg_rx_sync <= 3'b111; - end - end - - always_ff @(posedge clk_i or negedge rstn_i) - begin - if (rstn_i == 1'b0) - begin - baud_cnt <= 'h0; - bit_done <= 1'b0; - end - else - begin - if(baudgen_en) - begin - if(!start_bit && (baud_cnt == cfg_div_i)) - begin - baud_cnt <= 'h0; - bit_done <= 1'b1; - end - else if(start_bit && (baud_cnt == {1'b0,cfg_div_i[15:1]})) - begin - baud_cnt <= 'h0; - bit_done <= 1'b1; - end - else - begin - baud_cnt <= baud_cnt + 1; - bit_done <= 1'b0; - end - end - else - begin - baud_cnt <= 'h0; - bit_done <= 1'b0; - end - end - end - - always_ff @(posedge clk_i or negedge rstn_i) - begin - if (rstn_i == 1'b0) - begin - err_o <= 1'b0; - end - else - begin - if(err_clr_i) - begin - err_o <= 1'b0; - end - else - begin - if(set_error) - err_o <= 1'b1; - end - end - end - - assign rx_data_o = reg_data; - -endmodule diff --git a/rtl/e203/perips/apb_uart/uart_rx.v b/rtl/e203/perips/apb_uart/uart_rx.v new file mode 100644 index 0000000..34bd15d --- /dev/null +++ b/rtl/e203/perips/apb_uart/uart_rx.v @@ -0,0 +1,216 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module uart_rx ( + input wire clk_i, + input wire rstn_i, + input wire rx_i, + input wire [15:0] cfg_div_i, + input wire cfg_en_i, + input wire cfg_parity_en_i, + input wire [1:0] cfg_parity_sel_i, + input wire [1:0] cfg_bits_i, + // input wire cfg_stop_bits_i, + output wire busy_o, + output reg err_o, + input wire err_clr_i, + output wire [7:0] rx_data_o, + output reg rx_valid_o, + input wire rx_ready_i +); + + localparam [2:0] IDLE = 0; + localparam [2:0] START_BIT = 1; + localparam [2:0] DATA = 2; + localparam [2:0] SAVE_DATA = 3; + localparam [2:0] PARITY = 4; + localparam [2:0] STOP_BIT = 5; + + reg [2:0] CS, NS; + + reg [7:0] reg_data; + reg [7:0] reg_data_next; + reg [2:0] reg_rx_sync; + reg [2:0] reg_bit_count; + reg [2:0] reg_bit_count_next; + + reg [2:0] s_target_bits; + + reg parity_bit; + reg parity_bit_next; + + reg sampleData; + + reg [15:0] baud_cnt; + reg baudgen_en; + reg bit_done; + + reg start_bit; + reg set_error; + wire s_rx_fall; + + assign busy_o = (CS != IDLE); + + always @(*) begin + case (cfg_bits_i) + 2'b00: s_target_bits = 3'h4; + 2'b01: s_target_bits = 3'h5; + 2'b10: s_target_bits = 3'h6; + 2'b11: s_target_bits = 3'h7; + endcase + end + + + always @(*) begin + NS = CS; + sampleData = 1'b0; + reg_bit_count_next = reg_bit_count; + reg_data_next = reg_data; + rx_valid_o = 1'b0; + baudgen_en = 1'b0; + start_bit = 1'b0; + parity_bit_next = parity_bit; + set_error = 1'b0; + + case (CS) + IDLE: begin + if (s_rx_fall) begin + NS = START_BIT; + baudgen_en = 1'b1; + start_bit = 1'b1; + end + end + START_BIT: begin + parity_bit_next = 1'b0; + baudgen_en = 1'b1; + start_bit = 1'b1; + if (bit_done) NS = DATA; + end + DATA: begin + baudgen_en = 1'b1; + parity_bit_next = parity_bit ^ reg_rx_sync[2]; + + case (cfg_bits_i) + 2'b00: reg_data_next = {3'b0, reg_rx_sync[2], reg_data[4:1]}; + 2'b01: reg_data_next = {2'b0, reg_rx_sync[2], reg_data[5:1]}; + 2'b10: reg_data_next = {1'b0, reg_rx_sync[2], reg_data[6:1]}; + 2'b11: reg_data_next = {reg_rx_sync[2], reg_data[7:1]}; + endcase + + if (bit_done) begin + sampleData = 1'b1; + if (reg_bit_count == s_target_bits) begin + reg_bit_count_next = 'h0; + NS = SAVE_DATA; + end else begin + reg_bit_count_next = reg_bit_count + 1; + end + end + end + SAVE_DATA: begin + baudgen_en = 1'b1; + rx_valid_o = 1'b1; + if (rx_ready_i) begin + if (cfg_parity_en_i) NS = PARITY; + else NS = STOP_BIT; + end + end + PARITY: begin + baudgen_en = 1'b1; + if (bit_done) begin + case (cfg_parity_sel_i) + 2'b00: + if (reg_rx_sync[2] != ~parity_bit) set_error = 1'b1; + 2'b01: + if (reg_rx_sync[2] != parity_bit) set_error = 1'b1; + 2'b10: + if (reg_rx_sync[2] != 1'b0) set_error = 1'b1; + 2'b11: + if (reg_rx_sync[2] != 1'b1) set_error = 1'b1; + endcase + NS = STOP_BIT; + end + end + STOP_BIT: begin + baudgen_en = 1'b1; + if (bit_done) NS = IDLE; + end + default: NS = IDLE; + endcase + end + + + always @(posedge clk_i or negedge rstn_i) begin + if (rstn_i == 1'b0) begin + CS <= IDLE; + reg_data <= 8'hff; + reg_bit_count <= 'h0; + parity_bit <= 1'b0; + end else begin + if (bit_done) + parity_bit <= parity_bit_next; + if (sampleData) + reg_data <= reg_data_next; + + reg_bit_count <= reg_bit_count_next; + + if (cfg_en_i) + CS <= NS; + else + CS <= IDLE; + end + end + + assign s_rx_fall = ~reg_rx_sync[1] & reg_rx_sync[2]; + + always @(posedge clk_i or negedge rstn_i) begin + if (rstn_i == 1'b0) + reg_rx_sync <= 3'b111; + else if (cfg_en_i) + reg_rx_sync <= {reg_rx_sync[1:0], rx_i}; + else + reg_rx_sync <= 3'b111; + end + + always @(posedge clk_i or negedge rstn_i) begin + if (rstn_i == 1'b0) begin + baud_cnt <= 'h0; + bit_done <= 1'b0; + end else if (baudgen_en) begin + if (!start_bit && (baud_cnt == cfg_div_i)) begin + baud_cnt <= 'h0; + bit_done <= 1'b1; + end else if (start_bit && (baud_cnt == {1'b0, cfg_div_i[15:1]})) begin + baud_cnt <= 'h0; + bit_done <= 1'b1; + end else begin + baud_cnt <= baud_cnt + 1; + bit_done <= 1'b0; + end + end else begin + baud_cnt <= 'h0; + bit_done <= 1'b0; + end + end + + + always @(posedge clk_i or negedge rstn_i) + if (rstn_i == 1'b0) + err_o <= 1'b0; + else if (err_clr_i) + err_o <= 1'b0; + else if (set_error) + err_o <= 1'b1; + + assign rx_data_o = reg_data; + +endmodule diff --git a/rtl/e203/perips/apb_uart/uart_tx.sv b/rtl/e203/perips/apb_uart/uart_tx.sv deleted file mode 100644 index 6efa9b0..0000000 --- a/rtl/e203/perips/apb_uart/uart_tx.sv +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2017 ETH Zurich and University of Bologna. -// -- Adaptable modifications made for hbirdv2 SoC. -- -// Copyright 2020 Nuclei System Technology, Inc. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the “License”); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module uart_tx ( - input logic clk_i, - input logic rstn_i, - output logic tx_o, - output logic busy_o, - input logic cfg_en_i, - input logic [15:0] cfg_div_i, - input logic cfg_parity_en_i, - input logic [1:0] cfg_parity_sel_i, - input logic [1:0] cfg_bits_i, - input logic cfg_stop_bits_i, - input logic [7:0] tx_data_i, - input logic tx_valid_i, - output logic tx_ready_o - ); - - enum logic [2:0] {IDLE,START_BIT,DATA,PARITY,STOP_BIT_FIRST,STOP_BIT_LAST} CS,NS; - - logic [7:0] reg_data; - logic [7:0] reg_data_next; - - - logic [2:0] reg_bit_count; - logic [2:0] reg_bit_count_next; - - logic [2:0] s_target_bits; - - logic parity_bit; - logic parity_bit_next; - - logic sampleData; - - logic [15:0] baud_cnt; - logic baudgen_en; - logic bit_done; - - assign busy_o = (CS != IDLE); - - always_comb - begin - case(cfg_bits_i) - 2'b00: - s_target_bits = 3'h4; - 2'b01: - s_target_bits = 3'h5; - 2'b10: - s_target_bits = 3'h6; - 2'b11: - s_target_bits = 3'h7; - endcase - end - - always_comb - begin - NS = CS; - tx_o = 1'b1; - sampleData = 1'b0; - reg_bit_count_next = reg_bit_count; - reg_data_next = {1'b1,reg_data[7:1]}; - tx_ready_o = 1'b0; - baudgen_en = 1'b0; - parity_bit_next = parity_bit; - case(CS) - IDLE: - begin - if (cfg_en_i) - tx_ready_o = 1'b1; - if (tx_valid_i) - begin - NS = START_BIT; - sampleData = 1'b1; - reg_data_next = tx_data_i; - end - end - - START_BIT: - begin - tx_o = 1'b0; - parity_bit_next = 1'b0; - baudgen_en = 1'b1; - if (bit_done) - NS = DATA; - end - - DATA: - begin - tx_o = reg_data[0]; - baudgen_en = 1'b1; - parity_bit_next = parity_bit ^ reg_data[0]; - if (bit_done) - begin - if (reg_bit_count == s_target_bits) - begin - reg_bit_count_next = 'h0; - if (cfg_parity_en_i) - begin - NS = PARITY; - end - else - begin - NS = STOP_BIT_FIRST; - end - end - else - begin - reg_bit_count_next = reg_bit_count + 1; - sampleData = 1'b1; - end - end - end - - PARITY: - begin - case(cfg_parity_sel_i) - 2'b00: - tx_o = ~parity_bit; - 2'b01: - tx_o = parity_bit; - 2'b10: - tx_o = 1'b0; - 2'b11: - tx_o = 1'b1; - endcase - - baudgen_en = 1'b1; - if (bit_done) - NS = STOP_BIT_FIRST; - end - STOP_BIT_FIRST: - begin - tx_o = 1'b1; - baudgen_en = 1'b1; - if (bit_done) - begin - if (cfg_stop_bits_i) - NS = STOP_BIT_LAST; - else - NS = IDLE; - end - end - STOP_BIT_LAST: - begin - tx_o = 1'b1; - baudgen_en = 1'b1; - if (bit_done) - begin - NS = IDLE; - end - end - default: - NS = IDLE; - endcase - end - - always_ff @(posedge clk_i or negedge rstn_i) - begin - if (rstn_i == 1'b0) - begin - CS <= IDLE; - reg_data <= 8'hFF; - reg_bit_count <= 'h0; - parity_bit <= 1'b0; - end - else - begin - if(bit_done) - begin - parity_bit <= parity_bit_next; - end - - if(sampleData) - begin - reg_data <= reg_data_next; - end - - reg_bit_count <= reg_bit_count_next; - if(cfg_en_i) - CS <= NS; - else - CS <= IDLE; - end - end - - always_ff @(posedge clk_i or negedge rstn_i) - begin - if (rstn_i == 1'b0) - begin - baud_cnt <= 'h0; - bit_done <= 1'b0; - end - else - begin - if(baudgen_en) - begin - if(baud_cnt == cfg_div_i) - begin - baud_cnt <= 'h0; - bit_done <= 1'b1; - end - else - begin - baud_cnt <= baud_cnt + 1; - bit_done <= 1'b0; - end - end - else - begin - baud_cnt <= 'h0; - bit_done <= 1'b0; - end - end - end - - - //synopsys translate_off - always_ff @(posedge clk_i or negedge rstn_i) - begin - if (tx_valid_i & tx_ready_o & rstn_i) begin - $fwrite(32'h80000002,"%c",tx_data_i); - end - end - //synopsys translate_on - - -endmodule diff --git a/rtl/e203/perips/apb_uart/uart_tx.v b/rtl/e203/perips/apb_uart/uart_tx.v new file mode 100644 index 0000000..ef5c59d --- /dev/null +++ b/rtl/e203/perips/apb_uart/uart_tx.v @@ -0,0 +1,192 @@ +// Copyright 2017 ETH Zurich and University of Bologna. +// -- Adaptable modifications made for hbirdv2 SoC. -- +// Copyright 2020 Nuclei System Technology, Inc. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the “License”); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module uart_tx ( + input wire clk_i, + input wire rstn_i, + output reg tx_o, + output wire busy_o, + input wire cfg_en_i, + input wire [15:0] cfg_div_i, + input wire cfg_parity_en_i, + input wire [1:0] cfg_parity_sel_i, + input wire [1:0] cfg_bits_i, + input wire cfg_stop_bits_i, + input wire [7:0] tx_data_i, + input wire tx_valid_i, + output reg tx_ready_o +); + + localparam [2:0] IDLE = 0; + localparam [2:0] START_BIT = 1; + localparam [2:0] DATA = 2; + localparam [2:0] PARITY = 3; + localparam [2:0] STOP_BIT_FIRST = 4; + localparam [2:0] STOP_BIT_LAST = 5; + + reg [2:0] CS,NS; + + reg [7:0] reg_data; + reg [7:0] reg_data_next; + reg [2:0] reg_bit_count; + reg [2:0] reg_bit_count_next; + + reg [2:0] s_target_bits; + + reg parity_bit; + reg parity_bit_next; + + reg sampleData; + + reg [15:0] baud_cnt; + reg baudgen_en; + reg bit_done; + + assign busy_o = (CS != IDLE); + + always @(*) begin + case (cfg_bits_i) + 2'b00: s_target_bits = 3'h4; + 2'b01: s_target_bits = 3'h5; + 2'b10: s_target_bits = 3'h6; + 2'b11: s_target_bits = 3'h7; + endcase + end + + always @(*) begin + NS = CS; + tx_o = 1'b1; + sampleData = 1'b0; + reg_bit_count_next = reg_bit_count; + reg_data_next = {1'b1, reg_data[7:1]}; + tx_ready_o = 1'b0; + baudgen_en = 1'b0; + parity_bit_next = parity_bit; + + case (CS) + IDLE: begin + if (cfg_en_i) + tx_ready_o = 1'b1; + if (tx_valid_i) begin + NS = START_BIT; + sampleData = 1'b1; + reg_data_next = tx_data_i; + end + end + START_BIT: begin + tx_o = 1'b0; + parity_bit_next = 1'b0; + baudgen_en = 1'b1; + if (bit_done) + NS = DATA; + end + DATA: begin + tx_o = reg_data[0]; + baudgen_en = 1'b1; + parity_bit_next = parity_bit ^ reg_data[0]; + + if (bit_done) begin + if (reg_bit_count == s_target_bits) begin + reg_bit_count_next = 'h0; + if (cfg_parity_en_i) + NS = PARITY; + else + NS = STOP_BIT_FIRST; + end else begin + reg_bit_count_next = reg_bit_count + 1; + sampleData = 1'b1; + end + end + end + PARITY: begin + case (cfg_parity_sel_i) + 2'b00: tx_o = ~parity_bit; + 2'b01: tx_o = parity_bit; + 2'b10: tx_o = 1'b0; + 2'b11: tx_o = 1'b1; + endcase + + baudgen_en = 1'b1; + + if (bit_done) + NS = STOP_BIT_FIRST; + end + STOP_BIT_FIRST: begin + tx_o = 1'b1; + baudgen_en = 1'b1; + + if (bit_done) begin + if (cfg_stop_bits_i) + NS = STOP_BIT_LAST; + else + NS = IDLE; + end + end + STOP_BIT_LAST: begin + tx_o = 1'b1; + baudgen_en = 1'b1; + if (bit_done) + NS = IDLE; + end + default: NS = IDLE; + endcase + end + + + always @(posedge clk_i or negedge rstn_i) begin + if (rstn_i == 1'b0) begin + CS <= IDLE; + reg_data <= 8'hff; + reg_bit_count <= 'h0; + parity_bit <= 1'b0; + end else begin + if (bit_done) + parity_bit <= parity_bit_next; + if (sampleData) + reg_data <= reg_data_next; + + reg_bit_count <= reg_bit_count_next; + + if (cfg_en_i) + CS <= NS; + else + CS <= IDLE; + end + end + + always @(posedge clk_i or negedge rstn_i) begin + if (rstn_i == 1'b0) begin + baud_cnt <= 'h0; + bit_done <= 1'b0; + end else if (baudgen_en) begin + if (baud_cnt == cfg_div_i) begin + baud_cnt <= 'h0; + bit_done <= 1'b1; + end + else begin + baud_cnt <= baud_cnt + 1; + bit_done <= 1'b0; + end + end else begin + baud_cnt <= 'h0; + bit_done <= 1'b0; + end + end + + //synopsys translate_off + always @(posedge clk_i or negedge rstn_i) begin + if ((tx_valid_i & tx_ready_o) & rstn_i) + $fwrite(32'h80000002, "%c", tx_data_i); + end + //synopsys translate_on + +endmodule diff --git a/rtl/e203/perips/sirv_otp_top.v b/rtl/e203/perips/sirv_otp_top.v deleted file mode 100644 index 42ad744..0000000 --- a/rtl/e203/perips/sirv_otp_top.v +++ /dev/null @@ -1,65 +0,0 @@ - /* - Copyright 2018-2020 Nuclei System Technology, Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - - - -//===================================================================== -// -// Designer : Bob Hu -// -// Description: -// The top level module of otp -// -// ==================================================================== - -module sirv_otp_top( - input clk, - input rst_n, - - input i_icb_cmd_valid, - output i_icb_cmd_ready, - input [32-1:0] i_icb_cmd_addr, - input i_icb_cmd_read, - input [32-1:0] i_icb_cmd_wdata, - - output i_icb_rsp_valid, - input i_icb_rsp_ready, - output [32-1:0] i_icb_rsp_rdata, - - input f_icb_cmd_valid, - output f_icb_cmd_ready, - input [32-1:0] f_icb_cmd_addr, - input f_icb_cmd_read, - input [32-1:0] f_icb_cmd_wdata, - - output f_icb_rsp_valid, - input f_icb_rsp_ready, - output [32-1:0] f_icb_rsp_rdata -); - - assign i_icb_cmd_ready = 1'b0; - - assign i_icb_rsp_valid = 1'b0; - assign i_icb_rsp_rdata = 32'b0; - - assign f_icb_cmd_ready = 1'b0; - - assign f_icb_rsp_valid = 1'b0; - assign f_icb_rsp_rdata = 32'b0; - - // In FPGA platform this module is just an empty wrapper - -endmodule diff --git a/rtl/e203/perips/sirv_plic_man.v b/rtl/e203/perips/sirv_plic_man.v index 8263198..7b95e0e 100644 --- a/rtl/e203/perips/sirv_plic_man.v +++ b/rtl/e203/perips/sirv_plic_man.v @@ -71,8 +71,8 @@ localparam PLIC_PEND_ARRAY = (((PLIC_IRQ_NUM-1)/32) + 1); wire [PLIC_IRQ_NUM-1:0] irq_i_gated_ready; wire [PLIC_IRQ_NUM-1:0] irq_i_gated_hsked; - reg [PLIC_IRQ_NUM-1:0] icb_claim_irq; - reg [PLIC_IRQ_NUM-1:0] icb_complete_irq; + wire [PLIC_IRQ_NUM-1:0] icb_claim_irq; + wire [PLIC_IRQ_NUM-1:0] icb_complete_irq; wire irq_o; @@ -509,16 +509,11 @@ localparam PLIC_PEND_ARRAY = (((PLIC_IRQ_NUM-1)/32) + 1); // for(i=0; i