1. Johnson Counter
1.题目:
请用Verilog实现4位约翰逊计数器(扭环形计数器),计数器的循环状态如下。
电路的接口如下图所示
2.解题思路
2.1 一个简单的状态机的配置。
2.2 注意 起始状态 是 0000 就行
3.解题代码
`timescale 1ns/1ns
module JC_counter(
input clk ,
input rst_n,
output reg [3:0] Q
);
parameter s0 = 4'b0000;
parameter s1 = 4'b1000;
parameter s2 = 4'b1100;
parameter s3 = 4'b1110;
parameter s4 = 4'b1111;
parameter s5 = 4'b0111;
parameter s6 = 4'b0011;
parameter s7 = 4'b0001;
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
Q <= s0;
end
else
begin
case (Q)
s0 : Q<=s1;
s1 : Q<=s2;
s2 : Q<=s3;
s3 : Q<=s4;
s4 : Q<=s5;
s5 : Q<=s6;
s6 : Q<=s7;
s7 : Q<=s0;
default: Q <= s0;
endcase
end
end
endmodule
2.VL56 流水线乘法器
1.题目:
实现4bit无符号数流水线乘法器设计。
2.解题思路
2.1 可以利用 for 的循环结构减轻代码量。
2.2 第一个输入 作为 左移的判断位, 第二个作为左移的单位。
2.3 然后所有的位置 相加。
3.解题代码
`timescale 1ns/1ns
module multi_pipe#(
parameter size = 4
)(
input clk ,
input rst_n ,
input [size-1:0] mul_a ,
input [size-1:0] mul_b ,
output reg [size*2-1:0] mul_out
);
reg[size*2 -1 :0] data[size-1:0]; //定义一个存储数据的地方
reg[size*2 -1 :0] data1;
reg [size*2-1:0] mul_out1;
integer j;
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
mul_out <=0;
for(j=0; j<size; j=j+1)
begin
data[j] <=0; //寄存器单位置0
end
end
else
begin
for(j=0;j<size ;j=j+1)
begin
data[j] <= {4'd0,mul_a} << (mul_b[j] ? j :8); //
end
mul_out1 =0;//开始的时候清零 ,因为是堵塞赋值
for(j=0;j<size ;j=j+1)
begin
mul_out1 = mul_out1+ data[j];//堵塞赋值可以这样用
end
mul_out <= mul_out1;//非堵塞赋值, 时序要求。
end
end
endmodule
3.VL57 交通灯
1.题目:
要求实现一个交通红绿灯,具有红黄绿三个小指示灯和一个行人按钮,正常情况下,机动车道指示灯按照60时钟周期绿灯,5个时钟周期黄灯,10个时钟周期红灯循环。当行人按钮按下,如果剩余绿灯时间大于10个时钟,则缩短为10个时钟,小于10个时钟则保持不变。
注:机动车道的指示灯和人行道指示灯应该是配对的,当机动车道的灯为绿或者黄时,人行道的灯为红;当机动车道的灯为红时,人行道的灯为绿,为简便起见,只考虑机动车道的指示灯。
模块的信号接口图如下:
2.解题思路
2.1 这个题目做了半天 不懂!!
2.2 观看题解后,震惊我了。 交通灯的循序 红 -> 黄 -> 绿 ???
2.3 直接抄答案, 不懂!!
3.解题代码
别人的通关代码: (我是做不出!)
`timescale 1ns/1ns
module triffic_light
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input pass_request,
output wire[7:0]clock,
output reg red,
output reg yellow,
output reg green
);
parameter idle = 2'd0,
s1_red = 2'd1,
s2_yellow = 2'd2,
s3_green = 2'd3;
reg [7:0] cnt;
reg [1:0] state;
reg p_red,p_yellow,p_green; //用于缓存信号灯的前一时刻的数值,判断上升沿
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
state <= idle;
p_red <= 1'b0;
p_green <= 1'b0;
p_yellow <= 1'b0;
end
else case(state)
idle:
begin
p_red <= 1'b0;
p_green <= 1'b0;
p_yellow <= 1'b0;
state <= s1_red;
end
s1_red:
begin
p_red <= 1'b1;
p_green <= 1'b0;
p_yellow <= 1'b0;
if (cnt == 3)
state <= s2_yellow;
else
state <= s1_red;
end
s2_yellow:
begin
p_red <= 1'b0;
p_green <= 1'b0;
p_yellow <= 1'b1;
if (cnt == 3)
state <= s3_green;
else
state <= s2_yellow;
end
s3_green:
begin
p_red <= 1'b0;
p_green <= 1'b1;
p_yellow <= 1'b0;
if (cnt == 3)
state <= s1_red;
else
state <= s3_green;
end
endcase
end
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 7'd10;
else if (pass_request&&green&&(cnt>10))
cnt <= 7'd10;
else if (!green&&p_green)
cnt <= 7'd60;
else if (!yellow&&p_yellow)
cnt <= 7'd5;
else if (!red&&p_red)
cnt <= 7'd10;
else cnt <= cnt -1;
assign clock = cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
yellow <= 1'd0;
red <= 1'd0;
green <= 1'd0;
end
else
begin
yellow <= p_yellow;
red <= p_red;
green <= p_green;
end
endmodule
自己写的 (时序图中间卡住了) (没有过关!!)
`timescale 1ns/1ns
module triffic_light
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input pass_request,
output wire[7:0]clock,
output reg red,
output reg yellow,
output reg green
);
parameter s0 = 2'd0; //绿灯状态
parameter s1 = 2'd1; //黄灯状态
parameter s2 = 2'd2; //红灯状态
reg[1:0] flag;// 状态标志位
reg[6:0] cnt; //计数器
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
flag <=s0; //交通灯状态
cnt <= 7'd10;
end
else
begin
if(pass_request && flag ==s0 && (cnt>10))
begin
if(cnt >10)
begin
cnt <=10;
end
end
else if(flag == s0 && cnt == 7'd0 )
begin
flag <= s1;
cnt <= 4;
end
else if(flag == s1 && cnt == 7'd0)
begin
flag <= s2;
cnt <= 9;
end
else if(flag == s2 && cnt == 7'd0)
begin
flag <= s0;
cnt <= 59;
end
else
begin
cnt <= cnt -1;
end
end
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
red <=0;
yellow <=0;
green <=0;
end
else
begin
case (flag)
s0 :begin
green <=1;
yellow <=0;
red <=0;
end
s1 :begin
green <=0;
yellow <=1;
red <=0;
end
s2 :begin
green <=0;
yellow <=0;
red <=1;
end
endcase
end
end
assign clock = cnt;
endmodule
4.VL58 游戏机计费程序
1.题目:
要求实现一个游戏机计费模块,某游戏机具有多个模式,价格不同:普通模式每分钟1元,畅玩模式每分钟收费2元,默认情况下为普通模式,在boost按键按下之后进入畅玩模式。
游戏机采用预付费模式,输入端口money的数值为预付费用,在set信号有效时,将money的数值读入。输出端口remain的数值为剩余费用,当费用小于10元时,黄色信号灯yellow亮起。当费用不足时,红色信号灯red亮起,同时关闭电脑。在游戏过程中可以通过set端口续费。每次set信号有效将此时刻money的数值加到remain之中。
注:在程序中以每个时钟周期代表一分钟,每个单位大小表示1元。
模块的信号接口图如下:
2.解题思路:
- 根据boost类型确定每分钟/周期消费金额,注意充值所在分钟/周期是不消费的。
- 两个灯(red yellow)不能同时亮起,先判断红灯是否满足条件,再判断黄灯。
3.解题代码 (if 有点多)
`timescale 1ns/1ns
module game_count
(
input rst_n, //异位复位信号,低电平有效
input clk, //时钟信号
input [9:0]money,
input set,
input boost,
output reg[9:0]remain,
output reg yellow,
output reg red
);
parameter s0=1'd0; //普通模式
parameter s1=1'd1; //畅玩模式
reg[1:0] flag; //标记 电脑模式
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
remain <=0;
end
else
begin
if(boost == s0)
begin
if(set == 1'b1)
begin
remain <= remain +money;
end
else
begin
if(remain >0)
begin
remain <= remain -1;
end
else
begin
remain <=remain;
end
end
end
else if(boost == s1)
begin
if(set == 1'b1)
begin
remain <= remain +money;
end
else
begin
if(remain >1)
begin
remain <= remain -2;
end
else
begin
remain <=remain;
end
end
end
end
end
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
begin
yellow <=0;
red <=0;
end
else
begin
if(boost == s0)
begin
if(remain <1)
begin
red <=1;
yellow <=0;
end
else if(remain <10)
begin
red <=0;
yellow <=1;
end
else
begin
red <=0;
yellow <=0;
end
end
else if(boost == s1)
begin
if(remain <2)
begin
red <=1;
yellow <=0;
end
else if(remain <10)
begin
red <=0;
yellow <=1;
end
else
begin
red <=0;
yellow <=0;
end
end
end
end
endmodule