【芯片前端】保持代码手感——交通灯

简介: 【芯片前端】保持代码手感——交通灯

长时间做方案,还是通过一些练习来保持代码手感。这次的题目是交通灯,经典的状态机题目,但是我不爱写状态机所以还是按自己的思路来组织下。


题目

要求实现一个交通红绿灯,具有红黄绿三个小指示灯和一个行人按钮,正常情况下,机动车道指示灯按照60时钟周期绿灯,5个时钟周期黄灯,10个时钟周期红灯循环。当行人按钮按下,如果剩余绿灯时间大于10个时钟,则缩短为10个时钟,小于10个时钟则保持不变。


注:机动车道的指示灯和人行道指示灯应该是配对的,当机动车道的灯为绿或者黄时,人行道的灯为红;当机动车道的灯为红时,人行道的灯为绿,为简便起见,只考虑机动车道的指示灯。

module triffic_light
    (
    input rst_n, //异位复位信号,低电平有效
        input clk, //时钟信号
        input pass_request,
    output [7:0]clock,
        output red,
    output yellow,
    output green
    );
end


解题思路

写RTL无非就是基于时序写逻辑,所以我还是先把时序单元也就是打拍寄存器做出来:

module dffre#(
  parameter WIDTH = 1
)(
  input         clk,
  input         rst_n,
  input  [WIDTH -1:0] d,
  input       en,
  output [WIDTH -1:0] q
);
reg [WIDTH -1:0]q;
always @(posedge clk or negedge rst_n)begin
  if(~rst_n)  q <= {WIDTH{1'b0}};
  else if(en) q <= d;
end
endmodule
module dffse#(
  parameter WIDTH = 1,
  parameter SET   = {WIDTH{1'b1}}
)(
  input         clk,
  input         rst_n,
  input  [WIDTH -1:0] d,
  input       en,
  output [WIDTH -1:0] q
);
reg [WIDTH -1:0]q;
always @(posedge clk or negedge rst_n)begin
  if(~rst_n)  q <= SET;
  else if(en) q <= d;
end
endmodule


分别做了两种寄存器,一种是复位归零一种是复位置位的;


接下来思考下,这三个灯其实就是寄存器的输出结果,对于绿灯而言,他的复位值应该是1(假设复位后路灯亮),在clock信号跳变为0时 && (当前为绿灯 或 当前为红灯)时,会发生信号的跳变,当前为绿灯则下一时刻绿灯变为0,当前为红灯则下一时刻绿灯变为1:

wire green_en;
wire green_d;
assign green_en = (red | green) & (cnt_q == 8'b0);
assign green_d  = ~green;
dffse #(.WIDTH(1), .SET(1'b1)) u_green(
  .clk  (clk),
  .rst_n(rst_n),
  .d    (green_d),
  .en   (green_en),
  .q    (green)
);

对于黄灯而言,在clock信号跳变为0时 && (当前为绿灯 或 当前为黄灯)时,会发生信号的跳变,当前为绿灯则下一时刻黄灯变为1,当前为黄灯则下一时刻黄灯变为0:

wire yellow_en;
wire yellow_d;
assign yellow_en = (green | yellow) & (cnt_q == 8'b0);
assign yellow_d  = ~yellow;
dffse #(.WIDTH(1), .SET(1'b0)) u_yellow(
  .clk  (clk),
  .rst_n(rst_n),
  .d    (yellow_d),
  .en   (yellow_en),
  .q    (yellow)
);


对于红灯而言,在clock信号跳变为0时 && (当前为红灯 或 当前为黄灯)时,会发生信号的跳变,当前为红灯则下一时刻黄灯变为0,当前为黄灯则下一时刻黄灯变为1:

wire red_en;
wire red_d;
assign red_en = (red | yellow) & (cnt_q == 8'b0);
assign red_d  = ~red;
dffse #(.WIDTH(1), .SET(1'b0)) u_red(
  .clk  (clk),
  .rst_n(rst_n),
  .d    (red_d),
  .en   (red_en),
  .q    (red)
);


可以看到,三个信号灯的逻辑可以说是高度一致的,区别只在于绿灯的复位值为1,一上来咱们先开绿灯。


那么接下来就是clock的逻辑了,clock的逻辑可以分成两种情况考虑:跳变和正常递减。对于跳变的情况,其实就下面这几种,注释里写的很清楚了:

wire     cnt_en;
wire         cnt_rerun_en;
wire [8 -1:0]cnt_d;
wire [8 -1:0]cnt_rerun_d;
wire [8 -1:0]cnt_q;
wire bypass = green & pass_request & (cnt_q>=10);
assign cnt_rerun_en = (cnt_q == 8'b0) | (green & bypass);
assign cnt_rerun_d  =  {8{red}}    & 8'd59 //red -> green
             | {8{yellow}} & 8'd9  //yello -> red
             | {8{green & !bypass}}  & 8'd4  //green -> yellow
             | {8{bypass}} & 8'd9; //green -> green


那么接下来就容易了,把正常递减和跳变组合在一起:

assign cnt_d = cnt_rerun_en ? cnt_rerun_d : cnt_q - 8'd1;
assign clock = cnt_q;
dffse #(.WIDTH(8), .SET(8'd59)) u_cnt(
  .clk  (clk),
  .rst_n(rst_n),
  .d    (cnt_d),
  .en   (1'b1),
  .q    (cnt_q)
);


全部代码完成!


波形验证




相关文章
|
1月前
|
前端开发 JavaScript 开发者
水墨代码:前端川的诞生——在夏日阴雨中启航
【前端川】网站于农历五月初一(2024年6月6日)上线,融合水墨画与现代前端技术,呈现独特的水墨代码美学。创建者陈川分享技术心得与实战经验,网站特色包括水墨风格界面、技术深度解析及实战案例。在夏日雨中启航,"前端川"致力于为开发者提供灵感与帮助,探索前端技术的无限可能。
65 17
|
1月前
|
应用服务中间件 开发工具 nginx
Mac M1/M2/M3 芯片环境配置以及常用软件安装-前端
Mac M1/M2/M3 芯片环境配置以及常用软件安装-前端 最近换了台新 Mac,所有的配置和软件就重新安装下,顺便写个文章。
108 1
|
28天前
|
前端开发 JavaScript 安全
高级前端开发需要知道的 25 个 JavaScript 单行代码
1. 不使用临时变量来交换变量的值 2. 对象解构,让数据访问更便捷 3. 浅克隆对象 4. 合并对象 5. 清理数组 6. 将 NodeList 转换为数组 7. 检查数组是否满足指定条件 8. 将文本复制到剪贴板 9. 删除数组重复项 10. 取两个数组的交集 11. 求数组元素的总和 12. 根据指定条件判断,是否给对象的属性赋值 13. 使用变量作为对象的键 14. 离线状态检查器 15. 离开页面弹出确认对话框 16. 对象数组,根据对象的某个key求对应值的总和 17. 将 url 问号后面的查询字符串转为对象 18. 将秒数转换为时间格式的字符串 19.
34 3
高级前端开发需要知道的 25 个 JavaScript 单行代码
|
15天前
|
前端开发 JavaScript Serverless
前端新手建议收藏的JavaScript 代码技巧
前端新手建议收藏的JavaScript 代码技巧
|
22天前
|
设计模式 前端开发 JavaScript
关于写好前端JS代码的一些建议
关于写好前端JS代码的一些建议
22 2
|
1月前
|
前端开发 JavaScript 安全
微前端架构采用 TypeScript 提升开发效率和代码可靠性
【6月更文挑战第12天】微前端架构采用 TypeScript 提升开发效率和代码可靠性。TypeScript 的类型安全防止了微前端间的类型错误,智能提示与自动补全加速开发,重构支持简化代码更新。通过定义公共接口和使用 TypeScript 编写微前端,确保通信一致性与代码质量。在构建流程中集成 TypeScript,保证构建正确性。总之,TypeScript 在微前端架构中扮演关键角色,推荐用于大型前端项目。
49 4
|
10天前
|
前端开发 应用服务中间件 nginx
安装Windows版nginx以及部署前端代码并就解决刷新出现404
安装Windows版nginx以及部署前端代码并就解决刷新出现404
20 0
|
12天前
|
前端开发 API
支付系统27-------梳理一下支付按钮,前端的代码
支付系统27-------梳理一下支付按钮,前端的代码
|
15天前
|
前端开发 JavaScript Java
高效前端开发技巧:如何优化JavaScript代码执行效率
在当今互联网应用日益复杂的背景下,前端开发者面临着更高的性能要求。本文探讨了一些提升JavaScript代码执行效率的实用技巧,包括优化循环结构、减少内存占用以及利用现代浏览器的优化能力。通过这些方法,开发者可以在保持代码清晰易读的前提下,显著提升应用程序的响应速度和用户体验。
|
25天前
|
JavaScript 前端开发
杨校老师课堂之Web前端JS类库_JQuery案例[效果图与代码齐全]
杨校老师课堂之Web前端JS类库_JQuery案例[效果图与代码齐全]
17 0