TopModule
可以看見,一個這樣多要求(功能)的計數器,拆成三個部份。`include "InitSel.v"
`include "Counter8combi.v"
`include "CircleStop.v"
module counter8uni2(clk, _areset, _aset, _load, preld_val, _updown, _wrapstop, dcout, overflow);
parameter countWidth = 8;
input clk,
_areset,
_aset,
_load,
_updown,
_wrapstop;
input [countWidth-1:0] preld_val;
output [countWidth-1:0] dcout;
output overflow;
wire [countWidth-1:0] tCount_M12, tCountM23;
InitSel M1( .oCountInitValue(tCount_M12), ._iReset(_areset), ._iSet(_aset), ._iLoad(_load), .iPreldVal(preld_val), .iCountValue(dcout) );
Counter8combi M2( .oCount(tCountM23), .iClk(clk), ._iIsAddOut(_updown), .iCount(tCount_M12) );
CircleStop M3( .oCount(dcout), .iClk(clk), .iCount(tCountM23), ._iWrapstop(_wrapstop), .oOverflow(overflow) );
endmodule
下面我們就來詳細的解說,這三個部份怎麼滿足這些規格吧!
第一個部份處理_areset、_aset、_load
這個部份要滿足- _areset =1 counter非同步輸出全0, _aset =1 counter非同步輸出全1, 若這兩個都是0, count照常運作
- _load = 1時, preld-val的值設定進counte
- 訊號優先權_areset > _aset > _load
最重要的一件事就是「非同步」,這個電路,沒有clk。
再來是優先權_areset > _aset > _load,所以code 的排序也是要注意的
在此使用always+準位觸發,用Blocking的方式,做非同步電路。
module InitSel(oCountInitValue, _iReset, _iSet, _iLoad, iPreldVal, iCountValue);
parameter CountWidth = 8;
input _iReset, _iSet, _iLoad;
input [CountWidth-1:0] iCountValue, iPreldVal;
output [CountWidth-1:0] oCountInitValue;
reg [CountWidth-1:0] oCountInitValue;
always@(_iReset, _iSet, _iLoad, iCountValue, iPreldVal)
begin
if (_iReset == 1)
oCountInitValue = 8'b1111_1111;
else if (_iSet == 1)
oCountInitValue = 8'b0000_0000;
else if (_iLoad == 1)
oCountInitValue = iPreldVal;
else
oCountInitValue = iCountValue;
end
endmodule
第二個部份處理_updown
這個部份是最重要的計數核心滿足一個規格
- _updown = 1, counter向上計數 counter = 0, counter向下計數
`include "coreCount8Add.v"
`include "coreCount8Sub.v"
module Counter8combi(iClk, _iIsAddOut, iCount, oCount);
parameter CountWidth = 8;
input iClk, _iIsAddOut;
input [CountWidth-1:0] iCount;
output [CountWidth-1:0] oCount;
wire [CountWidth-1:0] out_Add, out_Sub;
assign oCount = (_iIsAddOut)? out_Add: out_Sub;
coreCount8Add CA(iClk, _iIsAddOut, iCount, out_Add);
coreCount8Sub CS(iClk, _iIsAddOut, iCount, out_Sub);
endmodule
正數和反數計數器
它們差異不大,在此貼出反數的code,正數就改一下就是了正數修改處
- _iEn改iEn
- 運算符號-改+
module coreCount8Sub(iClk, _iEn, iCount, oCount);
parameter CountWidth = 8;
input iClk, _iEn;
input [CountWidth-1:0] iCount;
output [CountWidth-1:0] oCount;
reg [CountWidth-1:0] oCount;
always@(posedge iClk)
begin
if (!_iEn)
oCount <= iCount - 8'd1;
else
oCount <= iCount;
end
endmodule
第三個部份處理_wrapstop、overflow
在此也可以使用state mechine,但是我沒這麼做!規格如下
- _wrapstop = 1, counter循環計數, _wrapstop = 1, counter計數到最大或最小就停止,並且有overflow
- 承上,若計數超出範圍(超過最大值或低於最小值)則overflow = 1
module CircleStop(oCount, iClk, iCount, _iWrapstop, oOverflow);
parameter countWidth = 8;
input _iWrapstop, iClk;
input [countWidth-1:0] iCount;
output oOverflow;
output [countWidth-1:0] oCount;
reg [countWidth-1:0] oCount;
reg oOverflow;
always@(posedge iClk)
begin
if ((_iWrapstop == 1) && ((oCount == 8'b0000_0000)))
begin
oCount <= 8'b0000_0000;
oOverflow <= 'b1;
end
else if ((_iWrapstop == 1) && (oCount == 8'b1111_1111))
begin
oCount <= 8'b1111_1111;
oOverflow <= 'b1;
end
else
begin
oCount <= iCount;
oOverflow <= 'b0;
end
end
endmodule
這樣就組成了一個8bit的通用計數器。
沒有留言:
張貼留言
(什麼是留言欄訊息?)