- 追加された行はこのように表示されます。
- 削除された行は
このように表示されます。
!!!ブロックRAMを用いたスタック
!!パラメータ
,パラメータ名,既定値,
,AWIDTH,10,ブロックRAMのアドレス幅
,N,1024,スタック(ブロックRAM)の要素数
!!入出力ポート
, ,ポート名,既定値,
,入力,clk,1,グローバルクロック
,入力,reset,1,グローバルリセット
,入力,load,1,1のときclkの立ち上がりでスタックトップにdの値を書き込み
,入力,push,1,1のときclkの立ち上がりでスタックをプッシュ
,入力,pop,1,1のときclkの立ち上がりでスタックをポップ
,入力,pop2,1,1のときclkの立ち上がりでスタックを2つポップ(ポップ2回分)
,入力,thru,1,1のときthruをqtopに出力
,入力,d,16,スタックトップに書き込む値
,入力,dthru,16,thruが1のときdthruをqtopに出力
,出力,qtop,16,thruが1のときdthru,0のときスタックトップの値
,出力,qnext,16,スタックの2番目の値
PUSH命令(メモリから読み出したデータをスタックにプッシュ)を1クロックサイクルで実行するために,thruとdthruを導入.
メモリから読み出すのに1サイクル必要で,その読み出したデータをスタックトップに書き込むのにさらに1サイクル必要となる.そこでスタックに書き込むかわりに,メモリからの読み出しデータをdthruに入力し,それをスタックトップqtopの値とする.つまり,フリップフロップq[0]に書かれているスタックトップの値をスルーして,メモリの出力をスタックトップqtopとして出力する.
!!ソースコード
module stackm(clk, reset, load, push, pop, pop2, thru, d, dthru, qtop, qnext);
parameter AWIDTH = 10, N = 1024;
input clk, reset, load, push, pop, pop2, thru;
input [15:0] d, dthru;
output [15:0] qtop, qnext;
reg [AWIDTH-1:0] ptop, ptopf, addra, addrb;
reg [15:0] mem [N-1:0];
reg [15:0] qtopf;
wire [15:0] pnextf;
wire thruwrite;
input clk, reset, load, push, pop, pop2, thru;
input [15:0] d, dthru;
output [15:0] qtop, qnext;
reg [AWIDTH-1:0] ptop, ptopf, addra, addrb;
reg [15:0] mem [N-1:0];
reg [15:0] qtopf;
wire [15:0] pnextf;
wire thruwrite;
always @(push or pop or pop2 or ptop)
if(push) ptopf = ptop - 1;
else if(pop) ptopf = ptop + 1;
else if(pop2) ptopf = ptop + 2;
else ptopf = ptop;
always @(push or pop or pop2 or ptop)
if(push) ptopf = ptop - 1;
else if(pop) ptopf = ptop + 1;
else if(pop2) ptopf = ptop + 2;
else ptopf = ptop;
always @(posedge clk or negedge reset)
if(!reset) ptop <= 0;
else ptop <= ptopf;
always @(posedge clk or negedge reset)
if(!reset) ptop <= 0;
else ptop <= ptopf;
assign pnextf = ptopf + 1;
assign thruwrite = !(push||pop) && thru;
assign pnextf = ptopf + 1;
assign thruwrite = !(push||pop) && thru;
always @(load or push or pop or thru or d or dthru)
if(load) qtopf = d;
else if(thruwrite) qtopf = dthru;
else qtopf = 16'hxxxx;
always @(load or thruwrite or d or dthru)
if(load) qtopf = d;
else if(thruwrite) qtopf = dthru;
else qtopf = 16'hxxxx;
always @(posedge clk)
begin
if(load || thruwrite) mem[ptopf] <= qtopf;
addra <= ptopf;
end
always @(posedge clk)
begin
if(load || thruwrite) mem[ptopf] <= qtopf;
addra <= ptopf;
end
always @(posedge clk)
begin
if(push && thru) mem[pnextf] <= dthru;
addrb <= pnextf;
end
always @(posedge clk)
begin
if(push && thru) mem[pnextf] <= dthru;
addrb <= pnextf;
end
assign qtop = (thru ? dthru : mem[addra]);
assign qnext = mem[addrb];
assign qtop = (thru ? dthru : mem[addra]);
assign qnext = mem[addrb];
endmodule