Building Larger Circuits
Counter with period 1000
熟悉計數器寫法後,可以把邏輯寫得很簡潔。
Verilog
module top_module (
input clk,
input reset,
output reg[9:0] q);
always@(posedge clk)begin
if(reset) q <= 10'd0;
else if(q == 10'd999) q <= 10'd0;
else q <= q + 1'b1;
end
endmodule
4-bit shift register and down counter
Verilog
module top_module (
input clk,
input shift_ena,
input count_ena,
input data,
output reg[3:0] q);
always@(posedge clk)begin
case({shift_ena, count_ena})
2'b00: q <= q;
2'b01: q <= q - 1'b1;
2'b10: q <= {q[2:0],data};
2'b11: q <= 4'bxxxx;
endcase
end
endmodule
FSM: Sequence 1101 recognizer
Verilog
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output start_shifting);
reg [2:0] state, nstate;
parameter zero = 3'd0;
parameter one = 3'd1;
parameter two = 3'd2;
parameter three = 3'd3;
parameter four = 3'd4;
always@(*)begin
case(state)
zero: nstate = data? one: zero;
one: nstate = data? two: zero;
two: nstate = data? two: three;
three: nstate = data? four: zero;
four: nstate = four;
default: nstate = 3'bxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= zero;
else state <= nstate;
end
assign start_shifting = (state == four);
endmodule
FSM: Enable shift register
Verilog
module top_module (
input clk,
input reset, // Synchronous reset
output shift_ena);
reg [2:0] counter;
always@(posedge clk)begin
if(reset) counter <= 3'd0;
else if(counter == 3'd4) counter <= counter;
else counter <= counter + 1'b1;
end
assign shift_ena = ~counter[2];
endmodule
FSM: The complete FSM
整合前三題,FSM 與 datapath 分開處理會比較清楚。
Verilog
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output shift_ena,
output counting,
input done_counting,
output done,
input ack );
reg [3:0] state, nstate;
parameter re = 4'd0;
parameter l = 4'd1;
parameter ll = 4'd2;
parameter llo = 4'd3;
parameter llol = 4'd4;
parameter s1 = 4'd5;
parameter s2 = 4'd6;
parameter s3 = 4'd7;
parameter is_counting = 4'd8;
parameter is_done = 4'd9;
always@(*)begin
case(state)
re: nstate = data? l: re;
l: nstate = data? ll: re;
ll: nstate = data? ll: llo;
llo: nstate = data? llol: re;
llol: nstate = s1;
s1: nstate = s2;
s2: nstate = s3;
s3: nstate = is_counting;
is_counting: nstate = done_counting? is_done: is_counting;
is_done: nstate = ack? re: is_done;
default: nstate = 4'bxxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= re;
else state <= nstate;
end
assign shift_ena = (state == s1) | (state == s2) | (state == s3) | (state == llol);
assign counting = (state == is_counting);
assign done = (state == is_done);
endmodule
The complete timer
重點在 FSM、counter 與輸出控制的整合;delay 可用倒數 counter 實作,狀態會更好管理。
Verilog
module top_module (
input clk,
input reset, // Synchronous reset
input data,
output [3:0] count,
output counting,
output done,
input ack );
//FSM
reg [3:0] state,next_state;
parameter re = 4'd0;
parameter l = 4'd1;
parameter ll = 4'd2;
parameter llo = 4'd3;
parameter shift_o = 4'd4;
parameter shift_l = 4'd5;
parameter shift_lo = 4'd6;
parameter shift_ll = 4'd7;
parameter is_count = 4'd8;
parameter is_finish = 4'd9;
always@(*)begin
case(state)
re: next_state = data ? l: re;
l: next_state = data? ll: re;
ll: next_state = data? ll: llo;
llo: next_state = data? shift_o: re;
shift_o: next_state = shift_l;
shift_l: next_state = shift_lo;
shift_lo: next_state = shift_ll;
shift_ll: next_state = is_count;
is_count: next_state = ((num == 15'd999)&(data_pipe == 4'd0))? is_finish: is_count;
is_finish: next_state = ack? re: is_finish;
default: next_state = 4'bxxxx;
endcase
end
always@(posedge clk)begin
if(reset) state <= re;
else state <= next_state;
end
//Counter
reg [9:0] num;
always@(posedge clk)begin
if(reset) num <= 10'd0;
else if(num == 10'd999) num <= 10'd0;
else if(counting) num <= num +10'd1;
else num <= num;
end
//Data
wire is_data_shift;
reg [3:0] data_pipe;
assign is_data_shift = (state == shift_o) | (state == shift_l) | (state == shift_lo) | (state == shift_ll);
always@(posedge clk)begin
if(reset) data_pipe <= 4'd0;
else if(is_data_shift) data_pipe <= {data_pipe[2:0], data};
else if(num == 10'd999) data_pipe <= data_pipe - 1'b1;
else data_pipe <= data_pipe;
end
assign count = data_pipe;
assign counting = (state == is_count);
assign done = (state == is_finish);
endmodule
FSM: One-hot logic equations
和前一題相比,此題不需要 clock,可直接用 assign 描述 one-hot transition logic。
Verilog
module top_module(
input d,
input done_counting,
input ack,
input [9:0] state, // 10-bit one-hot current state
output B3_next,
output S_next,
output S1_next,
output Count_next,
output Wait_next,
output done,
output counting,
output shift_ena
); //
// You may use these parameters to access state bits using e.g., state[B2] instead of state[6].
parameter S=0, S1=1, S11=2, S110=3, B0=4, B1=5, B2=6, B3=7, Count=8, Wait=9;
assign B3_next = state[B2];
assign S_next = (state[Wait] & ack) | (state[S] & ~d) | (state[S1] & ~d) | (state[S110] & ~d);
assign S1_next = state[S] & d;
assign Count_next = state[B3] | (state[Count] & ~done_counting);
assign Wait_next = (state[Count] & done_counting) | (state[Wait] & ~ack);
assign done = state[Wait];
assign counting = state[Count];
assign shift_ena = state[B0] | state[B1] | state[B2] | state[B3];
endmodule