📄 cia8520.v
字号:
);//----------------------------------------------------------------------------------//instantiate timer A//----------------------------------------------------------------------------------timera tmra( .clk(clk), .wr(wr), .reset(reset), .tlo(talo), .thi(tahi), .tcr(cra), .datain(datain), .dataout(tmraout), .eclk(e), .tmra_ovf(tmra_ovf), .irq(ta) );//----------------------------------------------------------------------------------//instantiate timer B//----------------------------------------------------------------------------------timerb tmrb( .clk(clk), .wr(wr), .reset(reset), .tlo(tblo), .thi(tbhi), .tcr(crb), .datain(datain), .dataout(tmrbout), .eclk(e), .tmra_ovf(tmra_ovf), .irq(tb));//----------------------------------------------------------------------------------//instantiate timer D//----------------------------------------------------------------------------------timerd tmrd ( .clk(clk), .wr(wr), .reset(reset), .tlo(tdlo), .tme(tdme), .thi(tdhi), .tcr(crb), .datain(datain), .dataout(tmrdout), .count(tick), .irq(alrm)); endmodule//----------------------------------------------------------------------------------//----------------------------------------------------------------------------------//interrupt control//----------------------------------------------------------------------------------//----------------------------------------------------------------------------------module ciaint( input clk, //clock input wr, //write enable input reset, //reset input icrs, //intterupt control register select input ta, //ta (set TA bit in ICR register) input tb, //tb (set TB bit in ICR register) input alrm, //alrm (set ALRM bit ICR register) input flag, //flag (set FLG bit in ICR register) input ser, //ser (set SP bit in ICR register) input [7:0]datain, //bus data in output reg [7:0]dataout, //bus data out output irq //intterupt out); reg [4:0]icr; //interrupt register reg [4:0]icrmask; //interrupt mask register//reading of interrupt data register always @(wr or irq or icrs or icr) if(icrs && !wr) dataout[7:0] = {irq,2'b0,icr[4:0]}; else dataout[7:0] = 0;//writing of interrupt mask registeralways @(posedge clk) if(reset) icrmask[4:0] <= 0; else if(icrs && wr) begin if(datain[7]) icrmask[4:0] <= icrmask[4:0] | datain[4:0]; else icrmask[4:0] <= icrmask[4:0] & (~datain[4:0]); end//register new interrupts and/or changes by user readsalways @(posedge clk) if(reset)//synchronous reset icr[4:0] <= 0; else if (icrs && !wr) begin//clear latched intterupts on read icr[0] <= ta; //timer a icr[1] <= tb; //timer b icr[2] <= alrm; //timer tod icr[3] <= ser; //external ser input icr[4] <= flag; //external flag input end else begin//keep latched intterupts icr[0] <= icr[0]|ta; //timer a icr[1] <= icr[1]|tb; //timer b icr[2] <= icr[2]|alrm; //timer tod icr[3] <= icr[3]|ser; //external ser input icr[4] <= icr[4]|flag; //external flag input end//generate irq output (interrupt request)assign irq = (icrmask[0]&icr[0]) | (icrmask[1]&icr[1]) | (icrmask[2]&icr[2]) | (icrmask[3]&icr[3]) | (icrmask[4]&icr[4]);endmodule//----------------------------------------------------------------------------------//timer A/B//----------------------------------------------------------------------------------module timera( input clk, //clock input wr, //write enable input reset, //reset input tlo, //timer low byte select input thi, //timer high byte select input tcr, //timer control register input [7:0]datain, //bus data in output [7:0]dataout, //bus data out input eclk, //count enable output tmra_ovf, //timer A underflow output spmode, //serial port mode output start, //timer start (enable) output irq //intterupt out); reg [15:0]tmr; //timer reg [7:0]tmlh; //timer latch high byte reg [7:0]tmll; //timer latch low byte reg [6:0]tmcr; //timer control register reg forceload; //force load strobe wire oneshot; //oneshot mode //wire start; //timer start (enable) reg oneshot_load; //load tmr after writing thi in one-shot mode wire reload; //reload timer counter wire zero; //timer counter is zero wire underflow; //timer is going to underflow wire count; //count enable signal //count enable signal assign count = eclk; //writing timer control registeralways @(posedge clk) if(reset) //synchronous reset tmcr[6:0] <= 0; else if (tcr && wr) //load control register, bit 4(strobe) is always 0 tmcr[6:0] <= {datain[6:5],1'b0,datain[3:0]}; else if (oneshot_load) //start timer if thi is written in one-shot mode tmcr[0] <= 1; else if (underflow && oneshot) //stop timer in one-shot mode tmcr[0] <= 0;always @(posedge clk) forceload <= tcr & wr & datain[4]; //force load strobe assign oneshot = tmcr[3]; //oneshot aliasassign start = tmcr[0]; //start aliasassign spmode = tmcr[6]; //serial port mode (0-input, 1-output)//timer A latches for high and low bytealways @(posedge clk) if (reset) tmll[7:0] <= 8'b11111111; else if (tlo && wr) tmll[7:0] <= datain[7:0]; always @(posedge clk) if (reset) tmlh[7:0] <= 8'b11111111; else if (thi && wr) tmlh[7:0] <= datain[7:0];//thi is written in one-shot mode so tmr must be reloadedalways @(posedge clk) oneshot_load <= thi & wr & oneshot;//timer counter reload signalassign reload = oneshot_load | forceload | underflow;//timer counter always @(posedge clk) if (reset) tmr[15:0] <= 0; else if (reload) tmr[15:0] <= {tmlh[7:0],tmll[7:0]}; else if (start && count) tmr[15:0] <= tmr[15:0] - 1;//timer counter equals zero assign zero = ~|tmr; //timer counter is going to underflowassign underflow = zero & start & count;//Timer A underflow signal for Timer Bassign tmra_ovf = underflow;//timer underflow interrupt requestassign irq = underflow;//data outputassign dataout[7:0] = ({8{~wr&tlo}} & tmr[7:0]) | ({8{~wr&thi}} & tmr[15:8]) | ({8{~wr&tcr}} & {1'b0,tmcr[6:0]}); endmodulemodule timerb( input clk, //clock input wr, //write enable input reset, //reset input tlo, //timer low byte select input thi, //timer high byte select input tcr, //timer control register input [7:0]datain, //bus data in output [7:0]dataout, //bus data out input eclk, //count enable input tmra_ovf, //timer A underflow output irq //intterupt out); reg [15:0]tmr; //timer reg [7:0]tmlh; //timer latch high byte reg [7:0]tmll; //timer latch low byte reg [6:0]tmcr; //timer control register reg forceload; //force load strobe wire oneshot; //oneshot mode wire start; //timer start (enable) reg oneshot_load; //load tmr after writing thi in one-shot mode wire reload; //reload timer counter wire zero; //timer counter is zero wire underflow; //timer is going to underflow wire count; //count enable signal//Timer B count signal sourceassign count = tmcr[6] ? tmra_ovf : eclk;//writing timer control registeralways @(posedge clk) if(reset) //synchronous reset tmcr[6:0] <= 0; else if (tcr && wr) //load control register, bit 4(strobe) is always 0 tmcr[6:0] <= {datain[6:5],1'b0,datain[3:0]}; else if (oneshot_load) //start timer if thi is written in one-shot mode tmcr[0] <= 1; else if (underflow && oneshot) //stop timer in one-shot mode tmcr[0] <= 0;always @(posedge clk) forceload <= tcr & wr & datain[4]; //force load strobe assign oneshot = tmcr[3]; //oneshot aliasassign start = tmcr[0]; //start alias//timer B latches for high and low bytealways @(posedge clk) if (reset) tmll[7:0] <= 8'b11111111; else if (tlo && wr) tmll[7:0] <= datain[7:0]; always @(posedge clk) if (reset) tmlh[7:0] <= 8'b11111111; else if (thi && wr) tmlh[7:0] <= datain[7:0];//thi is written in one-shot mode so tmr must be reloadedalways @(posedge clk) oneshot_load <= thi & wr & oneshot;//timer counter reload signalassign reload = oneshot_load | forceload | underflow;//timer counter always @(posedge clk) if (reset) tmr[15:0] <= 0; else if (reload) tmr[15:0] <= {tmlh[7:0],tmll[7:0]}; else if (start && count) tmr[15:0] <= tmr[15:0] - 1;//timer counter equals zero assign zero = ~|tmr; //timer counter is going to underflowassign underflow = zero & start & count;//timer underflow interrupt requestassign irq = underflow;//data outputassign dataout[7:0] = ({8{~wr&tlo}} & tmr[7:0]) | ({8{~wr&thi}} & tmr[15:8]) | ({8{~wr&tcr}} & {1'b0,tmcr[6:0]}); endmodule//----------------------------------------------------------------------------------//----------------------------------------------------------------------------------//timer D//----------------------------------------------------------------------------------//----------------------------------------------------------------------------------module timerd( input clk, //clock input wr, //write enable input reset, //reset input tlo, //timer low byte select input tme, //timer mid byte select input thi, //timer high byte select input tcr, //timer control register input [7:0]datain, //bus data in output reg [7:0]dataout, //bus data out input count, //count enable output reg irq //intterupt out); reg le; //timer d output latch enable reg ce; //timer d count enable reg crb7; //bit 7 of control register B reg [23:0]tod; //timer d reg [23:0]alarm; //alarm reg [15:0]todl; //timer d latch//timer D output latch controlalways @(posedge clk) if(reset) le <= 1; else if(!wr) begin if(thi)//if MSB read, hold data for subsequent reads le <= 0; else if (tlo)//if LSB read, update data every clock le <= 1; endalways @(posedge clk) if(le) todl[15:0] <= tod[15:0];//timer D and crb7 read always @(wr or tlo or tme or thi or tcr or tod or todl or crb7) if (!wr) begin if(thi)//high byte of timer D dataout[7:0] = tod[23:16]; else if (tme)//medium byte of timer D (latched) dataout[7:0] = todl[15:8]; else if (tlo)//low byte of timer D (latched) dataout[7:0] = todl[7:0]; else if (tcr)//bit 7 of crb dataout[7:0] = {crb7,7'b0000000}; else dataout[7:0] = 0; end else dataout[7:0] = 0; //timer D count enable controlalways @(posedge clk) if(reset) ce <= 1; else if(wr && !crb7)//crb7==0 enables writing to TOD counter begin if(thi || tme)//stop counting ce <= 0; else if(tlo)//write to LSB starts counting again ce <= 1; end//timer D counteralways @(posedge clk) if(reset)//synchronous reset begin tod[7:0] <= 0; tod[15:8] <= 0; tod[23:16] <= 0; end else if(wr && !crb7)//crb7==0 enables writing to TOD counter begin if(tlo) tod[7:0] <= datain[7:0]; if(tme) tod[15:8] <= datain[7:0]; if(thi) tod[23:16] <= datain[7:0]; end else if(ce && count) tod[23:0] <= tod[23:0]+1;//alarm writealways @(posedge clk) if(reset)//synchronous (p)reset begin alarm[7:0] <= 8'b11111111; alarm[15:8] <= 8'b11111111; alarm[23:16] <= 8'b11111111; end else if(wr && crb7)//crb7==1 enables writing to ALARM begin if(tlo) alarm[7:0] <= datain[7:0]; if(tme) alarm[15:8] <= datain[7:0]; if(thi) alarm[23:16] <= datain[7:0]; end//crb7 writealways @(posedge clk) if (reset) crb7 <= 0; else if(wr && tcr) crb7 <= datain[7];//alarm interruptalways @(tod or alarm or count) if( (tod[23:0]==alarm[23:0]) && count) irq = 1; else irq = 0;endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -