initial commit

This commit is contained in:
2026-04-12 22:20:18 +08:00
commit 190c2edbb2
155 changed files with 36314 additions and 0 deletions

View File

@@ -0,0 +1,711 @@
/*------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Copyright (c) 2016, Loongson Technology Corporation Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. Neither the name of Loongson Technology Corporation Limited nor the names of
its contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL LOONGSON TECHNOLOGY CORPORATION LIMITED BE LIABLE
TO ANY PARTY FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
------------------------------------------------------------------------------*/
`include "uart_defines.h"
`define UART_DL1 7:0
`define UART_DL2 15:8
`define UART_DL3 23:16
module uart_regs (clk, rst, clk_carrier,
addr, dat_i, dat_o, we, re,
modem_inputs,
rts_pad_o, dtr_pad_o,
stx_pad_o,TXD_i,srx_pad_i,RXD_o,
int_o,
usart_mode,
rx_en,
tx2rx_en
);
input clk;
input rst ;
input clk_carrier;
input [2:0] addr;
input [7:0] dat_i;
output [7:0] dat_o;
input we;
input re;
output stx_pad_o;
input srx_pad_i;
input TXD_i;
output RXD_o;
input [3:0] modem_inputs;
output rts_pad_o;
output dtr_pad_o;
output int_o;
output usart_mode;
output tx2rx_en;
output rx_en;
wire [3:0] modem_inputs;
reg enable;
wire stx_pad_o;
wire srx_pad_i;
wire srx_pad;
reg [7:0] dat_o;
wire [2:0] addr;
wire [7:0] dat_i;
reg [3:0] ier;
reg [3:0] iir;
reg [1:0] fcr;
reg [4:0] mcr;
reg infrared;
reg rx_pol;
reg [7:0] lcr;
reg [7:0] msr;
reg [23:0] dl;
reg start_dlc;
reg lsr_mask_d;
reg msi_reset;
reg [15:0] dlc;
reg int_o;
reg [3:0] trigger_level;
reg rx_reset;
reg tx_reset;
wire dlab;
wire usart_mode;
wire usart_rx_en;
wire usart_tx_en;
wire tx2rx_en;
reg sclk_reg;
reg sclk_en_reg;
reg [7:0] mode_reg;
reg [7:0] fi_di_reg;
reg [7:0] sclk_count;
reg [2:0] repeat_reg;
wire usart_normal;
wire usart_irda;
wire usart_t0;
wire usart_t1;
wire rx_en;
wire tx_en;
wire sclk_por;
assign usart_normal = mode_reg[1:0]==2'h0;
assign usart_irda = mode_reg[1:0]==2'h1;
assign usart_t0 = mode_reg[1:0]==2'h2;
assign usart_t1 = mode_reg[1:0]==2'h3;
assign usart_tx_en = mode_reg[2]==1'b0;
assign usart_rx_en = mode_reg[2]==1'b1;
assign sclk_por = mode_reg[3];
assign RXD_o = sclk_reg^sclk_por;
assign usart_mode = usart_t0 || usart_t1;
assign rx_en = usart_normal || usart_irda || usart_mode && usart_rx_en;
assign tx_en = usart_normal || usart_irda || usart_mode && usart_tx_en;
always @(posedge clk )
begin
if (rst) begin
mode_reg <= 8'h0;
fi_di_reg <= 8'h0;
repeat_reg<= 3'h4;
sclk_en_reg<= 1'b0;
end
else if (we && addr==`UART_REG_SR)begin
if(dlab)
fi_di_reg <= dat_i;
else
mode_reg <= dat_i;
end
else begin
if(enable) sclk_en_reg <= mode_reg[4];
repeat_reg <= mode_reg[7:5];
end
end
always @(posedge clk)
begin
if(rst) begin
sclk_count <= 8'b0;
sclk_reg <=1'b0;
end
else if(usart_mode&&(fi_di_reg>8'h1)&&sclk_en_reg) begin
if(sclk_count == fi_di_reg[7:1]) begin
sclk_reg <= 1'b1;
sclk_count <= sclk_count + 1'b1;
end
else if(sclk_count == fi_di_reg) begin
sclk_reg <= 1'b0;
sclk_count <= 8'b0;
end
else begin
sclk_count <= sclk_count + 1'b1;
end
end
else begin
sclk_reg <=1'b0;
sclk_count <= 8'b0;
end
end
wire cts_pad_i, dsr_pad_i, ri_pad_i, dcd_pad_i;
wire loopback;
wire cts, dsr, ri, dcd;
wire cts_c, dsr_c, ri_c, dcd_c;
wire rts_pad_o, dtr_pad_o;
wire [7:0] lsr;
wire lsr0, lsr1, lsr2, lsr3, lsr4, lsr5, lsr6, lsr7;
reg lsr0r, lsr1r, lsr2r, lsr3r, lsr4r, lsr5r, lsr6r, lsr7r;
wire lsr_mask;
assign lsr[7:0] = { lsr7r, lsr6r, lsr5r, lsr4r, lsr3r, lsr2r, lsr1r, lsr0r };
assign {cts_pad_i, dsr_pad_i, ri_pad_i, dcd_pad_i} = modem_inputs;
assign {cts, dsr, ri, dcd} = ~{cts_pad_i,dsr_pad_i,ri_pad_i,dcd_pad_i};
assign {cts_c, dsr_c, ri_c, dcd_c} = loopback ? {mcr[`UART_MC_RTS],mcr[`UART_MC_DTR],mcr[`UART_MC_OUT1],mcr[`UART_MC_OUT2]}
: {cts_pad_i,dsr_pad_i,ri_pad_i,dcd_pad_i};
assign dlab = lcr[`UART_LC_DL];
assign loopback = mcr[4];
assign rts_pad_o = mcr[`UART_MC_RTS];
assign dtr_pad_o = mcr[`UART_MC_DTR];
wire rls_int;
wire rda_int;
wire ti_int;
wire thre_int;
wire ms_int;
wire tf_push;
reg rf_pop;
wire [`UART_FIFO_REC_WIDTH-1:0] rf_data_out;
wire rf_error_bit;
wire [`UART_FIFO_COUNTER_W-1:0] rf_count;
wire [`UART_FIFO_COUNTER_W-1:0] tf_count;
wire [2:0] tstate;
wire [3:0] rstate;
wire [9:0] counter_t;
wire thre_set_en;
reg [7:0] block_cnt;
reg [7:0] block_value;
wire current_finish;
wire max_repeat_time;
wire serial_out;
wire serial_out_modulated = ~ (clk_carrier & serial_out);
uart_transmitter transmitter(.clk(clk), .wb_rst_i(rst), .lcr(lcr), .tf_push(tf_push), .wb_dat_i(dat_i),
.tx2rx_en (tx2rx_en),
.usart_mode(usart_mode),
.srx_pad_i(TXD_i),
.enable (enable && tx_en),
.usart_t0(usart_t0),
.repeat_time(repeat_reg ),
.current_finish(current_finish),
.max_repeat_time(max_repeat_time),
.stx_pad_o(serial_out), .tstate(tstate), .tf_count(tf_count),
.tx_reset(tx_reset), .lsr_mask(lsr_mask));
wire rcv_pad_i;
assign rcv_pad_i = ~usart_mode ? srx_pad_i : (rx_en ? TXD_i : 1'b1);
uart_sync_flops i_uart_sync_flops(
.rst_i (rst),
.clk_i (clk),
.stage1_rst_i (1'b0),
.stage1_clk_en_i (1'b1),
.async_dat_i (rcv_pad_i),
.sync_dat_o (srx_pad)
);
defparam i_uart_sync_flops.width = 1;
defparam i_uart_sync_flops.init_value = 1'b1;
wire serial_in = loopback ? serial_out : rx_pol ? ~srx_pad : srx_pad;
assign stx_pad_o = loopback ? 1'b1 : infrared ? serial_out_modulated : serial_out;
wire rf_overrun;
wire rf_push_pulse;
uart_receiver receiver(.clk(clk), .wb_rst_i(rst), .lcr(lcr), .rf_pop(rf_pop), .srx_pad_i(serial_in),
.enable(enable && rx_en),
.counter_t(counter_t), .rf_count(rf_count), .rf_data_out(rf_data_out), .rf_error_bit(rf_error_bit),
.rf_overrun(rf_overrun), .rx_reset(rx_reset), .lsr_mask(lsr_mask), .rstate(rstate), .rf_push_pulse(rf_push_pulse));
always @(dl or dlab or ier or iir or fi_di_reg or mode_reg
or lcr or lsr or msr or rf_data_out or addr )
begin
case (addr)
`UART_REG_RB : dat_o = dlab ? dl[`UART_DL1] : rf_data_out[10:3];
`UART_REG_IE : dat_o = dlab ? dl[`UART_DL2] : ier;
`UART_REG_II : dat_o = dlab ? dl[`UART_DL3] : {4'b1100,iir};
`UART_REG_LC : dat_o = lcr;
`UART_REG_LS : dat_o = lsr;
`UART_REG_MS : dat_o = msr;
`UART_REG_SR : dat_o = dlab ? fi_di_reg : mode_reg;
default : dat_o = 8'b0;
endcase
end
always @(posedge clk )
begin
if (rst)
rf_pop <= 0;
else
if (rf_pop)
rf_pop <= 0;
else
if (re && addr == `UART_REG_RB && !dlab)
rf_pop <= 1;
end
wire lsr_mask_condition;
wire iir_read;
wire msr_read;
wire fifo_read;
wire fifo_write;
assign lsr_mask_condition = (re && addr == `UART_REG_LS && !dlab);
assign iir_read = (re && addr == `UART_REG_II && !dlab);
assign msr_read = (re && addr == `UART_REG_MS && !dlab);
assign fifo_read = (re && addr == `UART_REG_RB && !dlab);
assign fifo_write = (we && addr == `UART_REG_TR && !dlab);
always @(posedge clk )
begin
if (rst)
lsr_mask_d <= 0;
else
lsr_mask_d <= lsr_mask_condition;
end
assign lsr_mask = lsr_mask_condition && ~lsr_mask_d;
always @(posedge clk )
begin
if (rst)
msi_reset <= 1;
else
if (msi_reset)
msi_reset <= 0;
else
if (msr_read)
msi_reset <= 1;
end
always @(posedge clk )
if (rst)
lcr <= 8'b00000011;
else
if (we && addr==`UART_REG_LC)
lcr <= dat_i;
always @(posedge clk )
if (rst)
begin
ier <= 4'b0000;
dl[`UART_DL2] <= 8'b0;
end
else
if (we && addr==`UART_REG_IE)
if (dlab)
begin
dl[`UART_DL2] <= dat_i;
end
else
ier <= dat_i[3:0];
else
ier<= ier;
always @(posedge clk )
if (rst) begin
fcr <= 2'b11;
rx_reset <= 0;
tx_reset <= 0;
dl[`UART_DL3] <= 8'h0;
end else
if (we && addr==`UART_REG_FC) begin
if(dlab) dl[`UART_DL3] <= dat_i;
else begin
fcr <= dat_i[7:6];
rx_reset <= dat_i[1];
tx_reset <= dat_i[2];
end
end else begin
rx_reset <= 0;
tx_reset <= 0;
end
always @(posedge clk )
if (rst) begin
mcr <= 5'b0;
infrared <= 1'b0;
rx_pol <= 1'b0; end
else
if(we && addr==`UART_REG_MC) begin
mcr <= dat_i[4:0];
infrared <= dat_i[7];
rx_pol <= dat_i[6]; end
assign tf_push = we & addr==`UART_REG_TR & !dlab;
always @(posedge clk )
if (rst)
begin
dl[`UART_DL1] <= 8'b0;
start_dlc <= 1'b0;
end
else
if (we && addr==`UART_REG_TR)
if (dlab)
begin
dl[`UART_DL1] <= dat_i;
start_dlc <= 1'b1;
end
else
begin
start_dlc <= 1'b0;
end
else
begin
start_dlc <= 1'b0;
end
always @(fcr)
case (fcr[`UART_FC_TL])
2'b00 : trigger_level = 1;
2'b01 : trigger_level = 4;
2'b10 : trigger_level = 8;
2'b11 : trigger_level = 14;
endcase
reg [3:0] delayed_modem_signals;
always @(posedge clk )
begin
if (rst)
begin
msr <= 0;
delayed_modem_signals[3:0] <= 0;
end
else begin
msr[`UART_MS_DDCD:`UART_MS_DCTS] <= msi_reset ? 4'b0 :
msr[`UART_MS_DDCD:`UART_MS_DCTS] | ({dcd, ri, dsr, cts} ^ delayed_modem_signals[3:0]);
msr[`UART_MS_CDCD:`UART_MS_CCTS] <= {dcd_c, ri_c, dsr_c, cts_c};
delayed_modem_signals[3:0] <= {dcd, ri, dsr, cts};
end
end
assign lsr0 = (rf_count==0 && rf_push_pulse);
assign lsr1 = rf_overrun;
assign lsr2 = rf_data_out[1];
assign lsr3 = rf_data_out[0];
assign lsr4 = rf_data_out[2];
assign lsr5 = current_finish && (tf_count==5'b0 && thre_set_en);
assign lsr6 = (tf_count==5'b0 && thre_set_en && (tstate == 3'd0));
assign lsr7 = rf_error_bit | rf_overrun;
reg lsr0_d;
always @(posedge clk )
if (rst) lsr0_d <= 0;
else lsr0_d <= lsr0;
always @(posedge clk )
if (rst) lsr0r <= 0;
else lsr0r <= (rf_count==1 && rf_pop && !rf_push_pulse || rx_reset) ? 0 :
lsr0r || (lsr0 && ~lsr0_d);
reg lsr1_d;
always @(posedge clk )
if (rst) lsr1_d <= 0;
else lsr1_d <= lsr1;
always @(posedge clk )
if (rst) lsr1r <= 0;
else lsr1r <= lsr_mask ? 0 : lsr1r || (lsr1 && ~lsr1_d);
reg lsr2_d;
always @(posedge clk )
if (rst) lsr2_d <= 0;
else lsr2_d <= lsr2;
always @(posedge clk )
if (rst) lsr2r <= 0;
else lsr2r <= lsr_mask ? 0 : lsr2r || (lsr2 && ~lsr2_d);
reg lsr3_d;
always @(posedge clk )
if (rst) lsr3_d <= 0;
else lsr3_d <= lsr3;
always @(posedge clk )
if (rst) lsr3r <= 0;
else lsr3r <= lsr_mask ? 0 : lsr3r || (lsr3 && ~lsr3_d);
reg lsr4_d;
always @(posedge clk )
if (rst) lsr4_d <= 0;
else lsr4_d <= lsr4;
always @(posedge clk )
if (rst) lsr4r <= 0;
else lsr4r <= lsr_mask ? 0 : lsr4r || (lsr4 && ~lsr4_d);
reg lsr5_d;
always @(posedge clk )
if (rst) lsr5_d <= 1;
else lsr5_d <= lsr5;
always @(posedge clk )
if (rst) lsr5r <= 1;
else lsr5r <= (fifo_write) ? 0 : lsr5r || (lsr5 && ~lsr5_d);
reg lsr6_d;
always @(posedge clk )
if (rst) lsr6_d <= 1;
else lsr6_d <= lsr6;
always @(posedge clk )
if (rst) lsr6r <= 1;
else lsr6r <= (fifo_write) ? 0 : lsr6r || (lsr6 && ~lsr6_d);
reg lsr7_d;
always @(posedge clk )
if (rst) lsr7_d <= 0;
else lsr7_d <= lsr7;
always @(posedge clk )
if (rst) lsr7r <= 0;
else lsr7r <= lsr_mask ? 0 : lsr7r || (lsr7 && ~lsr7_d);
reg [8:0] M_cnt;
wire [8:0] M_next = M_cnt + dl[`UART_DL3];
wire M_toggle = M_cnt[8] ^ M_next[8];
always @(posedge clk )
begin
if (rst) begin
dlc <= 0;
M_cnt <= 8'h0;
end
else if (start_dlc | ~ (|dlc)) begin
dlc <= dl - 1 + M_toggle;
M_cnt <= M_next;
end
else
dlc <= dlc - 1;
end
always @(posedge clk )
begin
if (rst)
enable <= 1'b0;
else if (|dl & ~(|dlc))
enable <= 1'b1;
else
enable <= 1'b0;
end
always @(lcr)
case (lcr[3:0])
4'b0000 : block_value = 95;
4'b0100 : block_value = 103;
4'b0001, 4'b1000 : block_value = 111;
4'b1100 : block_value = 119;
4'b0010, 4'b0101, 4'b1001 : block_value = 127;
4'b0011, 4'b0110, 4'b1010, 4'b1101 : block_value = 143;
4'b0111, 4'b1011, 4'b1110 : block_value = 159;
4'b1111 : block_value = 175;
endcase
always @(posedge clk )
begin
if (rst)
block_cnt <= 8'd0;
else
if(lsr5r & fifo_write)
block_cnt <= usart_t0 ? (block_value + 8'h16) : block_value;
else
if (enable & block_cnt != 8'b0)
block_cnt <= block_cnt - 1;
end
assign thre_set_en = ~(|block_cnt);
assign rls_int = ier[`UART_IE_RLS] && (lsr[`UART_LS_OE] || lsr[`UART_LS_PE] || lsr[`UART_LS_FE] || lsr[`UART_LS_BI]);
assign rda_int = ier[`UART_IE_RDA] && (rf_count >= {1'b0,trigger_level});
assign thre_int = ier[`UART_IE_THRE]&& lsr[`UART_LS_TFE];
assign ms_int = ier[`UART_IE_MS] && (usart_t0 ? max_repeat_time : (| msr[3:0]));
assign ti_int = ier[`UART_IE_RDA] && (counter_t == 10'b0) && (|rf_count);
reg rls_int_d;
reg thre_int_d;
reg ms_int_d;
reg ti_int_d;
reg rda_int_d;
always @(posedge clk )
if (rst) rls_int_d <= 0;
else rls_int_d <= rls_int;
always @(posedge clk )
if (rst) rda_int_d <= 0;
else rda_int_d <= rda_int;
always @(posedge clk )
if (rst) thre_int_d <= 0;
else thre_int_d <= thre_int;
always @(posedge clk )
if (rst) ms_int_d <= 0;
else ms_int_d <= ms_int;
always @(posedge clk )
if (rst) ti_int_d <= 0;
else ti_int_d <= ti_int;
wire rls_int_rise;
wire thre_int_rise;
wire ms_int_rise;
wire ti_int_rise;
wire rda_int_rise;
assign rda_int_rise = rda_int & ~rda_int_d;
assign rls_int_rise = rls_int & ~rls_int_d;
assign thre_int_rise = thre_int & ~thre_int_d;
assign ms_int_rise = ms_int & ~ms_int_d;
assign ti_int_rise = ti_int & ~ti_int_d;
reg rls_int_pnd;
reg rda_int_pnd;
reg thre_int_pnd;
reg ms_int_pnd;
reg ti_int_pnd;
always @(posedge clk )
if (rst) rls_int_pnd <= 0;
else
rls_int_pnd <= lsr_mask ? 0 :
rls_int_rise ? 1 :
rls_int_pnd && ier[`UART_IE_RLS];
reg d1_fifo_read;
always @( posedge clk ) d1_fifo_read <= fifo_read;
always @(posedge clk)
if (rst) rda_int_pnd <= 0;
else rda_int_pnd <= ((rf_count == {1'b0,trigger_level}) && d1_fifo_read) ? 0 :
rda_int_rise ? 1 :
rda_int_pnd && ier[`UART_IE_RDA];
always @(posedge clk )
if (rst) thre_int_pnd <= 0;
else
thre_int_pnd <= fifo_write || (iir_read & ~iir[`UART_II_IP] & iir[`UART_II_II] == `UART_II_THRE)? 0 :
thre_int_rise ? 1 :
thre_int_pnd && ier[`UART_IE_THRE];
always @(posedge clk )
if (rst) ms_int_pnd <= 0;
else
ms_int_pnd <= msr_read ? 0 : ms_int_rise ? 1 :
ms_int_pnd && ier[`UART_IE_MS];
always @(posedge clk )
if (rst) ti_int_pnd <= 0;
else
ti_int_pnd <= fifo_read ? 0 : ti_int_rise ? 1 :
ti_int_pnd && ier[`UART_IE_RDA];
always @(posedge clk )
begin
if (rst) int_o <= 1'b0;
else int_o <= rls_int_pnd ? ~lsr_mask :
rda_int_pnd ? 1 :
ti_int_pnd ? ~fifo_read:
thre_int_pnd? !(fifo_write & iir_read) :
ms_int_pnd ? ~msr_read :
0;
end
always @(posedge clk )
begin
if (rst)
iir <= 1;
else
if (rls_int_pnd)
begin
iir[`UART_II_II] <= `UART_II_RLS;
iir[`UART_II_IP] <= 1'b0;
end else
if (rda_int_pnd)
begin
iir[`UART_II_II] <= `UART_II_RDA;
iir[`UART_II_IP] <= 1'b0;
end
else if (ti_int_pnd)
begin
iir[`UART_II_II] <= `UART_II_TI;
iir[`UART_II_IP] <= 1'b0;
end
else if (thre_int_pnd)
begin
iir[`UART_II_II] <= `UART_II_THRE;
iir[`UART_II_IP] <= 1'b0;
end
else if (ms_int_pnd)
begin
iir[`UART_II_II] <= `UART_II_MS;
iir[`UART_II_IP] <= 1'b0;
end else
begin
iir[`UART_II_II] <= 0;
iir[`UART_II_IP] <= 1'b1;
end
end
endmodule